Languages :: PHP :: [ZF] pushing subclassed controller_action onto ActionStack |
|||
| By: Flavius |
Date: 14/02/2009 16:44:08 |
Points: 200 | Status: Answered Quality : Excellent |
|
I'm trying to push subclassed zend_controller_actions on the ActionStack in order to simulate a navigation menu with sources from all of the modules. The problem is that the dojo helper accordionpane generates duplicade div ids in certain situations. Does anyone have an idea what causes this, and a possible solution. Below the relevant code and more explanations (or the more colorful pastie) ----- In a FC plugin's routeStartup() I'm pushing custom actions onto the actionstack like this: ## class My_Plugin_Initialize extends Zend_Controller_Plugin_Abstract { public function initModules() { $this->logger->info(__METHOD__); Zend_Controller_Front::getInstance()->addModuleDirectory($this->config->modulesPath); $actionstack = Zend_Controller_Action_HelperBroker::getStaticHelper('ActionStack'); $modules = $this->config->module->toArray(); //reverse it in order to achieve the same stack pop order as in .ini $moduleOrder = array_reverse(explode(' ',$this->config->moduleOrder)); $this->logger->info($modules); foreach($moduleOrder as $module) { $settings = $modules[$module]; if($settings['active'] && $settings['navbar']) { $this->logger->warn('module navpane: ' . $module); $actionstack->actionToStack('navpane','index',$module /*, $this->getRequest()->getParams()/**/ ); } } /** * It can be done here, or in My_Controller_Action::preDispatch() * If done here, it is impossible not to have the default action triggered. * If done there, you can ensure you get an /default/index/index only if a * My_Controller_Action is instanced, which should provide a greater * flexibility later, That's why it's commented out [!]. */ $actionstack->actionToStack('index','index','default'); Zend_Registry::set('my_action_controller',array()); return $this; } ## the base class for actions Then, my base class for these actions (in the order pushed on the stack: /assessments/index/navpane, /forum/index/navpane, /default/index/index) looks like this <?php require_once 'Zend/Controller/Action.php'; class My_Controller_Action extends Zend_Controller_Action { protected $_isDirectCall = FALSE;//module/controller/action only if it has not already been done protected $_isStartAction = FALSE;//is the /default/index/index action /* * array containing three keys, each in the format 0 => module 1 => controller 2 => action * 'default' : what the front controller returns as "default homepage" * 'this' : this very object/request * 'url' : what is actually in the url */ private $_mvcs = NULL; public function preDispatch() { $logger = Zend_Registry::get('logger'); $mvc = $this->getMVCs(); $logger->info('BEGIN PREdispatching for action /' . implode('/',$mvc['this'])); $mvcs = $this->getMVCs(); if($mvcs['default'] === $mvcs['this']) {//startpage $this->_isStartAction = TRUE; $logger->info('IS DEFAULT'); } if($mvcs['this'] === $mvcs['url']) {//direct call $this->_isDirectCall = TRUE; $logger->info('IS DIRECT'); } $this->view->MVCs = $this->_mvcs; $this->view->isDirectCall = $this->_isDirectCall; $this->view->isDefaultAction = $this->_isStartAction; parent::preDispatch(); } public function postDispatch() { $logger = Zend_Registry::get('logger'); $mvc = $this->getMVCs(); $logger->info($mvc); $logger->info('END POSTdispatching for action /' . implode('/',$mvc['this'])); parent::postDispatch(); $this->_isDirectCall = FALSE; $this->_isStartAction = FALSE; } public function getMVCs() { $fc = Zend_Controller_Front::getInstance(); //$this->getFrontController(); if(!$this->_mvcs) { $this->_mvcs = array(); $this->_mvcs['default'] = array($fc->getDefaultModule(), $fc->getDefaultControllerName(), $fc->getDefaultAction()); // usually /default/index/index $t = $this->getRequest()->getParams(); $this->_mvcs['url'] = array($t['module'],$t['controller'],$t['action']);//this is what you see in the URL } $t = $fc->getRequest(); $this->_mvcs['this'] = array($t->getModuleName(),$t->getControllerName(),$t->getActionName());//the module/controller/action of this very object return $this->_mvcs; } } ## action view scripts navpane.html for my two modules, assessments and forum, look similar (only with different ID attributes, etc): <?php $this->placeholder('default_ui_navPane')->captureStart(); echo $this->accordionPane('assessments_navpane_navpane','automatically generated assessments pane', array('title' => 'Assessments')); $this->placeholder('default_ui_navPane')->captureEnd(); The placeholders are then echo'd in layout.phtml. ## test case and problems Considering the order of the modules ($modulesOrder in the POC above) being "assessments forum", everything works as expected if I go to the /assessments/index/index (or whichever is the first, if there are more modules), but when I visit /forum/index/index, it tries to generate two times the dijit div with the id assessments_navpane_navpane (or whichever is the previous on stack). What causes this and how to fix it in a clean way? To me personally, it looks like a "circular overwrite" of inherited object properties. ## additional info Also, if the modules are "assessments forum wiki", then /assessments works fine, /forum generates <div id="assessments_navpane_navpane" title="Assessments" dojoType="dijit.layout.AccordionPane">automatically generated forum pane</div> <div id="wiki_navpane_navpane" title="Wikis" dojoType="dijit.layout.AccordionPane">automatically generated wiki pane</div> and /wiki/index/index: <div id="forum_navpane_navpane" title="Forums" dojoType="dijit.layout.AccordionPane">automatically generated forum pane</div> <div id="forum_navpane_navpane" title="Forums" dojoType="dijit.layout.AccordionPane">automatically generated wiki pane</div> Where the message 'automatically generated '.$this->module.' pane' uses a variable defined in each navpaneAction() of my concrete subclasses of My_Controller_Action, like Forum_IndexController, etc. -- PS: yes, the question is 200 pts worth, since neither the official zend framework mailing list, nor the freenode irc channel or other "specialized" forums were helpful. |
|||
| By: VGR | Date: 17/02/2009 19:42:15 | Type : Comment |
|
| well, it's not as sexy as patie, but it's more legible when code parts are between [ code] and [ /code]... (the inline HTML editor has "QUOTE" and "CODE" buttons for such inclusions) as for the question, I've no clue, as I don't use those tools. I hope someone will be able to help you. Regards |
|||
| By: Flavius | Date: 18/02/2009 12:24:07 | Type : Comment |
|
| Yeah, I realized that just after posting, but I couldn't see any "edit" option. | |||
| By: Flavius | Date: 18/02/2009 12:28:53 | Type : Answer |
|
| After hours of debugging I've also realized the cause: Zend_View_Abstract::_script() uses cached paths. As such, it renders the navbar.phtml in the first directory it finds - which belongs to the 'navbar' controller first pushed on the stack - in this case the assessments module. So the first solution would be to name individually each action across all modules, like $actionstack->actionToStack('navpane'.$module,'index',$module); But that's not a clean, modular solution. Of course I've also tried to $view->setBasePath(), but there must be an exception somewhere. Hard to tell where, since all I get is a white page with not HTML generated. |
|||
| By: VGR | Date: 21/02/2009 07:40:09 | Type : Comment |
|
| seems a nice tool then ;-) (white page, hours of debugging, for a navbar) why do you use it ? there is no "edit" option, that is true. Experience on forums tells it would challenge many people's honesty :D But there are admins that can arrange or modify under their own responsibility. |
|||
|
Do register to be able to answer |
|||
©2010 These pages are served without commercial sponsorship. (No popup ads, etc...). Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE.
Please DO link to this page!








