| Latest |Kites |Pictures |Programming |Life |
![]() [filed under Programming]Zend Framework Menus Navigation ![]() Tags: Zend Framework, menus, controller, action, navigation, template, menu.phtml, This is how to put menu logic in your web page. OK, from the get go, this is hard. You may need to read it a couple of times or do more research. What we want is a web page with a menu system (a list of items) on the left of the page. The menu will be different for each controller and action. What usually happens in ZF is the ApplicationController class is created and the method indexAction is called. indexAction then uses the model to get data and passes info to the view (for example using $this->view->data = 99; ). The view is then rendered as a string, which is appended to the Layout content. It took me a while to figure that out. To make the menu we need a seperate controller, the MenuController will decide what to show on the menu. The the menu view will render it and we capture the output of the view into a layout variable. The menu HTML is used later in the layout.phtml template. In our application controller we push the "menu" onto the actionStack which makes ZF run MenuController::applicationAction next.
MenuController.php The MenuController changes the layout response segment to 'menu', all the HTML in the menu view is saved to this variable. This HTML to make the menu is then merged into the web page in layout.phtml. More notes on Zend Framework Menu Navigation. Comments [20th of Sep, 2008 @ 01:35 PM] Pete Williams said: Thank you! I've been trying to get my head around this for about 2 days now and now it finally makes sense! [29th of Sep, 2008 @ 10:32 AM] ignar said: Thanks. You help me much. [13th of Nov, 2008 @ 11:07 AM] David said: Firstly, what is your view on this approach? Adding an actionStack call to every controller seems long winded especially if the majority use a standard menu i.e. defaultmenuAction in the NavController. Also using this method I am encountering a problem with the use of _forward() in my actions. When calling a _forward from one action to another within the same controller the menu action is added to the actionStack twice (once for initial init() and then for each forward). How would you propose I stop this easily? Is there a way of detecting if the actionStack currently has the call to the action in the NavController and thus doesnt add it again? Back to my original question... is there a better way entirely? Thanks for your help. [20th of Nov, 2008 @ 11:39 AM] Pieter said: David, You can create an Zend_Controller_Action class that all your controllers can inherit and only do the actionStack in the Parent class like this: public function __construct($req, $rsp) { parent::__construct($req, $rsp); $this->_helper->actionStack('menu','nav'); } Haven't tested this but I'm sure it should work [5th of Dec, 2008 @ 02:04 PM] Sammy said: To the author of this article, thank you!!! You saved me: 1) In my layout.phtml I needed a menu, and it's elements should be translated depending on the language. 2) I have a helper translate. 2) Helpers don't work in layout.phtml, so I needed to call it in a DEFAULTcontroller. But which one ... 3) I used Pieters advice and created a Zend_Controller_Action class with an actionStack in it that all my controllers can inherit. 4) And then I used your MenuController.php Thanks again! [29th of Dec, 2008 @ 02:32 PM] Chris said: Hi, Enlightening article. New to Zend. How do you recommend keeping track of the selected menu item? In your example, does another.phtml have a different menu than application.phtml's menu? Keep 'em coming. [7th of Jan, 2009 @ 04:09 PM] Nilesh said: Yo! a great one. I was scratching my head around this for many hours. Thanks for the informative and helpful article! Nilesh Govindrajan www.itech7.com Site & Server Administrator [26th of Jan, 2009 @ 01:47 AM] Erik Ellis said: Instead of pushing to the actionstack in your controller (and killing off further use of the actionstack or _forward) you can do it in an Action plugin BEFORE the dispatch loop is even running. class Tempel_Controller_Plugin_Menu extends Zend_Controller_Plugin_Abstract { public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request) { parent::dispatchLoopStartup($request); $actionStack = Zend_Controller_Front::getInstance()->getPlugin('Zend_Controller_Plugin_ActionStack'); $actionStack->pushStack(new Zend_Controller_Request_Simple('menu', 'menu', 'default')); } } Now the menu action will only run once. [27th of Jan, 2009 @ 05:56 AM] Athena said: I'm getting the following error :Fatal error: Call to a member function actionStack() on a non-object and I was wondering if anyone can help me fix it? I'm fairly new to Zend and just trying to wrap my head around it all. Thank you! [27th of Jan, 2009 @ 06:01 AM] Athena said: I'm getting the following error :Fatal error: Call to a member function actionStack() on a non-object and I was wondering if anyone can help me fix it? I'm fairly new to Zend and just trying to wrap my head around it all. Thank you! [27th of Jan, 2009 @ 09:30 PM] Ed said: Just use the view helper http://framework.zend.com/manual/en/zend.view.helpers.html [29th of Jan, 2009 @ 04:57 PM] tanie strony internetowe said: Thanks for this article, it's great. So great that we've made it 'sticky' on The Webmaster Forums. Now we don't have to repeat ourselves, just send people to this article! [6th of Feb, 2009 @ 02:50 PM] Rock said: Any solution for Fatal error: Call to a member function actionStack() on a non-object? I checked the view helper but not too much luck... Still googlin around [19th of Feb, 2009 @ 02:41 PM] Florin said: Very good article. But I had the same problem as Athena and Rock had. To solve it, include this piece of code in your bootstrap file: $actionStack = new Zend_Controller_Action_Helper_ActionStack(); Zend_Controller_Action_HelperBroker::addHelper($actionStack); Now, in file ApplicationController.php you should have a constructor like this one: public function __construct($rqs, $rsp) { parent::__construct($rqs, $rsp); // if (Zend_Controller_Action_HelperBroker::hasHelper('actionStack')) { // echo 'actionStack helper registered'; // } $this->_helper->actionStack->actionToStack('application', 'menu'); } The commented lines just check if actionStack helper is registered. Note: I'm not sure this is a best practice, but works for me. Hope it will help somehow. [25th of Feb, 2009 @ 06:29 PM] ceiling roses said: So great that we've made it 'sticky' on The Webmaster Forums. Now we don't have to repeat ourselves, just send people to this article! [21st of Apr, 2009 @ 09:05 PM] Betty said: I have: 1) class My_Zf_Controller_Default extends Zend_Controller_Action 2) class MenuController extends Zend_Controller_Action 3) class IndexController extends My_Zf_Controller_Default which means Zend_controller_action is called twice (in Default and in Menu). What should I use in Menu instead? Thanks a lot for sharing this info! [24th of Jul, 2009 @ 08:35 PM] Ben said: First off, thank you for this. I am just starting to sink my teeth into the Zend framework and I am surprised that more people don't put their menus into their layout. I am having problems though. It doesn't appear that ApplicationController is being called because if I echo from it I don't see anything. What am I missing? Thanks, -Ben [29th of Aug, 2009 @ 07:39 PM] luoshiben said: Also be sure to checkout Zend_Navigation. Couple that with a Zend_Config file and some bootstrap magic and you don't have to repetitively put code anywhere. More specifically, make a new _initView method in your bootstrap like so: protected function _initView() { //* Initialize view $view = new Zend_View(); $view->doctype('XHTML1_STRICT'); $view->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=utf-8'); $view->headTitle('My Website')->setSeparator(' - '); $view->env = APPLICATION_ENV; //* setup nav from nav xml file for use in view $navContainerConfig = new Zend_Config_Xml(APPLICATION_PATH.'/configs/navigation.xml','nav'); $navContainer = new Zend_Navigation($navContainerConfig); $view->navigation($navContainer); //* Add view to the ViewRenderer $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper( 'ViewRenderer' ); $viewRenderer->setView($view); //* Return view, so that it can be stored by the bootstrap return $view; } Then, in your layout just call: <?php echo $this->navigation() ?> In your bootstrap you can also apply auth and acl models to the navigation so that it only displays what people have access to see, like so: $view->navigation($navContainer)->setAcl($acl)->setRole($roleId); [4th of Sep, 2009 @ 09:41 AM] Maria said: luoshiben Thank you! Your comment helped a lot! My intension was to use Zend_Navigation and it was'nt easy. 2009-09-01 I downloaded the latest release and a quickstart. In this latest zend-lib the Zend_Navigation is included. If somebody whants to do the same, follow lushibens instruktion with my changes: In Bootstrap.php the function to call is not _initView but _initViewHelpers(). You catch the view by: $view = $this->bootstrap('view')->getResource('view'); And after that it is the same code. [13th of Jun, 2010 @ 01:39 PM] Laura Dean said: Here is a quick tutorial on how to create a menu with Zend_Layout and Zend_Navigation, starting from the default ZF quickstart: http://zendreflections.blogspot.com/2010/06/layout-and-navigation-part-1.html http://zendreflections.blogspot.com/2010/06/layout-and-navigation-part-2.html |
| Server Grind [0.0501 seconds] |