|
Been having a nightmare trying to use a completely custom view scripts location, combined with having noViewRenderer=true by default in Zend_Controller_Front, but then switching it on for certain action controllers via a routeShutdown plugin hook.
I'm know the noViewRenderer param gets passed through to the dispatcher, hence toggling it at the routeShutdown stage. I can test at various other points below the dispatcher (i.e. in the action controller) that if I've set noViewRenderer=false, this appears to persist down to the action controller level. I want to set a completely custom path to my view scripts, so I can't use the default view scenario which gets set up by the viewRenderer action helper, as it seems to test for the presence of a view scripts folder according to the 'stock' folder structure. So I tied replacing the initView() method of my action controller thus: public function initView () { $this->view = new Zend_View(array('basePath' => APPLICATION_PATH . '/custom/path/to/views/')); $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view); $this->_helper->addHelper($viewRenderer); // even slightly on track?!?! return $this->view; } I'm then trying all sorts in my action method to try and get the view working. I can get the view scripts loaded and rendered no problem. But whatever I try, the view object that my view script sees somehow doesn't have any of the vars I've assigned it in the controller - i.e. it looks to be a different view object altogether.. public function indexAction () { $this->initView(); // tried both with and without this, in various permutations $this->view->myvar = 'hello world'; $this->view->render('somescript'); // tried this, with or without .phtml // OR $this->render(); // ..also tried this } The direct Zend_Controller_Action::render() version seems to use code within the viewRenderer helper to work out what view script it should load, and whether it exists or not. Conversely, the $this->view->render() approach uses the view object's native methods to do the same. Neither is playing ball for me it would seem. Things might go wrong within the ::_script() private method of the Zend_View_Abstract class from my extensive problem-hunting (stab in the dark) investigations. Can anyone help? I basically want to: - have noViewRenderer=true (M & C, but no V) by default, but for selected actions/controllers I need to use a view and view scripts - have completely custom paths to where my view scripts are located in my bespoke folder structure ...can it be that hard? Jon |
|
I would approach this problem differently:
1) Use application.ini to set up your custom view script path resources.view.basePath = APPLICATION_PATH "/custom/path/to/views/" 2) Use the plugin to disable the view renderer as necessary $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); $viewRenderer->setNoRender(true); // disable view rendering Then you can wrap that in your logic to decide whether views should be rendered. I hope this helps. -- *Hector Virgen* Sr. Web Developer http://www.virgentech.com --
Hector Virgen |
|
Thanks Hector. Couple of further questions..
Is there another way to state this setting globally without using an INI file? The problem is that I need to generate this path *dynamically*, as the ZF entry-point is within a shared codebase. Questions on this would be: - Would this work at the Zend_Controller_Action::preDispatch() level, or is that too late? (assuming the above would normally be in the front controller plugin routeShutdown() method). My thinking would be to create a base action controller with this in preDispatch() which I can subclass for whatever action controllers need this logic. - Will this work just as well with inverted logic/booleans, i.e. Zend_Controller_Front->setParam('noViewRenderer')=true; and then $viewRenderer->setNoRender(false); in the routeShutdown() or action controller preDispatch() ?? Jonny |
|
On Sat, Mar 5, 2011 at 2:11 AM, jonnott <[hidden email]> wrote:
> Is there another way to state this setting globally without using an > INI file? The problem is that I need to generate this path *dynamically*, as > the ZF entry-point is within a shared codebase. Yes, you can bootstrap your view instance and then pull it from the bootstrap to modify it. This ensures that you are accessing and modifying the same view instance throughout your application. To make sure your view is bootstrapped, add at least one configuration option to application.ini. If you want to use all the defaults, then pass in an empty config: # application/configs/application.ini ; Bootstraps the view with default values resources.view[] = Then, you can pull the view from the bootstrap from within an action controller like this: # application/controllers/IndexController.php public function init() { $bootstrap = $this->getInvokeArg('bootstrap'); $view = $bootstrap->getResource('view'); } From that point you can then add your custom view script paths: $view->addScriptPath('path/to/my/view/scripts'); Would this work at the Zend_Controller_Action::preDispatch() level, or > is that too late? (assuming the above would normally be in the front > controller plugin routeShutdown() method). Automatic view script rendering occurs during postDispatch, so swapping paths in preDispatch or even within your action body should work. In my example above I used init, which occurs before preDispatch. My thinking would be to create a base action controller with this in > preDispatch() which I can subclass for whatever action controllers need this > logic. If you find that you need to provide this functionality in more than one action controller, I suggest using action helpers instead of creating a base action controller. The problem with base action controllers is that they tend to get bloated with some functionality for controllers A, B, and C and other functionality for controllers D, E, and F. Maintaing this can become problematic and often requires a large ugly switch. Action helpers allow you to take that bit of functionality and encapsulate it in its own class, allowing you to use it on-demand from any action controller. For more info on action helpers check out the docs: http://framework.zend.com/manual/en/zend.controller.actionhelpers.html Will this work just as well with inverted logic/booleans, > i.e. Zend_Controller_Front->setParam('noViewRenderer')=true; and > then $viewRenderer->setNoRender(false); in the routeShutdown() or > action controller preDispatch() Setting the param "noViewRenderer" to true prevents the front controller from registering the view renderer helper entirely, but in your case I believe you want it registered but simply not performing any automatic view script rendering. So I would go with my original suggestion of leaving the view renderer there (because you might need it), disabling automatic view rendering (a property of the view renderer itself), and then re-enabling it when required. -- *Hector Virgen* Sr. Web Developer http://www.virgentech.com --
Hector Virgen |
|
In reply to this post by jonnott
May be this can be useful to you:
http://stackoverflow.com/q/5210475/605093 I need to test this idea in real application though. |
|
The way I usually handle this:
- I register a Layout Plugin, extending Zend_Layout_Controller_Plugin_Layout - I use the preDispatch hook to determine what module, controller, action I am in - I switch between layouts and views depending on the context For me, that's by far the easiest method. GJ
|
|
In reply to this post by Hector Virgen
Seems the major problem with ZF 1.x MVC is that you cannot do away with the directory structure it imposes on you! This is getting annoying..
I'm trying to use ZF in the context of a legacy codebase, and am in no way using the default assumed directory structure in any part of my app. I already had to subclass the Dispatcher in order to not follow its assumptions about where action controller classes would be loaded from. Now it appears I'm probably going to have to do the same with the viewRenderer just in order to use it to render views with my custom-located view scripts. So, in my FC plugin I'm doing the following: public function routeShutdown () { $view = new Zend_View(); $view->setBasePath('/completely/custom/path/to/views'); $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); $viewRenderer->setView($view)->setNoRender(true); } Which sets the paths fine within the $view object, which in turn gets assigned to the viewRenderer (setView) ok. But then when I do a request, to any controller/action, with setParam('noViewRenderer',false) on the FC, I get the following exception and trace: Fatal error: Uncaught exception 'Zend_Controller_Action_Exception' with message 'ViewRenderer cannot locate module directory for module "default"' in /library/Zend/Controller/Action/Helper/ViewRenderer.php:249 Stack trace: #0 /library/Zend/Controller/Action/Helper/ViewRenderer.php(287): Zend_Controller_Action_Helper_ViewRenderer->getModuleDirectory() #1 /library/Zend/Controller/Action/Helper/ViewRenderer.php(381): Zend_Controller_Action_Helper_ViewRenderer->getInflector() #2 /library/Zend/Controller/Action/Helper/ViewRenderer.php(469): Zend_Controller_Action_Helper_ViewRenderer->_getBasePath() #3 /library/Zend/Controller/Action/Helper/ViewRenderer.php(516): Zend_Controller_Action_Helper_ViewRenderer->initView() I don't HAVE a module directory, that's why! I don't even want to have a module directory! I just want it to look at the custom view script path I've set in the view object it encapsulates, and then use the scripts it finds there to render the views. Can it be that difficult?? Is there no way I can use the viewRenderer in this way without subclassing it? Am I stuck with having to manually maintain an app-wide view object myself, and manually configure/render it within each controller's actions? Jon |
|
In reply to this post by jonnott
Hi I know my response a bit late but just incase someone is reading the thread so he would get it.
I'd solve the above issue as below. In my action controller I'd add addScriptPath to the shared directory I'd like to have my views in, the I'd use render Script # Path to a shared folder which located out of the scripts/views folder. $this->view->addScriptPath('library/CMS/view/'); # Render the generic index page which locate inside generic which is inside library/cms.view $this->renderScript('generic/index.phtml'); Mazen |
| Powered by Nabble | See how NAML generates this page |
