使用自定义流包装器作为PHP的http://流包装器的测试存根
我正在编写一个自定义流包装器,用作使用内置http://流包装器的HTTP客户端类的单元测试中的存根.
具体来说,我需要通过调用自定义流包装器创建的流上的stream_get_meta_data来控制’wrapper_data’键中返回的值.不幸的是,关于自定义流包装器的文档很糟糕,API似乎不直观. 自定义包装器中的哪个方法控制meta wrapper_data响应? 使用底部的类我只能在var_dump(stream_get_meta_data($stream))时得到以下结果;在使用自定义包装器创建的流上… array(10) { 'wrapper_data' => class CustomHttpStreamWrapper#5 (3) { public $context => resource(13) of type (stream-context) public $position => int(0) public $bodyData => string(14) "test body data" } ... 但我需要哄骗包装器在元数据检索上产生类似下面的内容,这样我就可以测试客户端类对真实http://流包装器返回的数据的解析… array(10) { 'wrapper_data' => Array( [0] => HTTP/1.1 200 OK [1] => Content-Length: 438 ) ... 这是我目前用于自定义包装器的代码: class CustomHttpStreamWrapper { public $context; public $position = 0; public $bodyData = 'test body data'; public function stream_open($path,$mode,$options,&$opened_path) { return true; } public function stream_read($count) { $this->position += strlen($this->bodyData); if ($this->position > strlen($this->bodyData)) { return false; } return $this->bodyData; } public function stream_eof() { return $this->position >= strlen($this->bodyData); } public function stream_stat() { return array('wrapper_data' => array('test')); } public function stream_tell() { return $this->position; } }
stream_get_meta_data在
ext/standard/streamfunc.c中实现.相关部分是
if (stream->wrapperdata) { MAKE_STD_ZVAL(newval); MAKE_COPY_ZVAL(&stream->wrapperdata,newval); add_assoc_zval(return_value,"wrapper_data",newval); } 即,任何zval流 – > wrapperdata保持被$retval [“wrapper_data”]“复制”/引用. /* set wrapper data to be a reference to our object */ stream->wrapperdata = us->object; us-> object“is”已为流实例化的自定义包装器的实例.我还没有找到一种方法来影响来自其他用户空间脚本的stream-> wrapperdata. <?php function test() { stream_wrapper_register("mock","CustomHttpStreamWrapper") or die("Failed to register protocol"); $fp = fopen("mock://myvar","r+"); $md = stream_get_meta_data($fp); echo "Iterator / IteratorAggregaten"; foreach($md['wrapper_data'] as $e) { echo $e,"n"; } echo "nArrayAccessn"; echo $md['wrapper_data'][0],"n"; echo "nvar_dumpn"; echo var_dump($md['wrapper_data']); } class CustomHttpStreamWrapper implements IteratorAggregate,ArrayAccess { public $context; public $position = 0; public $bodyData = 'test body data'; protected $foo = array('HTTP/1.1 200 OK','Content-Length: 438','foo: bar','ham: eggs'); /* IteratorAggregate */ public function getIterator() { return new ArrayIterator($this->foo); } /* ArrayAccess */ public function offsetExists($offset) { return array_key_exists($offset,$this->foo); } public function offsetGet($offset ) { return $this->foo[$offset]; } public function offsetSet($offset,$value) { $this->foo[$offset] = $value; } public function offsetUnset($offset) { unset($this->foo[$offset]); } /* StreamWrapper */ public function stream_open($path,&$opened_path) { return true; } public function stream_read($count) { $this->position += strlen($this->bodyData); if ($this->position > strlen($this->bodyData)) { return false; } return $this->bodyData; } public function stream_eof() { return $this->position >= strlen($this->bodyData); } public function stream_stat() { return array('wrapper_data' => array('test')); } public function stream_tell() { return $this->position; } } test(); 版画 Iterator / IteratorAggregate HTTP/1.1 200 OK Content-Length: 438 foo: bar ham: eggs ArrayAccess HTTP/1.1 200 OK var_dump object(CustomHttpStreamWrapper)#1 (4) { ["context"]=> resource(5) of type (stream-context) ["position"]=> int(0) ["bodyData"]=> string(14) "test body data" ["foo":protected]=> array(4) { [0]=> string(15) "HTTP/1.1 200 OK" [1]=> string(19) "Content-Length: 438" [2]=> string(8) "foo: bar" [3]=> string(9) "ham: eggs" } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |