Php user streams are amazing - they're powerful, fun, and make things like a templating system with filters and multiple back ends quick and easy.
Here's a little "test script" that shows you how to implement contexts for your streams. What are contexts? They're resources that hold additional information. Built in php streams, such as the ftp streams, already have contexts you can set. But they're also great to use in your own user land streams.
[php]
class test
{
/**
* public function stream_open
*
* This method is called immediately after your stream object is created.
* You can use parse_url() to break path apart.
* You are responsible for checking that mode is valid for the path requested.
* STREAM_USE_PATH: use the include_path
* STREAM_REPORT_ERRORS: trigger_error() during opening of the stream
* If the path is opened successfully, and STREAM_USE_PATH is set in options, you should set opened_path to the full path of the file/resource that was actually opened.
*
* @param string $path url passed to fopen()
* @param string $mode see fopen docs for mode choices
* @param int $options STREAM_USE_PATH and STREAM_REPORT_ERRORS optionally orred together
* @param string $opened_path path actually opened
* @return type bool
*/
public function stream_open($path, $mode, $options, $opened_path)
{
// bug fix for include
if (!isset($this->context)) { $this->context = stream_context_get_default(); }
$context = stream_context_get_options($this->context);
var_dump($context);
return true;
}
/**
* public function stream_close
*
* called on fclose() - release resources
*
* @return void
*/
public function stream_close()
{
}
/**
* public function stream_read
*
* fread() and fgets() - return up-to count bytes of data from the current
* read/write position as a string. If no more data is available, return
* either FALSE or an empty string. Update the read/write position of the
* stream by the number of bytes that were successfully read.
*
* @param int $count
* @return type about
*/
public function stream_read($count)
{
}
/**
* public function stream_eof
*
* used for feof() return TRUE if the read/write position is at the end of
* the stream and if no more data is available to be read
*
* @return bool
*/
public function stream_eof()
{
}
/**
* public function stream_stat
*
* fstat() - returns array(dev, ino, mode, nlink, uid, gid, size, atime,
* mtime, ctime) and may have additional items
*
* @return array
*/
public function stream_stat()
{
}
}
stream_wrapper_register('test', 'test');
$default = stream_context_get_default(array('test'=> array('type' => 'pgsql')));
file_get_contents('test://test');
$different = stream_context_get_default(array('test'=> array('param' => 'value')));
stream_context_set_option($different, 'test', 'param', 'new_value');
file_get_contents('test://test', false, $different);
stream_context_set_option($different, 'test', 'param', 'another_value');
file_get_contents('test://test');
$new = stream_context_create(array('test'=> array('param' => 'secondvalue')));
file_get_contents('test://test', false, $new);
include('test://test');
[/php]
Notice the little "bug fix" there. Right now include is slightly broken, because $this->context isn't getting populated (I'm hunting through the source to fix it...if I don't get it done by |tek I'll bug Sara ;)
Now you know how to pass information into your stream wrapper!
Dreaming of Dawn








Chris Hartjes
I keep forgetting about streams (PHP 4 in the brain I guess), but can you point to an example of doing templates using streams? It seemed such a teaser to not provide an example. :)
2007-05-07 4:34 am