Потоки — это ресурсы, предоставляемые PHP, которые мы часто используем прозрачно, но которые также могут быть очень мощными инструментами. Научившись использовать их возможности, мы можем вывести наши приложения на более высокий уровень.
В руководстве по PHP есть отличное описание потоков:
Потоки были введены в PHP 4.3.0 как способ обобщения файлов, сети, сжатия данных и других операций, которые имеют общий набор функций и применений. В своем простейшем определении поток — это объект ресурса, который демонстрирует поведение в потоке. То есть он может считываться или записываться линейным образом и может быть способен выполнять
fseek()
в произвольных местах в потоке.
Каждый поток имеет оболочку реализации, которая имеет дополнительный код, необходимый для обработки конкретного протокола или кодирования. PHP предоставляет несколько встроенных оболочек, и мы можем легко создавать и регистрировать собственные. Мы можем даже изменить или улучшить поведение оболочек, используя контексты и фильтры.
Основы Stream
На поток ссылаются как <scheme>://<target>
. <scheme>
— это имя оболочки, а <target>
зависит от синтаксиса оболочки.
Оболочкой по умолчанию является file://
что означает, что мы используем поток каждый раз, когда получаем доступ к файловой системе. Мы можем либо написать readfile('/path/to/somefile.txt')
например, либо readfile('file:///path/to/somefile.txt')
и получить тот же результат. Если вместо этого мы используем readfile('http://google.com/')
то мы говорим PHP использовать обертку потока HTTP.
Как я уже говорил, PHP предоставляет несколько встроенных оболочек , протоколов и фильтров. Чтобы узнать, какие оболочки установлены на нашей машине, мы можем использовать:
<?php print_r(stream_get_transports()); print_r(stream_get_wrappers()); print_r(stream_get_filters());
Моя установка выдает следующее:
массив ( [0] => tcp [1] => UDP [2] => unix [3] => UDG [4] => ssl [5] => sslv3 [6] => sslv2 [7] => TLS ) массив ( [0] => https [1] => ftps [2] => compress.zlib [3] => compress.bzip2 [4] => php [5] => файл [6] => шар [7] => данные [8] => http [9] => ftp [10] => почтовый индекс [11] => phar ) массив ( [0] => zlib. * [1] => bzip2. * [2] => convert.iconv. * [3] => string.rot13 [4] => string.toupper [5] => string.tolower [6] => string.strip_tags [7] => конвертировать. * [8] => потребляется [9] => Дечанк [10] => mcrypt. * [11] => mdecrypt. * )
Хороший сет, тебе не кажется?
Кроме того, мы можем написать или использовать сторонние потоки для Amazon S3 , MS Excel , Google Storage , Dropbox и даже Twitter .
Php: // Wrapper
PHP имеет собственную оболочку для доступа к потокам ввода / вывода языка. Существуют базовые оболочки php://stdin
, php://stdout
и php://stderr
которые отображают ресурсы ввода-вывода по умолчанию, и у нас есть php://input
, доступный только для чтения, с необработанным тело запроса POST. Это удобно, когда мы имеем дело с удаленными службами, которые помещают полезные данные в тело запроса POST.
Давайте сделаем быстрый тест с использованием cURL:
curl -d "Hello World" -d "foo = bar & name = John" http: //localhost/dev/streams/php_input.php
Результат print_r($_POST)
в отвечающем скрипте PHP будет:
массив ( [foo] => бар [name] => Джон )
Обратите внимание, что первый пакет данных недоступен из массива $_POST
. Но если вместо этого мы используем readfile('php://input')
мы получим:
Hello World & foo = bar & name = Джон
В PHP 5.1 были представлены оболочки потока php://memory
и php://temp
которые используются для чтения и записи временных данных. Как видно из названий, данные хранятся соответственно в памяти или во временном файле, управляемом базовой системой.
Также есть php://filter
, мета-оболочка, предназначенная для применения фильтров при открытии потока с помощью функций вроде readfile()
или file_get_contents()
/ stream_get_contents()
.
<?php // Write encoded data file_put_contents("php://filter/write=string.rot13/resource=file:///path/to/somefile.txt","Hello World"); // Read data and encode/decode readfile("php://filter/read=string.toupper|string.rot13/resource=http://www.google.com");
В первом примере используется фильтр для кодирования данных, записанных на диск, а во втором — два каскадных фильтра, считывающих данные с удаленного URL-адреса. Результат может быть от очень базового до очень мощного в наших приложениях.
Потоковые контексты
Контекст — это специфический для потока набор параметров или опций, которые могут изменять и улучшать поведение наших оболочек. Обычный контекст использования — это модификация оболочки HTTP. Это позволяет нам избежать использования cURL для простых сетевых операций.
<?php $opts = array( 'http'=>array( 'method'=>"POST", 'header'=> "Auth: SecretAuthTokenrn" . "Content-type: application/x-www-form-urlencodedrn" . "Content-length: " . strlen("Hello World"), 'content' => 'Hello World' ) ); $default = stream_context_get_default($opts); readfile('http://localhost/dev/streams/php_input.php');
Сначала мы определяем наш массив параметров, массив массивов в формате $array['wrapper']['option_name']
(доступные параметры контекста варьируются в зависимости от конкретной оболочки). Затем мы вызываем stream_context_get_default()
которая возвращает контекст по умолчанию и принимает необязательный массив параметров для применения. Оператор readfile()
использует эти параметры для извлечения содержимого.
В этом примере содержимое отправляется внутри тела запроса, поэтому удаленный скрипт будет использовать php://input
для его чтения. Мы можем получить доступ к заголовкам с помощью apache_request_headers()
и получить:
массив ( [Host] => localhost [Auth] => SecretAuthToken [Content-type] => application / x-www-form-urlencoded [Content-length] => 11 )
Мы изменили параметры контекста по умолчанию, но мы можем создать альтернативные контексты для отдельного использования.
<?php $alternative = stream_context_create($other_opts); readfile('http://localhost/dev/streams/php_input.php', false, $alternative);
Вывод
Как мы можем использовать силу потоков в реальном мире? И куда мы можем пойти отсюда? Как мы уже видели, потоки совместно используют некоторые или все функции, связанные с файловой системой, поэтому первое, что приходит мне в голову, это серия виртуальных оболочек файловой системы, которые можно использовать с провайдерами PaaS, такими как Heroku или AppFog, у которых нет настоящей файловой системы. , Без особых усилий мы можем перенести наши приложения из стандартных хостинговых служб в эти облачные сервисы и пользоваться преимуществами. Также — и я покажу в следующей статье — мы можем создавать собственные оболочки и фильтры для наших приложений, которые реализуют пользовательские форматы файлов и кодировку.