The PHP Stream Wrapper

PHP has a huge standard library of functions, so big that I doubt any programmer has ever had the reason or chance to use all of it. For example, I have never needed PHP’s functions for manipulating ID3 tags. However, today I want to write about part of the standard library which I have found useful in the past, and which many PHP programmers (in my experience) are unfamiliar with: the php:// stream wrapper.

A Quick Introduction to Wrappers

Wrappers let you use some of PHP’s file-system functions on things that look like URIs. For example:

$content = file_get_contents("http://ericjmritz.name/");

PHP comes with a built-in wrapper for HTTP that allows you to read from sites as if they were files. The example above stores the HTML for my blog’s front page into that variable, as a string. It opens a stream to my site and reads from it as if it were a file. However, that does not mean you can do everything that you could with a normal file. Consider this:

$resource = fopen("http://ericjmritz.name/", "w");
fwrite($resource, "Haha, overwrote your site!");

I am sure you can think of some reasons why that code fails to work. The important point, though, is that wrappers allow you to use a subset of PHP’s file functions on sources of data which are not files in the typical sense. This is a useful layer of abstraction, e.g. how you can read HTML from a site using the exact same code you would use to read from a text file on your hard drive.

The PHP Wrapper

In this article I want to focus on the php:// wrapper. It gives you access to streams like standard input and output. That means you can write code like this to read everything from standard input:

$input = file_get_contents("php://stdin");

If you wanted to write data to standard output or standard error you could use php://stdout and php://stderr as files, respectively.

Note: These three specific stream wrappers are buggy in versions of PHP older than 5.2.1.

I know that does not look all that impressive or interesting, considering that PHP already provides constants like STDOUT for the same purposes—use those on older versions PHP as noted above. Standard output is already an alias for something else: a file-descriptor. The php://fd wrapper gives you access to files via their file-descriptor number.

$stdin  = fopen("php://fd/0"); /* Same as php://stdin  */
$stdout = fopen("php://fd/1"); /* Same as php://stdout */
$stderr = fopen("php://fd/2"); /* Same as php://stderr */

A more practical, useful stream provided by the wrapper is php://input. You can read from this stream in web applications to get data from HTTP requests. Instead of globals like $_REQUEST and $_POST and $HTTP_RAW_POST_DATA you can simply read from php://input to cover all of those. The wrapper also allows you to read data from other types of HTTP requests, e.g. PUT requests. PHP does not provide a global for PUT requests like it does GET and POST, so that makes php://input a useful source for reading data from all types of requests.

If you need to temporarily read and write data somewhere then you can use php://memory or php://temp. Both of these will store the data in memory, but the latter will write the data to a temporary file on disk once the amount of data crosses a certain threshold, two megabytes by default. You can adjust this limit by providing the threshold in bytes, e.g. php://temp/maxmemory:4096 tells PHP to write to disk only after the stream receives at least 4,096 bytes.

Note: The file that php://temp creates appears in the directory that sys_get_temp_dir() returns.

Conclusion

So that is a quick rundown of the php:// wrapper, which again is just one of the built-in wrappers. You can even create your own, a subject I will write about another day. In any case, I hope you find this information useful. In recent years I have found that using wrappers like php:// helps me reuse code that performs input and output operations, so maybe you will find a use for them too.

Advertisements

Add Your Thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s