Chapter 8. Streams, Wrappers, and Filters

PHP's streams provide a file-like interface for reading and writing data. A single interface for many different data sources lets you write reusable code: a program that extracts data from a local file can just as easily extract data from a web page, and new streams data sources can immediately be used with any existing streams code. This reuse makes streams a powerful and underused feature in PHP.

Streams were a late addition to PHP 4, arriving only in PHP 4.3. As a result, they're barely covered in other PHP books, and hardly anyone uses them to their full extent. Therefore, while PHP 5 introduces some new streams features, that's not the focus of this chapter. Instead, it compares programming with and without streams and discusses the advantages streams provide over alternatives, such as cURL.

An extension that provides a streams interface to a new data source is called a wrapper. The streams interface consists of 14 methods, but you need only implement the methods that make sense for your data source. For example, if you wanted to provide a streams interface to a mailbox of messages, you might not support renaming or rewriting. You can write wrappers in C or in PHP.

The SimpleXML extension is written to use the streams interface for its data. This means that the same function that loads XML from a datafile (simplexml_load_file( )) also loads XML from a URL, an FTP site, and any other data source you have a wrapper for.

Sometimes, in addition to transporting data, you want to modify it. For example, you might want to encode HTML entities, strip HTML tags, or otherwise alter the text. Since these conversions are independent of the wrapper, it doesn't make sense for the wrapper to handle the job. Stripping HTML tags is something you may want to do for local files and text retrieved via HTTP, and there's no point in writing one function for each location.

PHP streams support filters to make modifications to a stream's data. Once installed, a filter sits between a streams wrapper and PHP code that reads from or writes to a stream. The filter intercepts the data and may modify it. This makes a filter's actions transparent to a wrapper and to user code, allowing you to associate a filter with any stream, regardless of the wrapper the stream is using.

While it makes sense only to have one wrapper per data source, you can chain multiple filters in a row. The Unix shell has a similarly powerful feature, pipelines, where you can connect a series of programs to modify data. In Unix, as in PHP streams, all a filter knows is that it must take the data provided as input, filter it according to some rules, and then provide the new data as output. It doesn't care if this information has already been filtered or if another filter or two follows it.

This chapter shows how to use streams by explaining the wrappers available with PHP 5: file, http, ftp, and php. php is a PHP-specific wrapper that handles information passed to and emitted from PHP using standard input, output, and error. There are also a few compression wrappers and SSL-enabled wrappers that are available depending upon how your version of PHP is configured.

Next, you learn how to write a wrapper of your own so you can extend PHP. The Section 8.4 shows how to build a shared memory wrapper that uses PHP's shared memory functions. Shared memory allows you to easily communicate among all PHP processes on the same web server in an efficient manner.

After wrappers come filters. Again, PHP has a few built-in filters. In particular, the string.strip_tags and convert.iconv filters are extremely useful, as they allow you to eliminate HTML tags and convert text from one character encoding to another, respectively.

However, the main power of filters comes from the ability to write your own filters using PHP. Since filters are so flexible, there's a bit of wrapping code necessary to implement even a very simple filter, but once the basic structure is in place, it's easy to modify what you have in all sorts of directions.

This chapter concludes by showing how to write custom filters, using the htmlentities( ) function as an example, and also demonstrates how to chain multiple filters together.

For a complete streams reference, see the "Streams" section of the PHP Manual at If you're interested in implementing wrappers and filters in C, read