我很想实现一个php_user_filter::filter()。所以我得知道什么是斗牛队。这似乎是我可以使用stream_bucket_*函数操作的资源。但是这些文档并没有多大帮助。我能找到的最好的例子就是stream_filter_register()中的例子。
我特别好奇这些stream_bucket_new()和stream_bucket_make_writeable()能做些什么。
更新:看起来PHP正在公开一个Apache的内部数据结构。
发布于 2015-06-30 07:56:15
啊,欢迎来到PHP手册中文档最少的部分![我打开了一份关于它的错误报告;也许这个答案有助于记录它:https://bugs.php.net/bug.php?id=69966]
斗旅
首先,最初的问题是,桶旅只是一个名为userfilter.bucket brigade的资源的名称。
将两个不同的旅作为第一个和第二个参数传递给php_user_filter::filter()。第一个旅是你读到的输入桶,第二个旅最初是空的,你给它写。
关于数据结构…的更新它实际上只是一个双链接列表,基本上是带有字符串的。但这个名字很可能是从那里偷来的;
stream_bucket_prepend() / stream_bucket_append()
stream_bucket_prepend(resource $brigade, stdClass $bucket): null
stream_bucket_append(resource $brigade, stdClass $bucket): null期望的$brigade是输出旅,也就是php_user_filter::filter()上的第二个参数。
$bucket是一个stdClass对象,类似于stream_bucket_make_writable()或stream_bucket_new()返回的对象。
这两个函数只是将传递的桶添加到旅中。
stream_bucket_new()
要解开这个函数,首先分析它的功能签名是什么:
stream_bucket_new(resource $stream, string $buffer): stdClass第一个参数是您要编写这个桶的$stream。第二个是这个新桶将包含的$buffer。
我想在这里指出,$stream参数实际上并不是很重要;它只是用来检查我们是否需要持久地分配内存,这样它才能通过请求存活下来。我只是认为当您在非持久过滤器上操作时,可以通过在这里传递一个持久流来使PHP很好地分割错误.
现在创建了一个userfilter.bucket资源,它被分配给一个名为bucket的(stdClass)对象的属性。该对象还有另外两个属性:data和datalen,它们包含缓冲区和桶的缓冲区大小。
它将返回一个stdClass,您可以将其传递给stream_bucket_prepend()和stream_bucket_append()。
stream_bucket_make_writable()
stream_bucket_make_writeable(resource $brigade): stdClass|null它将第一个桶从$brigade中移出并返回。如果$brigade被清空,它将返回null。
进一步说明
当调用php_user_filter::filter()时,调用对象filter()上的$stream属性将被设置为我们当前正在处理的流。这也是调用stream_bucket_new()时需要传递给它的流。(调用后,$stream属性将再次是未设置的。不能在例如php_user_filter::onClose()中重用它)。
还请注意,即使返回了一个$datalen属性,也不需要设置该属性,以防您在将$data属性传递给stream_bucket_prepend()或stream_bucket_append()之前更改它。
该实现要求您在返回之前读取$in桶中的所有数据(它希望这样做,或者会抛出一个警告)。
还有另一种文档欺骗我们的情况:在php_user_filter::onCreate()中,没有设置$stream属性。它将只在filter()方法调用期间设置。
一般情况下,不要使用无阻塞流的过滤器.我试过一次,结果发生了可怕的错误,…它不太可能会被修复..。
总结(例子)
让我们从最简单的例子开始:把我们得到的东西写下来。
class simple_filter extends php_user_filter {
function filter($in, $out, &$consumed, $closing) {
while ($bucket = stream_bucket_make_writeable($in)) {
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
stream_filter_register("simple", "simple_filter")这里发生的一切都是从$in桶旅获得桶,并将其放回$out桶旅中。
好了,现在试着操纵我们的输入。
class reverse_filter extends php_user_filter {
function filter($in, $out, &$consumed, $closing) {
while ($bucket = stream_bucket_make_writeable($in)) {
$consumed += $bucket->datalen;
$bucket->data = strrev($bucket->data);
stream_bucket_prepend($out, $bucket);
}
return PSFS_PASS_ON;
}
}
stream_filter_register("reverse", "reverse_filter")现在,我们注册了reverse://协议,它反转了您的字符串(这里的每个写都是反转的;写入顺序仍然保持不变)。因此,我们现在显然需要操作存储桶数据,并在这里对其进行修改。
现在,stream_bucket_new()的用例是什么?通常您只需附加到$bucket->data;是的,您甚至可以将所有数据连接到第一个桶中,但是当flush()'ing可能没有任何数据在桶旅中,并且您想发送最后一个桶时,您就需要它。
class append_filter extends php_user_filter {
public $stream;
function filter($in, $out, &$consumed, $closing) {
while ($bucket = stream_bucket_make_writeable($in)) {
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
// always append a terminating \n
if ($closing) {
$bucket = stream_bucket_new($this->stream, "\n");
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
stream_filter_register("append", "append_filter")有了这些(以及关于班级的现有文档),人们应该能够通过将所有这些强大的可能性组合到更强大的代码中来进行各种神奇的用户流过滤。
发布于 2020-07-07 03:55:38
我想我会提供一些背景资料。
首先,术语桶和旅。原来有个东西叫水桶旅..。就像一支救火的队伍.你有一串人,他们一动不动地站着,却把一桶水递给旁边的人,不断地流满了水。
另外,正如上面所指出的,PHP对桶和旅的采用可能来自于Apache桶和Brigades(http://www.apachetutor.org/dev/brigades](http://www.apachetutor.org/dev/brigades%5D),.对方法和推理作了很好的解释。
但重要的是,如果您需要对某个内容进行修改,在发送之前,这样做有许多好处,特别是当您使用桶和旅对流建模时。
https://stackoverflow.com/questions/27103269
复制相似问题