3

I need same 2 lines in all my controllers, each controller have its own init logic, but these two lines are common for all of them.

public function init()
{
    $fm =$this->_helper->getHelper('FlashMessenger');
    $this->view->messages = $fm->getMessages();
}

How can I avoid repeat code ?

Update:

Ok, the FlashMessenger was only an example, let's say I need write a log line in every action except for 'someAction' @ 'someController'. So the new common lines should be.

$this->logger = new Zend_Log();
$writer = new Zend_Log_Writer_Stream(APPLICATION_PATH.'/../logs/log.txt');
$this->logger->addWriter($writer);
$this->logger->log('Some Message',Zend_Log::DEBUG);

The question is, where should I place these lines in order to avoid repeat them in all init() of each controller. These lines should be placed at bootstrap?. If so: How can skip log lines for 'someAction'. Or should I implement a 'BaseController' and make all my controller extend from it. If so: How can I Autoload it? (Fatal error: Class 'BaseController' not found) .

Charles
  • 50,943
  • 13
  • 104
  • 142
texai
  • 3,696
  • 6
  • 31
  • 41

5 Answers5

6

Just subclass the controller:

class Application_ControllerAction extends Zend_Controller_Action {
    public function init()
    {
        $fm =$this->_helper->getHelper('FlashMessenger');
        $this->view->messages = $fm->getMessages();
    }
}


class IndexController extends Application_ControllerAction {
}

You may also achieve the same writing Controller Plugin.

Edit:

Front controller plugins are executed on each request, just like the Controllers and have the same hook methods:

routeStartup(): prior to routing the request
routeShutdown(): after routing the request
dispatchLoopStartup(): prior to entering the dispatch loop
preDispatch(): prior to dispatching an individual action
postDispatch(): after dispatching an individual action
dispatchLoopShutdown(): after completing the dispatch loop

I addition, you may check controller params to execute the code only on selected requests:

if ('admin' == $this->getRequest()->getModuleName() 
&& 'update' == $this->getRequest()->getActionName() ) …
takeshin
  • 49,108
  • 32
  • 120
  • 164
  • Please, explain how would help the Controller Plugin – texai Feb 19 '11 at 18:19
  • 1
    I recommend using a view helper instead of subclassing the controller, since view helpers are created exactly for this purpose. Subclassing the Controller class is a usual approach within other frameworks, but Zend provides the helper functionality. The same goes for action helpers, by the way. – Martijn Feb 20 '11 at 11:39
1

You can access your flash messages through (you dont need to send anything from your controller to your view, it's all automated)

$fm = new Zend_Controller_Action_Helper_FlashMessenger();
Zend_Debug::dump($fm->getMessages());

in you view, i would also recommand that you encapsulate this code in a view helper like it is shown on this site http://grummfy.be/blog/191

JF Dion
  • 4,014
  • 2
  • 24
  • 34
  • @Jeff: Thanks for your answer, but I still want to know how to avoid repeat code in all your controllers. – texai Feb 18 '11 at 20:46
  • I've asked a smilar question regarding this http://stackoverflow.com/questions/4347965/zendframework-send-variables-from-controller-to-view-best-pactice – JF Dion Feb 18 '11 at 20:48
  • @Jeff: Also, I prefer don't write _new_ in my views. – texai Feb 18 '11 at 20:48
  • @texai : I can understand you coding preferences and I am fine with them, but if you refer to the theorical MVC design pattern, Controllers and Views can call Models, so, beside coding preference, there is nothing wrong there (http://en.wikipedia.org/wiki/Model_view_controller) – JF Dion Feb 18 '11 at 20:53
  • @Jeff: Sometimes I call static methods of my model classes from views, but I prefer do _new_ in contrllers. – texai Feb 18 '11 at 22:49
  • @Jeff FlashMessenger was only an example. I've set a new example, please see the update. – texai Feb 19 '11 at 06:12
0

In your bootstrap:

protected function _initMyActionHelpers() {
    $fm = new My_Controller_Action_Helper_FlashMessenger();
    Zend_Controller_Action_HelperBroker::addHelper($fm);;
}
Stephen Fuhry
  • 12,624
  • 6
  • 56
  • 55
-1

How can I avoid repeat code ?

Write your own custom controller, implement that in init method of that controller, and then extend all controllers in your app from your custom controller.

But approach with separate view helper as @Jeff mentioned (look at link) is often taken as a better solution. In your controller do only:

$this->_helper->flashMessanger('My message');

and view helper will do the rest.

Radek Benkel
  • 8,278
  • 3
  • 32
  • 41
  • That's defeating the whole point of action helpers! from the docs: "Action Helpers aim to minimize the necessity to extend the abstract Action Controller in order to inject common Action Controller functionality" http://framework.zend.com/manual/en/zend.controller.actionhelpers.html – Stephen Fuhry Feb 18 '11 at 21:35
  • I didn't say that it good solution. More - I wrote, that view helper will be better and suggested code without need to use `init`! But question was: "how to run **something** in all controllers **init** function" - and what I wrote is pure answer for that question. So I think, that downvoting me is inequitably. – Radek Benkel Feb 18 '11 at 21:38
-1

It's not the reason for creating new custom controller. Just add this line to all you init() methods.

$this->view->messages = $this->_helper->getHelper('FlashMessenger')->getMessages();
KomarSerjio
  • 2,861
  • 1
  • 16
  • 12