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

Reply via email to