In an application that I'm creating, I have the need to have all view
scripts (including those for modules) in a non-standard directory, as well
as change the default extension. The relevant directory structure would look
like this:
<base path>/
application/
modules/
ModuleName/
public/
Templates/
zf-views/
module-name/
index/
index.tpl.php
error/
error.tpl.php
I've decided to use a controller plugin to do this globally:
<?php
class Emg_Plugin_View extends Zend_Controller_Plugin_Abstract
{
/**
* @var Zend_Controller_Action_Helper_ViewRenderer
*/
protected $_view_renderer;
/**
* Sets the view script extension and the base script path before
routing
* occurs.
*
* This is done so that, if there's a routing error (e.g. invalid
module,
* controller, or action), the view script for the error controller can
be
* found.
*
* We can't check for the requested module and adjust the path
accordingly
* because that information hasn't been extracted from the requested URI
at
* this point.
*
* @param Zend_Controller_Request_Abstract $request
* @return void
*/
public function routeStartup( Zend_Controller_Request_Abstract $request
)
{
$this->_getViewRenderer()->setViewSuffix( 'tpl.php' );
$this->_getView()->setScriptPath( PUBLIC_PATH .
'/Templates/zf-views' );
}
/**
* Adjusts the script path for modules.
*
* @param Zend_Controller_Request_Abstract $request
* @return void
*/
public function dispatchLoopStartup( Zend_Controller_Request_Abstract
$request )
{
if( 'default' != $request->getModuleName() ) {
$this->_getView()->setScriptPath( PUBLIC_PATH .
'/Templates/zf-views/' . $request->getModuleName() );
}
}
/**
* @return Zend_Controller_Action_Helper_ViewRenderer
*/
protected function _getViewRenderer()
{
if( null === $this->_view_renderer ) {
$this->_view_renderer =
Zend_Controller_Action_HelperBroker::getStaticHelper( 'ViewRenderer' );
}
return $this->_view_renderer;
}
/**
* @return Zend_View_Interface
*/
protected function _getView()
{
return $this->_getViewRenderer()->view;
}
}
The problem I'm running into is that if a non-existent controller or action
is requested in the ModuleName module (let's say /module-name/foo), I get
the following exception:
Fatal error: Uncaught exception 'Zend_View_Exception' with message 'script
'error/error.tpl.php' not found in path (<base
path>/application/views/scripts/:<base
path>/htdocs/Templates/zf-views/module-name/)' in <base
path>/library/Zend/View/Abstract.php:980
Stack trace:
#0 <base path>/library/Zend/View/Abstract.php(876):
Zend_View_Abstract->_script('error/error.tpl...')
#1 <base path>/library/Zend/Controller/Action/Helper/ViewRenderer.php(898):
Zend_View_Abstract->render('error/error.tpl...')
#2 <base path>/library/Zend/Controller/Action/Helper/ViewRenderer.php(919):
Zend_Controller_Action_Helper_ViewRenderer->renderScript('error/error.tpl...',
NULL)
#3 <base path>/library/Zend/Controller/Action/Helper/ViewRenderer.php(958):
Zend_Controller_Action_Helper_ViewRenderer->render()
#4 <base path>/library/ in <base path>/library/Zend/View/Abstract.php on
line 980
Not surprisingly, given the code above, it's trying to look for the error
view script in ModuleName's view script path. What I need to do is, in
dispatchLoopStartup(), forgo updating the script path with the module name
if there's been a routing error. I'm just not sure how to go about that.
I've tried both of the following if conditions...
if( 'default' != $request->getModuleName() && 'error' !=
$request->getControllerName() ) {
...and...
if( 'default' != $request->getModuleName() && null === $request->getParam(
'error_handler' ) ) {
...but neither have solved my problem.
Any help would be appreciated. Any suggestions on how to handle the
situation in general more elegantly would also be appreciated. ;o)
Thanks,
Ryan Lange