Потоки

Потоки были впервые введены в PHP 4.3.0, как инструмент для работы с файлами, сетевого обмена, сжатия данных и выполнения других операций с помощью одного общего набора функций. Выражаясь простыми понятиями, поток (stream) - это ресурс (resource), который ведет себя, как источник непрерывной последовательности данных. То есть из потока можно последовательно читать данные, равно как и записывать в него. Также возможно перемещаться (fseek()) в разные позиции внутри потока.

Обертка (wrapper) - дополнительный код, который объясняет потоку особенности работы со специфичными протоколами или кодировками. Например, обертка http знает, как преобразовать URL в HTTP/1.0-запрос для файла на удаленном сервере. Существует множество оберток, как встроенных в PHP изначально, так и дополнительных. Дополнительные обертки можно добавлять либо отдельным скриптом с помощью функции stream_wrapper_register(), либо напрямую из расширения, используя API Working with streams. Добавлять можно произвольное количество оберток, что делает возможности работы с потоками практически безграничными. Посмотреть список зарегистрированных на данный момент оберток можно с помощью функции stream_get_wrappers().

Ссылка на поток записывается в следующем виде: scheme://target

scheme(строка) - Название обертки. Например, file, http, https, ftp, ftps, compress.zlib, compress.bz2, php. На случай, если название обертки не указать, каждая функция, работающая с потоком, имеет свои умолчания (обычно это file://). target - Зависит от того, какая обертка используется. Для потоков связанных с файловой системой это обычно путь и имя файла. Для сетевых потоков это, как правило, имя хоста (зачастую с добавлением к нему пути).

Поддерживаемые протоколы и обработчики (wrappers)

Замечание: URL синтаксис, используемый для описания обработчика, может быть только вида scheme://.... Варианты синтаксиса scheme:/ и scheme: не поддерживаются.

Схема Описание
file:// Доступ к локальной файловой системе
http:// Доступ к URL-адресам по протоколу HTTP(s)
ftp:// Доступ к URL-адресам по протоколу FTP(s)
php:// Доступ к различным потокам ввода-вывода
zlib:// Сжатые потоки
data:// Схема Data (RFC 2397)
glob:// Нахождение путей, соответствующих шаблону
phar:// PHP архив
ssh2:// Secure Shell 2
rar:// RAR
ogg:// Аудио потоки
expect:// Потоки для взаимодействия с процессами

stream_wrapper_register

Регистрирует обёртку URL, реализованную в виде PHP-класса. bool stream_wrapper_register ( string $protocol , string $classname [, int $flags = 0 ] )

  • Позволяет реализовать собственные обработчики протоколов и потоков для использования со всеми другими функциями файловой системы (такими, как fopen(), fread() и т. д.).
<?php
$existed = in_array("var", stream_get_wrappers());
if ($existed) {
    stream_wrapper_unregister("var");
}
stream_wrapper_register("var", "VariableStream");
$myvar = "";

$fp = fopen("var://myvar", "r+");

fwrite($fp, "line1\n");
fwrite($fp, "line2\n");
fwrite($fp, "line3\n");

rewind($fp);
while (!feof($fp)) {
    echo fgets($fp);
}
fclose($fp);
var_dump($myvar);

if ($existed) {
    stream_wrapper_restore("var");
}
/*
line1
line2
line3
string(18) "line1
line2
line3
"
*/
?>

php://

Описание

PHP предоставляет несколько разнообразных потоков ввода-вывода, которые позволяют получить доступ к собственным потокам ввода-вывода PHP,к дескрипторам стандартного ввода, вывода и потока ошибок, к временным файловым потокам в памяти и на диске, и фильтрам, которые могут манипулировать другими файловыми ресурсами по мере их считывания или записи.

php://stdin, php://stdout и php://stderr

php://stdin, php://stdout и php://stderr позволяют получить прямой доступ к соответствующим потокам ввода или вывода процесса PHP. Поток указывает на копию файлового дескриптора, таким образом, если вы откроете php://stdin и потом закроете его, вы закроете только вашу копию дескриптора. Актуальный поток, на который ссылается STDIN остается неизменным. Обратите внимание, что PHP демонстрировал ошибочное поведение в этом отношении до версии PHP 5.2.1. Рекомендуется просто использовать константы STDIN, STDOUT и STDERR вместо ручного открытия потоков, используя эти обертки.

Поток php://stdin предназначен только для чтения, тогда как php://stdout и php://stderr предназначены только для записи.

php://input

php://input является потоком только для чтения, который позволяет вам читать необработанные данные из тела запроса. В случае POST-запросов предпочтительней использовать php://input вместо $HTTP_RAW_POST_DATA, так как этот метод не зависит от специальных php.ini директив. Кроме того, в тех случаях, где $HTTP_RAW_POST_DATA не заполняется по умолчанию, это потенциально менее затратно для памяти, чем активация директивы always_populate_raw_post_data. php://input не доступен с типом содержимого enctype="multipart/form-data".

Замечание: До версии PHP 5.6, поток, открытый с php://input может быть прочтен только один раз. Поток не поддерживает операции поиска. Тем не менее, в зависимости от реализации SAPI интерфейса, может быть возможно открыть другой поток php://input и повторить чтение. Это возможно только если тело запроса заранее сохраняется. Это типично для случая с POST-запросом, но не для других методов запросов, таких как PUT или PROPFIND.

php://output

php://output является потоком только для записи, который позволяет вам записать данные в выходной буфер аналогично как это делают функции print и echo.

Потоки ввода/вывода

Модуль CLI SAPI определяет несколько констант для потоков ввода/вывода для упрощения работы с командной строкой.

Константы, специфичные для модуля CLI

Константа Описание
STDIN Уже открытый поток ввода (stdin). Он предотвращает необходимость его открывать через fopen('php://stdin', 'r');.
STDOUT Уже открытый поток вывода (stdout). Он предотвращает необходимость его открывать через $stdout = fopen('php://stdout', 'w');
STDERR Уже открытый поток ошибок (stderr). Он предотвращает необходимость его открывать через $stderr = fopen('php://stderr', 'w');