Extend Zend_View_Stream to easily escape view variables

Last modified date

Comments: 0

Zend_View_Stream is used pretty much when ever you use Zend_View, and I’ve blogged about how handy it is before.  But as it’s a class like any other, you can extend it to give added functionality.  One such use is to add automatic escaping to your view variables when you want.  So instead of doing:

[code lang=”php”]
<?php echo $this->escape($this->var); ?>
<?= $this->escape($this->var); ?>
[/code]

You could simply do:

[code lang=”php”]<?=~ $this->var; ?>[/code]

That’s a lot simpler, isn’t it?

To do this, we need to do two things; 1) extend the stream class and 2) make sure we register it before Zend Framework registers Zend_View_Stream.

[code lang=”php”]
<?php

class My_Stream extends Zend_View_Stream
{
/**
* Opens the script file and converts markup.
*/
public function stream_open($path, $mode, $options, &$opened_path)
{
// get the view script source
$path = str_replace(‘zend.view://’, ”, $path);
$this->_data = file_get_contents($path);

/**
* If reading the file failed, update our local stat store
* to reflect the real stat of the file, then return on failure
*/
if ($this->_data === false) {
$this->_stat = stat($path);
return false;
}

/**
* Convert <?= ?> to long-form <?php echo ?> and <? ?> to <?php ?>
*
*/
$this->_data = preg_replace(
‘/\<\?\=~ (.*?);? \?>/’,
‘<?php echo $this->escape($1); ?>’,
$this->_data
);
$this->_data = preg_replace(
‘/\<\?\=/’,
‘<?php echo ‘,
$this->_data
);
$this->_data = preg_replace(
‘/<\?(?!xml|php)/s’,
‘<?php ‘,
$this->_data
);

/**
* file_get_contents() won’t update PHP’s stat cache, so we grab a stat
* of the file to prevent additional reads should the script be
* requested again, which will make include() happy.
*/
$this->_stat = stat($path);

return true;
}
}
[/code]

The observant of you will notice that the above is almost exactly the same as Zend_View_Stream::stream_open(), but with this bit of code added to it:

[code lang=”php”]
$this->_data = preg_replace(
‘/\<\?\=~ (.*?);? \?>/’,
‘<?php echo $this->escape($1); ?>’,
$this->_data
);
[/code]

So if you don’t like using ~ to do the escape this is where you’d change it.

Now all you have to do is register your stream before Zend Framework does. You could do this in your bootstrap file, your application class, or whereever it makes sense for your applicaiton. Basically, you’d just be dropping in a line like this:

[code lang=”php”]stream_register_wrapper(‘zend.view’, ‘My_Stream’);[/code]

Hopefully that gives you some ideas on extending the stream wrapper even more!

Share

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.