Output Filters in Zend_View

Published in PHP on Jun 4, 2008

A feature of Zend Framework MVC that isn't currently very well documented is output filters. They're mentioned in passing in the Zend_View documentation, but not reviewed in detail anywhere in the Reference Guide as of version 1.5.2. I was curious enough about how to implement markup minification that I decided to trace through the Zend_View source code in attempt to discern how output filters actually worked. As it turns out, it's actually pretty simple.

First, you need to get a reference to the current Zend_View instance. If you're using the Zend_Layout MVC integration, you can get this by calling $this->_helper->layout->getLayoutInstance() within your Zend_Controller_Action class to get the current Zend_Layout instance and then getView() on that to get your Zend_View instance. Otherwise, the Zend_View instance is available via the view property of Zend_Controller_Action instance.

Next, call addFilterPath() or setFilterPath() on your Zend_View instance from your Zend_Controller_Action class. Pass in a path to the directory to contain your output filter classes and a naming prefix that all of your output filter classes will use. I'm not sure why the class prefix defaults to Zend_View_Filter_ since no such classes exist. In my opinion, it would have made more sense to derive the prefix based on the provided directory path. Anyway, create the directory you've specified if it doesn't already exist and create a new class file within that directory. In my case, I named the directory Vendor/View/Filter, the file Minify.php, and the class contained in the file Vendor_View_Filter_Minify.

Within this class, you must implement at least one method, filter(). This method should accept a single parameter, which will be a string containing the view ouput to be filtered, and should return the filtered version of that string. Optionally, if your filter requires access to the related Zend_View instance, you can also declare a setView() method that accepts the Zend_View instance as its only parameter, and it will automatically be passed in when your output filter class is instantiated. Within setView(), you can store the Zend_View instance in an instance property of the output filter class so it can be referred to later in the filter() method.

Once you've finished your output filter class, you need to explicitly add it to the output filters in use from your Zend_Controller_Action class. You can use addFilter() or setFilter() for this. Pass in the name of your output filter class without the class prefix. In my case, I passed in 'Minify'. At this point, the filter should be used when rendering your page. I poked around in the DOM and Tidy PHP extension documentation, but couldn't find a feature for markup minification, so I ended up using the PCRE extension to do the job. Below is the final source code for my output filter class.

// Vendor/View/Filter/Minify.php
class Vendor_View_Filter_Minify
{
    public function filter($string)
    {
        return preg_replace(
            array('/>\s+/', '/\s+</', '/\[\\x0A\\x0D\]+/'),
            array('>', '<', ' '),
            $string
        );
    }
}
// Vendor/Controller.php
class Vendor_Controller extends Zend_Controller_Action
{
    public function init()
    {
        $this->_helper->layout->getLayoutInstance()->getView()
            ->addFilterPath('Vendor/View/Filter', 'Vendor_View_Filter_')
            ->addFilter('Minify');
    }
}