When I took the Zend certification exam, one of the areas I really wasn't very clear on was PHP's stream wrappers. Since reading up on them for the exam, I've been kicking myself for not using them before, the amount of simplification they allow for common code is ridiculous.
As an example, a colleague recently showed me some code he'd written that downloaded a .dat.gz file from a remote server, saved it to disk, unzipped it and save the expanded contents into a file. The original code he showed me was similar to the following (with a lot more error checking and comments):
<?php
$tempfile = tempnam(sys_get_temp_dir());
// get the file from FTP to local disk
$fh = ftp_connect('ftphost.com', 21);
ftp_login($fh, 'username', 'password');
ftp_get($fh,$tempfile, '/path/to/file.dat.gz');
ftp_close($fh);
// read data from local .gz into var
$gh = gzopen($tempfile, 'r');
$data = gzread($gh, 1000000);
gzclose($gh);
unlink($tempfile);
// write data to local .dat
file_put_contents('/local/copy/of/file.dat', $data);
The first thing to note is that the ftp functions have an underscore in, while the gz functions don't. To me at least, this makes it almost impossible to remember without constantly referring to the reference. The second thing to note is that by downloading the file to disk first, then reading it into memory, then writing it to disk, we're doing a three-step process.
It might be possible to make this code more efficient using the ftp_* and gz* functions by keeping the data in memory more, and writing some sort of pipeline, but frankly stream wrappers are the way to go. In fact, the whole thing can be rewritten using stream wrappers into a single line:
<?php
copy('compress.zlib://ftp://username:password@ftphost.com:21/path/to/file.dat.gz', '/local/copy/of/file.dat');
This has the following benefits:
- The original complex operation is rephrased as a 'copy', so it's easier to see at a glance what's going on.
- Data is pipelined straight to disk as soon as enough has been downloaded from the FTP to start being decoded.
- It's far more compact.
This is only really the tip of the iceberg when it comes to the power of stream wrappers, but hopefully enough to pique your interest enough that you go and see for yourself how much more they can do for you.
1.
I have not used stream wrappers before but will certainly give them a try next time. It is quite amazing what you can accomplish with such a concise code.
Reading this made me think about what a small fraction of PHP I actually use on a day to day basis.
Just having a quick look through the manual I would estimate that I use about 5% to 10% of the available functionality regularly.
The really interesting question would be, how much of the bits that I don't use are actually useful? I think that stream wrappers are a great example of little used functionality that would actually make a developers life easier.
I suppose that although you only ever use a small percentage of of what PHP is capable of the key is to be aware of more unusual functionality.
Russell
2nd April 2009, 11:38