This post covers the Streams section of the Input/Output chapter when studying for the Zend PHP 7 Certification.
Streams are a way of generalising file, network, data compression, and other operations which share a common set of functions and uses.
A stream is usually referenced as scheme://target where scheme is the wrapper or protocol being used. target is usually a file name or a URL, but it depends on the scheme defined.
A list of supported protocols and wrappers can be seen below.
file:// — Accessing local filesystemhttp:// — Accessing HTTP(s) URLsftp:// — Accessing FTP(s) URLsphp:// — Accessing various I/O streamszlib:// — Compression Streamsdata:// — Data (RFC 2397)glob:// — Find pathnames matching patternphar:// — PHP Archivessh2:// — Secure Shell 2rar:// — RARogg:// — Audio streamsexpect:// — Process Interaction StreamsThe most common form of reading a file probably involves using the file_get_contents() function where the file name is passed in as an argument.
<?php
$localfile = file_get_contents("/home/bar/foo.txt");
However streams can also be specified. For example, the below is identical to the above except that it used the file:// protocol.
$localfile = file_get_contents("file:///home/bar/foo.txt");
Other example of protocols in use can be seen below:
/* Read remote file from www.example.com using HTTP */
$httpfile = file_get_contents("http://www.example.com/foo.txt");
/* Read remote file from www.example.com using HTTPS */
$httpsfile = file_get_contents("https://www.example.com/foo.txt");
/* Read remote file from ftp.example.com using FTP */
$ftpfile = file_get_contents("ftp://user:pass@ftp.example.com/foo.txt");
/* Read remote file from ftp.example.com using FTPS */
$ftpsfile = file_get_contents("ftps://user:pass@ftp.example.com/foo.txt");
PHP gives you the ability to create custom stream wrappers by using stream_wrapper_register() function. This function takes three parameters:
STREAM_IS_URL if protocol is a URL protocol. Default is 0, local stream.
<?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+");
Stream contexts are a set of parameters and wrapper options that can modify a stream’s behaviour.
In this case, the stream context can be passed as a parameter in fopen() and file_get_contents() to tell the functions to send that authorisation header and those options to the wrapper.
You can create a stream context using the stream_context_create() function.
<?php
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n" .
"Cookie: foo=bar\r\n"
)
);
$context = stream_context_create($opts);
/* Sends an http request to www.example.com
with additional headers shown above */
$fp = fopen('http://www.example.com', 'r', false, $context);
fpassthru($fp);
fclose($fp);
The stream_context_set_params() function sets parameters for a stream/wrapper/context.
bool stream_context_set_params ( resource $stream_or_context , array $params )
The stream_copy_to_stream() function copies data from one stream to another. There can be up to 4 parameters passed in this function.
The return value is the number of bytes copied.
<?php
$src = fopen('http://www.example.com', 'r');
$dest1 = fopen('destination.txt', 'w');
echo stream_copy_to_stream($src, $dest1, 1024) . " bytes copied to destination.txt";
A filter is a final piece of code which may perform operations on data as it is being read from or written to a stream. Any number of filters may be stacked onto a stream. Current filters can be seen using the stream_get_filters() function.
$streamlist = stream_get_filters(); print_r($streamlist); // Outputs: 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.* )
Custom filters can be registered using the stream_filter_register() function. The second parameter (class name) must extend the php_user_filter class.
<?php
/* Define our filter class */
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;
}
}
/* Register our filter with PHP */
stream_filter_register("strtoupper", "strtoupper_filter")
or die("Failed to register filter");
You can then add the custom filter to the stream using the stream_filter_append() function.
$fp = fopen("foo-bar.txt", "w");
/* Attach the registered filter to the stream just opened */
stream_filter_append($fp, "strtoupper");
Note: This article is based on PHP version 7.1.