Understanding Streams in PHP and phpstreams
Streams is a powerful tool provided by PHP. We often use it inadvertently. If it is used properly, PHP productivity will be greatly improved. With the power of Streams, applications will be elevated to a new level.
The following is a description of Streams in the PHP manual:
Streams was introduced in PHP 4.3.0. It is used to operate files in a unified way, such as files, networks, and data compression, provides a set of common function interfaces for these file operations. In short, a stream is a resource object with streaming behaviors. That is to say, we can use a linear method to read and write streams. You can also use fseek () to jump to any position in the stream.
Each Streams object has a packaging class. You can add Code related to special protocols and codes to the packaging. PHP has built-in some common packaging classes. We can also create and register custom packaging classes. We can even use the existing context and filter to modify and enhance the packaging class.
Basic Stream knowledge
Stream can be referenced by <scheme >:/// <target>. <Scheme> is the name of the packaging class, and the content in <target> is specified by the packaging class syntax. the syntax of different packaging classes varies.
The default PHP packaging class is file: //. That is to say, when we access the file system, we actually use a stream. We can read the content in the file in the following two ways: readfile ('/path/to/somefile.txt') or readfile ('file: /// path/to/somefile.txt '). The two methods are equivalent. If you use readfile ('HTTP: // google.com/'), PHP selects the http stream packaging class for operations.
As mentioned above, PHP provides many built-in conversion classes, protocols and filters. You can query the packages supported by the local machine as described below:
1234 |
<?php print_r(stream_get_transports()); print_r(stream_get_wrappers()); print_r(stream_get_filters()); |
The output result on my machine is:
1234567891011121314151617181920212223242526272829303132333435363738394041 |
Array ( [0] => tcp [1] => udp [2] => unix [3] => udg [4] => ssl [5] => sslv3 [6] => sslv2 [7] => tls ) Array ( [0] => https [1] => ftps [2] => compress.zlib [3] => compress.bzip2 [4] => php [5] => file [6] => glob [7] => data [8] => http [9] => ftp [10] => zip [11] => phar ) Array ( [0] => zlib.* [1] => bzip2.* [2] => convert.iconv.* [3] => string.rot13 [4] => string.toupper [5] => string.tolower [6] => string. strip_tags [7] => convert.* [8] => consumed [9] => dechunk [10] => mcrypt.* [11] => mdecrypt.* ) |
Many features are provided. Does it look good?
In addition to the built-in Stream above, we can also write more third-party streams for Amazon S3, MS Excel, Google Storage, Dropbox and even Twitter.
Php: // packaging class
PHP has built-in packaging classes for processing I/O stream. Php: // stdin, php: // stdout, and php: // stderr, these three streams are mapped to the default I/O resources respectively. PHP also provides php: // input, which can be used to access the raw body in the POST request in read-only mode. This is a very useful feature, especially when processing remote services that embed data loads into POST requests.
Here we will use the cURL tool for a simple test:
1 |
curl -d "Hello World" -d "foo=bar&name=John" <a href= "http://localhost/dev/streams/php_input.php" >http://localhost/dev/streams/php_input.php</a> |
The test results of using print_r ($ _ POST) in a PHP script are as follows:
12345 |
Array ( [foo] => bar [name] => John ) |
We note that $ _ POST array cannot access the first item of data. However, if we use readfile ('php: // input'), the results will be different:
1 |
Hello World&foo=bar&name=John |
PHP 5.1 adds the php: // memory and php: // tempstream conversion classes to read and write temporary data. As the packaging class name implies, the data is stored in the memory or temporary files of the underlying system.
Php: // filter is a meta-packaging class used to add the filter function for stream. When you use readfile () or file_get_contents ()/stream_get_contents () to open stream, the filter will be enabled. The following is an example:
123456 |
<?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" ); |
In the first example, a filter is used to encode the data stored on the disk. In the second example, two cascade filters are used to read data from the remote URL. Using filters can provide extremely powerful functions for your applications.
Stream Context
Context is a set of stream-related parameters or options. You can use context to modify or enhance the behavior of the packaging class. For example, using context to modify the HTTP wrapper is a common application scenario. In this way, you can complete some simple network operations without using the cURL tool. The following is an example:
123456789101112 |
<?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' ); |
First, define an options array, which is a two-dimensional array. You can access the parameters in the form of $ array ['wrapper'] ['option _ name. (Note that the options of context in each packaging class are different ). Call stream_context_get_default () to set these options. stream_context_get_default () will return the default context as the result. After the settings are complete, call readfile () to apply the context you just set to capture the content.
In the above example, the content is embedded into the request body, so that remote scripts can use php: // input to read the content. At the same time, we can also use apache_request_headers () to obtain the request header, as shown below:
1234567 |
Array ( [Host] => localhost [Auth] => SecretAuthToken [Content-type] => application/x-www-form-urlencoded [Content-length] => 11 ) |
In the above example, we modify the default context parameter. Of course, we can also create a new context for alternate use.
123 |
<?php $alternative = stream_context_create( $other_opts ); readfile( 'http://localhost/dev/streams/php_input.php' , false, $alternative ); |
Conclusion
How can we control the power of stream in the real world? What are the practical benefits of using stream for our programs? As described above, stream abstracts all file system-related functions, so the first application scenario I thought of was to use the packaging class of the Virtual File System to access the services provided by the PaaS vendor. For example, to access HeroKu or AppFog, they do not actually have a real file system. Stream can be transplanted to the cloud as long as our application is slightly modified. Next -- in my next article -- I will introduce how to write custom packaging classes to perform operations on special file formats and encoding formats.