David Reuss home

How (apparently!) not to do action based caching with Zend Framework

May 18th 2009

I’ve playing with Zend Framework. (ZF) for a personal project at the time, and there is a lot to like about ZF but you also have to realize it can be quite a monster to wrap your head around. Especially if you’re dealing with the MVC package of the framework.

The goal was to have access to easy action based caching, by utilizing any of the Zend_Cache frontends. I’d read a bit about the plugin infrastructure of ZF components and it seemed pretty standard.

I figured an action helper helper extending Zend_Controller_Action_Helper_Abstract would accomplish what i needed as it would give me pre and post dispatch hooks. The idea was just to hook into postDispatch, and see if it’s a registered method i want cached, and then store it away for the preDispatch hook to look after on the nest request.

Before actually implementing anything i whipped up a very simple helper for figuring out whether it did what i wanted or not.

<?php
class Helper_ActionCache
    extends Zend_Controller_Action_Helper_Abstract {

    public function preDispatch() {
        $this->fire('>');
    }
    public function postDispatch() {
        $this->fire('<');
    }
    protected function fire($when) {
        $req = $this->getRequest();
        $actionName = strtoupper($req->getActionName());
        $this->getResponse()
             ->appendBody("$when $actionName\n");
    }
}
?>

It’s basically just a stupid logger that appends to the content of the page
so i’d be able to figure out what time the hooks are run, and if i have access to the
content that i’d like to cache.

I had to perform a couple of tests to see if everything worked out in each of the different scenarios.

  1. Plain action being called
  2. Forwarding/rendering another action inside a controller
  3. Nested actions – calling an action inside another action
  4. Action being called inside a viewscript

So i wired stuff up, creating my IndexController and my actions and noted the results on each of them.

The code

controllers/IndexController.php

<?php
class IndexController extends Zend_Controller_Action {
    public function init() {
        $helper = $this->_helper->getHelper('actionCache');
    }
    public function indexAction() {}
    public function byrenderAction() {
        $this->render('index');
    }
    public function nestedAction() {}
    public function outerAction() {}
    public function innerAction() {}
}
?>

views/scripts/index.phtml

Content...

views/scripts/nested.phtml

<?= $this->action('outer', 'index') ?>'

views/scripts/outer.phtml

<?= $this->action('outer', 'index') ?>

Results

1. Plain action being called (index)

> INDEX
< INDEX
Content...

Um.. That was not exactly what i expected. And this was just for a plain action being called directly. Doesn’t look good.

2. Forwarding/rendering another action inside a controller (byrender)

> BYRENDER
Content...
< BYRENDER

Calling a plain action doesn’t work, but rendering another action inside one does? Weird.

3. Nested actions – calling an action inside another action (nested)

> NESTED
< NESTED
> INDEX
Content...
< INDEX
< INDEX

What the heck is going on here? Nothing from the outer action at all?

4. Action being called inside a viewscript (outer)

> OUTER
< OUTER
> INDEX
Content...
< INDEX

Again. Confusing.

Failure

I set out creating a simple solution for action based caching with ZF and it seems as i’ve failed miserably at doing it. Is the approach wrong? I’m not sure. If the helper is not supposed to work like this (on plain actions) why is it seemingly invoked in the first place?

If you have anything to say about this, please don’t hesitate to leave a comment. I’d love for this type of solution to work, as it seems like something really useful. Without a great deal of overhead. I know i will appreciate it very much.

If it turns out this is indeed not intended behaviour i might give a shot at turning it into unit tests, or even fixing it myself, if i’d be able to fully comprehend the ZF dispatch cycle.

blog comments powered by Disqus
Fork me on GitHub