stream_filter_register() позволяет вам реализовать
ваш собственный фильтр на любом зарегистрированном потоке, используемом со всеми другими
функциями файловой системы (такими как fopen(),
fread() и т. д.).
Список параметров
filtername
Название регистрируемого фильтра.
classname
Для того, чтобы реализовать фильтр, вам нужно определить класс как расширение
php_user_filter c функциями-членами как указано ниже. При
выполнении операций чтения/записи на потоке, к которому прикреплён ваш фильтр,
PHP будет передавать данные через ваш фильтр (и через любые другие фильтры,
прикреплённые к потоку) так что данные могут быть изменены как требуется.
Вы должны реализовать методы точно как описано ниже. Иная реализация
приведёт к непредсказуемому поведению.
Этот метод вызывается каждый раз, когда данные читаются или записываются в
прикреплённый поток (такой, как с функциями fread() или fwrite()).
Переменная in - это ресурс, указывающий на последовательный поток данных
(bucket brigade), который содержит одну или больше единиц данных
(bucket), содержащих данные для фильтрации.
Переменная out - это ресурс, указывающий на второй последовательный
поток данных (bucket brigade), в который должны быть помещены ваши
модифицированные единицы данных (buckets).
Переменная consumed, которая должна
всегда передаваться по ссылке, должна быть увеличена на длину
данных, которые ваш фильтр читает и изменяет. В большинстве случаев это означает,
что вы будете увеличивать consumed на
$bucket->datalen для каждого $bucket.
Если поток в процессе закрытия (и таким образом это последний проход по цепочке
фильтров), параметр closing будет установлен в значение
TRUE. Метод filter() должен возвращать одно из трёх
предопределённых значений после завершения.
Возвращаемое значение
Смысл
PSFS_PASS_ON
Фильтр отработал успешно, данные доступны в
outbucket brigade.
PSFS_FEED_ME
Фильтр отработал успешно,однако данные не доступны для возврата. Требуется
больше данных из потока или предыдущего фильтра.
PSFS_ERR_FATAL (по умолчанию)
Фильтр получил неисправимую ошибку и не может продолжать.
boolonCreate
( void
)
Этот метод вызывается во время создания объекта класса
фильтра. Если ваш фильтр выделяет или инициализирует любые другие
ресурсы (такие, как буфер), то нужно делать это здесь. Ваша реализация
этого метода должна возвращать FALSE в случае неудачи или TRUE в случае успеха.
Когда создаётся первый экземпляр вашего фильтра и вызывается метод
yourfilter->onCreate(), будет доступно несколько свойств,
показанных в таблице ниже.
Свойство
Содержимое
FilterClass->filtername
Строка, содержащая название фильтра, экземпляр которого был создан.
Фильтры могут быть зарегистрированы под разными именами или шаблонами.
Используйте это свойство для того, чтобы определить какое название было
использовано.
Ресурс фильтруемого потока. Может быть доступен только во время вызовов
filter(), когда параметр closing
установлен в значение FALSE.
voidonClose
( void
)
Этот метод вызывается во время завершения фильтра (обычно это происходит во время
завершения потока), и выполняется после того, как был
вызван метод flush. Если любые ресурсы были выделены или
инициализированы во время вызова метода onCreate(), то
здесь следует их уничтожить или избавиться от них.
Возвращаемые значения
Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.
stream_filter_register() будет возвращать FALSE если
фильтр с именем filtername уже определён.
Примеры
Пример #1 Фильтр для перевода букв в верхний регистр в потоке foo-bar.txt
Пример ниже реализует фильтр с названием strtoupper
на файловом потоке foo-bar.txt, который будет переводить
в заглавные все буквы, которые пишутся/читаются из этого потока.
<?php
/* Определяем наш класс фильтра */ class strtoupper_filter extends php_user_filter { function filter($in, $out, &$consumed, $closing) { while ($bucket = stream_bucket_make_writeable($in)) { $bucket->data = strtoupper($bucket->data); $consumed += $bucket->datalen; stream_bucket_append($out, $bucket); } return PSFS_PASS_ON; } }
/* Регистрируем наш фильтр в PHP */ stream_filter_register("strtoupper", "strtoupper_filter") or die("Не удалось зарегистрировать фильтр");
$fp = fopen("foo-bar.txt", "w");
/* Присоединяем зарегистрированный фильтр к только что открытому потоку */ stream_filter_append($fp, "strtoupper");
fwrite($fp, "Line1\n"); fwrite($fp, "Word - 2\n"); fwrite($fp, "Easy As 123\n");
fclose($fp);
/* Читаем содержимое снова */ readfile("foo-bar.txt");
?>
Результат выполнения данного примера:
LINE1
WORD - 2
EASY AS 123
Пример #2 Регистрация стандартного фильтра, соответствующего множественным именам фильтров.
<?php
/* Определяем наш класс фильтра */ class string_filter extends php_user_filter { var $mode;
function filter($in, $out, &$consumed, $closing) { while ($bucket = stream_bucket_make_writeable($in)) { if ($this->mode == 1) { $bucket->data = strtoupper($bucket->data); } elseif ($this->mode == 0) { $bucket->data = strtolower($bucket->data); }
function onCreate() { if ($this->filtername == 'str.toupper') { $this->mode = 1; } elseif ($this->filtername == 'str.tolower') { $this->mode = 0; } else { /* Был вызван какой-то другой фильтр str.*, возвращаем ошибку, чтобы PHP мог продолжить его поиск */ return false; }
return true; } }
/* Регистрируем наш фильтр в PHP */ stream_filter_register("str.*", "string_filter") or die("Не удалось зарегистрировать фильтр");
$fp = fopen("foo-bar.txt", "w");
/* Присоединяем зарегистрированный фильтр к только что открытому потоку Мы могли бы использовать здесь str.tolower */ stream_filter_append($fp, "str.toupper");
fwrite($fp, "Line1\n"); fwrite($fp, "Word - 2\n"); fwrite($fp, "Easy As 123\n");
fclose($fp);
/* Читаем содержимое снова */ readfile("foo-bar.txt"); ?>