Что такое потоки
В программировании постоянно приходиться работать с различными ресурсами: файлами
, сокетами
, http-соединениями
. У всех есть некий интерфейс доступа, часто несовместимый друг с другом, чтобы устранить данные несоответствия и унифицировать работу с различными источниками данных, начиная с PHP 4.3 были придуманы PHP Streams потоки
.
Поток, это передача данных между местами. В данном контексте, местом может быть - файл, ZIP-архив, соединение и даже процесс через командную строку.
Вы должны понимать разницу между открытием файла и открытием веб-страницы, у них обоих есть контент, но это два совершенно разных типа потоковых данных, поэтому для них требуются разные протоколы. Например, мы можем открыть веб-страницу, подключившись к удаленным веб-серверам с помощью HTTP
, HTTPS
, SSL
. Эти протоколы называются потоковыми оболочками, они предоставляют уникальный интерфейс.
Поток stream
, это ресурс resource
который ведет себя, как источник непрерывной последовательности данных. То есть из потока можно последовательно читать данные, равно как и записывать в него. Также возможно перемещаться в разные позиции внутри потока.
Обертка wrapper
, дополнительный код который объясняет потоку особенности работы со специфичными протоколами или кодировками. Например, обертка http
знает, как преобразовать URL
в HTTP/1.0-запрос
для файла на удаленном сервере. Существует множество оберток, как встроенных в PHP изначально, так и дополнительных.
Схема формирования потока
Каждый поток формируется из схемы
и цели
, в приведенном ниже формате:
схема://цель
Схема
это название обертки. Например - file
, http
, https
, ftp
, ftps
, compress.zlib
, compress.bz2
, php
. На случай, если название обертки не указать, каждая функция, работающая с потоком, имеет свои умолчания, обычно это file://
.
Цель
зависит от того, какая обертка используется. Для потоков связанных с файловой системой это обычно путь и имя файла. Для сетевых потоков это, как правило, имя хоста с добавлением к нему пути.
Поддерживаемые схемы
file://
доступ к локальной файловой системеhttp://
доступ к URL-адресам по протоколу HTTP(s)ftp://
доступ к URL-адресам по протоколу FTP(s)php://
доступ к различным потокам ввода-выводаzlib://
сжатые потокиdata://
схема Data (RFC 2397)glob://
нахождение путей, соответствующих шаблонуphar://
PHP архивssh2://
Secure Shell 2rar://
RARogg://
аудио потокиexpect://
потоки для взаимодействия с процессами
Потоки PHP
PHP предоставляет несколько разнообразных потоков ввода-вывода, которые позволяют получить доступ к собственным потокам ввода-вывода PHP,к дескрипторам стандартного ввода, вывода и потока ошибок, к временным файловым потокам в памяти и на диске, и фильтрам, которые могут манипулировать другими файловыми ресурсами по мере их считывания или записи.
Потоки PHP имеют функции, которые помогают разработчикам управлять различными ресурсами:
fopen()
fwrite()
fgets()
file_get_contents()
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
.
Дополнительные обертки
Дополнительные обертки можно добавлять либо отдельным скриптом с помощью функции stream_wrapper_register()
, либо напрямую из расширения, используя API Working with streams
. Добавлять можно произвольное количество оберток, что делает возможности работы с потоками практически безграничными. Посмотреть список зарегистрированных на данный момент оберток можно с помощью функции stream_get_wrappers()
.
stream_wrapper_register()
регистрирует обёртку URL, реализованную в виде PHP-класса, bool stream_wrapper_register ( string $protocol , string $classname [, int $flags = 0 ] )
.
Позволяет реализовать собственные обработчики протоколов и потоков для использования со всеми другими функциями файловой системы, такими как fopen()
, fread()
.
<?
$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
"
*/
Модуль CLI SAPI
Модуль CLI SAPI
определяет несколько констант для потоков ввода/вывода для упрощения работы с командной строкой.
Константы, специфичные для модуля CLI SAPI
:
STDIN
уже открытый поток вводаstdin
. Он предотвращает необходимость его открывать черезfopen('php://stdin', 'r');
STDOUT
уже открытый поток выводаstdout
. Он предотвращает необходимость его открывать через$stdout = fopen('php://stdout', 'w');
STDERR
уже открытый поток ошибокstderr
. Он предотвращает необходимость его открывать через$stderr = fopen('php://stderr', 'w');