Zend View Helper in database stored content

by Patrick on February 13, 2011

One of my co-workers currently writes his own website based on the Zend Framework. He wanted to use view helpers inside of the content, just like you do in view scripts. But the thing with content nowadays is that it is stored inside a database. He came up with a pretty simple, yet somewhat brilliant solution.

Basically, he loads the content from database, saves them as a file and passes the path to that file directly to Zend_View::renderScript(), which in turn handles the content as if it were a view script.


class IndexController extends Custom_Controller_Action
{
    /**
     * Index action
     *
     * @return void
     */
    public function indexAction()
    {
        // Content article
        $conGUID = $this->getRequest()->setParam('con_guid', 'default');

        // Category
        $catGUID = $this->getRequest()->setParam('cat_guid', 'main');

        //  content action
        $this->contentAction();

        // Deactivate auto render, we will render in content action
        $this->_helper->viewRenderer->setNoRender();
    }

	/**
	 * Show content article action
	 *
	 * @return void
	 */
	public function contentAction()
	{
        // Evaluate params

        // Content article
        $conGUID = $this->getRequest()->getParam('con_guid');

        // Category
        $catGUID = $this->getRequest()->getParam('cat_guid');

        // Set loaded false
        $loaded = false;

        // Content article AND category requested
        if ( $conGUID && $catGUID ) {

            // Configure cache object

            // Set cache frontend options
            $frontendOptions = array(
                'lifetime' => 7200 // save for 2 hours
            );

            // Get script path
            $scriptPath = $this->view->getScriptPaths();

            // Set cache backend options
            $backendOptions = array(
                'cache_dir' => $scriptPath[0].'index/cache/'
            );

            // Create Zend_Cache_Core object
            $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);

            // If no cache available for this content page
            if(!$cache->test('content_'.$conGUID)) {
                // Load content article
                $content = new Custom_Content_Page();

                if ( $content->load($conGUID) ) {
                    // Content assigned to requested category?
                    if ( $content->c_guid === $catGUID && true === $content->isOnline() ) {
                        // Content loaded
                        $loaded = true;
                    }
                }

                // Not found or not online
                if ( false === $blLoaded ) {
                    throw new Custom_Content_Exception('Cannot load content page. Invalid parameter specified ('.$conGUID.').');
                } else {
                    // Save content in cache object
                    $cache->save($oContent->getContent(), 'content_'.$conGUID);
                }
            }

            // Try to load cache file
            if ( $result = $cache->load('content_'.$conGUID) ) {

                // Get metatags if guid is set
                $oMeta = new Custom_Content_Meta();

                if ( $oMeta->load($conGUID) ) {
                    $this->view->oMeta = $oMeta;
                }

                // Assign content
                $this->view->content = $result;

                // @TODO: dynamic ftw
                $this->renderScript('index/cache/zend_cache---content_'.$conGUID);
            }
        }
    }
}

The code itself should be self-explanatory, though it’s commented pretty detailed. As you can see, this is a basic database caching mechanism, but instead of caching the final output of the content page which would be parsed by the browser, the code itself is cached and used as a view script. That way, the view helpers (and any other PHP code inside the content) are executed and produce the desired output. Of course without using include() directly or, even worse, eval().

In order to have a real cache, one would need to cache the final output of that rendering action, say, as a HTML file. In this case, Zend_Cache is just used because you can quite comfortably check for already stored files and then load or write them. Zend_File anyone?

4 comments

Sounds great, Thanks!

Any chance of also getting the code for class Custom_Content_Page() which is used in above code?

Thank you!
G.

by George on November 5, 2011 at 11:19 pm #

It’s like wine, the older the better… :P

Glad you liked it, I’ll see what I can do, as I said it was written by one of my co-workers. But I don’t think this is a problem.

by Patrick on November 8, 2011 at 6:15 pm #

Here you go: https://gist.github.com/1353067

by Patrick on November 9, 2011 at 10:20 pm #

Great, great, great! Thanks so much indeed.

by George on November 10, 2011 at 7:37 pm #