0

我正在尝试捕获回调函数中发生的 http 请求:

// Code omitted
public function capture($fn)
{
  // start http capture
  $fn();
  // end http capture and stores the capture in a variable
}


//example usage
$request->capture(function(){
  do_some_http_request_with_curl_or_whatever_you_want();
});

我已经用 ob_start() 和 php 包装器尝试了各种东西......但没有任何效果,非常感谢帮助!

4

2 回答 2

0

由于回调有很多可能的方法来处理它,因此不可能捕获任何任意 HTTP 请求:

  • 带有 URL 包装器的高级函数(例如file_get_contents
  • 更底层的方法(例如流、套接字)
  • 自定义 PHP 扩展(例如 curl)

这些方法中的每一种都有(或根本没有!)不同的方法来让你挂钩到请求的机制中,所以除非你想要针对的所有机制都支持挂钩并且回调积极地与你合作,否则没有办法去做这个。

于 2012-07-01T11:40:28.663 回答
0

如果您只需要支持流包装器(即不使用套接字函数),则应该可以取消注册http流包装器并添加您自己的拦截调用然后转发它们。这是一个例子:

<?php

class HttpCaptureStream
{
    private $fd;
    public static $captured;

    public static function reset()
    {
        static::$captured = array();
    }

    public function stream_open($path, $mode, $options, &$opened_path)
    {
        static::$captured[] = $path;

        $this->fd = $this->restored(function () use ($path, $mode) {
            return fopen($path, $mode);
        });

        return (bool) $this->fd;
    }

    public function stream_read($count)
    {
        return fread($this->fd, $count);
    }

    public function stream_write($data)
    {
        return fwrite($this->fd, $data);
    }

    public function stream_tell()
    {
        return ftell($this->fd);
    }

    public function stream_eof()
    {
        return feof($this->fd);
    }

    public function stream_seek($offset, $whence)
    {
        return fseek($this->fd, $offset, $whence);
    }

    public function stream_stat()
    {
        return fstat($this->fd);
    }

    protected function restored($f)
    {
        stream_wrapper_restore('http');

        $result = $f();

        stream_wrapper_unregister('http');
        stream_wrapper_register('http', __CLASS__);

        return $result;
    }
}

function capture($f) {
    stream_wrapper_unregister('http');

    stream_wrapper_register('http', 'HttpCaptureStream');
    HttpCaptureStream::reset();

    $f();

    stream_wrapper_restore('http');
}

capture(function () {
    file_get_contents('http://google.com');
    file_get_contents('http://stackoverflow.com');

    var_dump(HttpCaptureStream::$captured);
});
于 2012-07-01T16:54:55.960 回答