值得注意的是,由 yannick at gmail 定义的接口不应始终由流包装器类实现,因为如果类没有使用某些方法,则不应实现这些方法(根据手册)。
具体来说,如果包装器没有使用 mkdir、rename、rmdir 和 unlink 这些方法,则“不应定义”这些方法。结果是不会返回适当的错误消息。
如果实现了该接口,则将无法灵活地不实现这些方法。
不是要学术性,但对我来说很有用。
(PHP 4 >= 4.3.2, PHP 5, PHP 7, PHP 8)
允许您实现自己的协议处理程序和流,以便与所有其他文件系统函数(如 fopen()、fread() 等)一起使用。
注意:
这不是一个真正的类,而是一个定义其自身协议的类的原型。
注意:
以与此处描述的不同方式实现方法会导致未定义的行为。
当流函数尝试访问与它关联的协议时,将初始化该类的实例。
当前的 上下文,如果没有将上下文传递给调用函数,则为 null
。
使用 stream_context_get_options() 解析上下文。
注意:
此属性必须为 public,以便 PHP 可以使用实际的上下文资源填充它。
值得注意的是,由 yannick at gmail 定义的接口不应始终由流包装器类实现,因为如果类没有使用某些方法,则不应实现这些方法(根据手册)。
具体来说,如果包装器没有使用 mkdir、rename、rmdir 和 unlink 这些方法,则“不应定义”这些方法。结果是不会返回适当的错误消息。
如果实现了该接口,则将无法灵活地不实现这些方法。
不是要学术性,但对我来说很有用。
这些方法不需要,你只需要实现它们的一部分:目录、文件等等。
例如,“glob://”支持最少的语法,glob() 功能更强大,你可以替换/扩展本机包装器:检查表格中的选项 https://php.net/manual/ru/wrappers.glob,你只需要创建只包含“dir_...dir”方法的包装器。有关更多信息,请参阅 https://php.net/manual/en/class.globiterator.php#125220
这是一个非常简单的流包装器,它会为读取调用您的回调函数
<?php
class CallbackUrl
{
const WRAPPER_NAME = 'callback';
public $context;
private $_cb;
private $_eof = false;
private static $_isRegistered = false;
public static function getContext($cb)
{
if (!self::$_isRegistered) {
stream_wrapper_register(self::WRAPPER_NAME, get_class());
self::$_isRegistered = true;
}
if (!is_callable($cb)) return false;
return stream_context_create(array(self::WRAPPER_NAME => array('cb' => $cb)));
}
public function stream_open($path, $mode, $options, &$opened_path)
{
if (!preg_match('/^r[bt]?$/', $mode) || !$this->context) return false;
$opt = stream_context_get_options($this->context);
if (!is_array($opt[self::WRAPPER_NAME]) ||
!isset($opt[self::WRAPPER_NAME]['cb']) ||
!is_callable($opt[self::WRAPPER_NAME]['cb'])) return false;
$this->_cb = $opt[self::WRAPPER_NAME]['cb'];
return true;
}
public function stream_read($count)
{
if ($this->_eof || !$count) return '';
if (($s = call_user_func($this->_cb, $count)) == '') $this->_eof = true;
return $s;
}
public function stream_eof()
{
return $this->_eof;
}
}
class Test {
private $_s;
public function __construct($s)
{
$this->_s = $s;
}
public function read($count) {
return fread($this->_s, $count);
}
}
$t = new Test(fopen('/etc/services', 'r'));
$fd = fopen('callback://', 'r', false, CallbackUrl::getContext(array($t, 'read')));
while(($buf = fread($fd, 128)) != '') {
print $buf;
}
?>
PHP 包装器接口
<?php
interface WrapperInterface
{
/**
* 资源上下文
*
* @var resource
*/
//public $context;
/**
* 构造函数
*
*/
public function __construct();
/**
*
*
* @return bool
*/
public function dir_closedir();
/**
* 进入描述
*
* @param string $path
* @param int $options
* @return bool
*/
public function dir_opendir($path , $options);
/**
* 进入描述
*
* @return string
*/
public function dir_readdir();
/**
* 进入描述
*
* @return bool
*/
public function dir_rewinddir();
/**
* 进入描述
*
* @param string $path
* @param int $mode
* @param int $options
* @return bool
*/
public function mkdir($path , $mode , $options);
/**
* 进入描述
*
* @param string $path_from
* @param string $path_to
* @return bool
*/
public function rename($path_from , $path_to);
/**
* 进入描述
*
* @param string $path
* @param int $options
* @return bool
*/
public function rmdir($path , $options);
/**
* 进入描述
*
* @param int $cast_as
* @return resource
*/
public function stream_cast($cast_as);
/**
* 进入描述
*
*/
public function stream_close();
/**
* 进入描述
*
* @return bool
*/
public function stream_eof();
/**
* 进入描述
*
* @return bool
*/
public function stream_flush();
/**
* 进入描述
*
* @param mode $operation
* @return bool
*/
public function stream_lock($operation);
/**
* 进入描述
*
* @param string $path
* @param string $mode
* @param int $options
* @param string &$opened_path
* @return bool
*/
public function stream_open($path , $mode , $options , &$opened_path);
/**
* 进入描述
*
* @param int $count
* @return string
*/
public function stream_read($count);
/**
* 进入描述
*
* @param int $offset
* @param int $whence = SEEK_SET
* @return bool
*/
public function stream_seek($offset , $whence = SEEK_SET);
/**
* 进入描述
*
* @param int $option
* @param int $arg1
* @param int $arg2
* @return bool
*/
public function stream_set_option($option , $arg1 , $arg2);
/**
* 进入描述
*
* @return array
*/
public function stream_stat();
/**
* 进入描述
*
* @return int
*/
public function stream_tell();
/**
* 进入描述
*
* @param string $data
* @return int
*/
public function stream_write($data);
/**
* 进入描述
*
* @param string $path
* @return bool
*/
public function unlink($path);
/**
* 进入描述
*
* @param string $path
* @param int $flags
* @return array
*/
public function url_stat($path , $flags);
}
?>