views:

45

answers:

2

I wrote a plugin that needs to set a property on the controller that's currently being dispatched. For example, if my plugin is:

class Application_Plugin_Foo extends Zend_Controller_Plugin_Abstract
{
    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
    {
        // Get an instance of the current controller and inject the $foo property
        // ???->foo = 'foo';
    }
}

I want to be able to do this:

class IndexController extends Zend_Controller_Action
{
    public function indexAction()
        {
            $this->view->foo = $this->foo;
        }
    }
}

Any help is greatly appreciated!

A: 

Browsing through the API, I didn't find a way to reach the controller directly (I'm guessing this loop is performed before the controller exists). What I could find is almost as easy to access, albeit with a bit different syntax.

Via request params

class Application_Plugin_Foo extends Zend_Controller_Plugin_Abstract
{
    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
    {
        $yourParam = 'your value';
        if($request->getParam('yourParam')) {
           // decide if you want to overwrite it, the following assumes that you do not care
           $request->setParam('yourParam', $yourParam);
        }
    }
}

And in a Zend_Controller_Action::xxxAction(): $this->getParam('yourParam');


Via Zend_Controller_Action_Helper_Abstract

There's another way mentioned in MWOP's blog, but it takes the form of an action helper instead: A Simple Resource Injector for ZF Action Controllers. His example would let you access any variable in Zend_Controller_Action as $this->yourParam.

chelmertz
Seems that the *Simple Resource Injector for ZF Action Controllers* link's contents was copied into @DavidW's answer but I urge you to read the whole discussion on the original page. There's a lot of useful comments as well.
chelmertz
@chelmertz I started going the getParam() way before posting this question. I even wen the "extending a base controller" way too but found both to have many flaws not worth discussing here. Using an action helper seemed to be the right way to do what I wanted to do but after reading the article you mentioned I changed my mind and will go the "injecting dependencies" way Matthew describes. Seem the most effective method for working with a group of programmers.
Julian
@Julian I agree with you but if it's not documented properly it might be hard to find where all those dependencies are coming from. All in all it seems like a solid method!
chelmertz
@chelmertz, you are right about the dependencies. In fact this whole thread got me to rewriting a lot of stuff and I now have a specific place where all needed dependencies are declared (very much in the same fashion the article you mentioned says). Thanks again!
Julian
A: 

The controller is not directly accessible directly from a controller plugin. It's the dispatcher that instantiates the controller object and he doesn't appear to save it anywhere accessible.

However, the controller is accessible from any registered action helpers. Since action helpers have a preDispatch hook, you could do your injection there.

So, in library/My/Controller/Helper/Inject.php:

class My_Controller_Helper_Inject extends Zend_Controller_Action_Helper_Abstract
{
    public function preDispatch()
    {
        $controller = $this->getActionController();
        $controller->myParamName = 'My param value';
    }
}

Then register an instance of the helper in application/Bootstrap.php:

protected function _initControllerInject()
{
    Zend_Controller_Action_HelperBroker::addHelper(
        new My_Controller_Helper_Inject()
    );
}

And, as always, be sure to include My_ as an autoloader namespace in configs/application.ini:

autoloaderNamespaces[] = "My_"

Then, in the controller, access the value directly as a public member variable:

public function myAction()
{
    var_dump($this->myParamName);
}

One thing to note: Since the helper uses the preDispatch() hook, I believe it will get called on every action, even an internal forward().

David Weinraub