Что такое ведерная бригада?

Я бы очень хотел реализовать php_user_filter::filter(). Но поэтому я должен знать, что ведерная бригада является. Кажется, это ресурс, которым я могу управлять с stream_bucket_* функции. Но документация не очень полезна. Лучшее, что я мог найти, это те примеры в stream_filter_register().

Я особенно любопытен, что это stream_bucket_new() а также stream_bucket_make_writeable() сможет сделать.


Обновление: похоже, что PHP выставляет внутренняя структура данных Apache.

23

Решение

Ах, добро пожаловать в наименее документированные части руководства по PHP! [Я открыл сообщение об ошибке об этом; возможно этот ответ будет полезен для документирования: https://bugs.php.net/bug.php?id=69966]

Чтобы начать с вашего первоначального вопроса, бригада ведра — это просто имя ресурса, названного userfilter.bucket brigade,

Вы передали две разные бригады в качестве первого и второго параметров php_user_filter::filter(), Первая бригада — это входные сегменты, из которых вы читаете, вторая бригада изначально пуста; ты пишешь в него.

Что касается вашего обновления о структуре данных … Это на самом деле просто двусвязный список со строками. Но вполне может быть, что имя было украдено оттуда 😉

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(resource $stream, string $buffer): stdClass

Первый аргумент $stream ты пишешь это ведро. Второе $buffer это новое ведро будет содержать.

[Я хотел бы отметить, что $stream параметр на самом деле не очень значительный; он просто используется для проверки того, нужно ли нам постоянно выделять память, чтобы она сохранялась через запросы. Я просто предполагаю, что вы можете сделать PHP красиво segfault, передавая здесь постоянный поток при работе с непостоянным фильтром …]

Теперь есть userfilter.bucket создан ресурс, который присваивается свойству (stdClass) объект с именем bucket,
Этот объект также имеет два других свойства: data а также datalen, которые содержат буфер и размер буфера этого сегмента.

Это вернет вам stdClass который вы можете передать stream_bucket_prepend() а также stream_bucket_append(),

stream_bucket_make_writeable(resource $brigade): stdClass|null

Это сдвигает первое ведро из $brigade и возвращает его. Если $brigade был опустошен, он возвращается null,

когда php_user_filter::filter() называется, $stream недвижимость на объекте filter() Будет вызван поток, над которым мы сейчас работаем. Это также поток, который нужно передать stream_bucket_new() при звонке (The $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()Возможно, в бригаде ведра ничего нет, и вы хотите отправить последнее ведро, тогда вам это нужно.

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")

С этим (и существующая документация о php_user_filter учебный класс), нужно уметь выполнять все виды волшебной фильтрации пользовательских потоков, объединяя все эти мощные возможности в еще более сильный код.

33

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]