Для потомков вот что я закончил, взбив. Сам фильтр происходит от php_user_filter
, который описан в документации для stream_filter_register
:
class HookableFilter extends php_user_filter {
public function filter($in, $out, &$consumed, $closing) {
$data = '';
while ($bucket = stream_bucket_make_writeable($in)) {
$consumed += $bucket->datalen;
$data .= $bucket->data;
stream_bucket_append($out, $bucket);
}
call_user_func($this->params, $data);
return PSFS_PASS_ON;
}
}
Обратите внимание, что я использую непосредственно $this->params
в качестве обратного вызова, что делает эту функцию действительно спартанской (есть причина; см. Ниже).
Регистрация фильтра с помощью PHP:
stream_filter_register('generic.hookable', 'HookableFilter');
Присоединение фильтра к потоку:
$callback = function($data) { /* log the data */ };
stream_filter_append($stream, 'generic.hookable', STREAM_FILTER_READ, $callback);
stream_filter_append($stream, 'generic.hookable', STREAM_FILTER_WRITE, $callback);
Важно: Насколько я мог видеть, если вы подключите фильтр к обоим каналам дуплексного потока (например, один, созданный с помощью stream_socket_client
) у вашего фильтра нет возможности узнать, на каком канале он работает, когда он вызывается . Поэтому, если вам необходимо различать входящие и исходящие данные, как я, единственный вариант - прикрепить фильтр отдельно к каждому каналу. Если вы это сделаете, вы также наверняка захотите предоставить разные обратные вызовы для каждого канала (не так, как в упрощенном примере выше).