2
votes

I have a view helper being called in my layout that works fine in the default module, but I get an exception when I am in another module.

I have already changed my app.ini to use the default layout across all modules by setting:

resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"

And searching here and google provided me with another app.ini setting to add the view helper path for all modules:

resources.view.helperPath.Zend_View_Helper = APPLICATION_PATH "/views/helpers"

However instead of fixing the problem, that additional setting causes the Zend Exception to become a WSOD.

Without that second app.ini setting, I see the layout and get this exception:

Plugin by name 'AutoScript' was not found in the registry; used paths: Admin_View_Helper_: /Applications/XAMPP/xamppfiles/htdocs/dad/application/modules/admin/views/helpers/ Zend_View_Helper_: Zend/View/Helper/:./views/helpers/

With the helperPath.Zend_View_Helper ini setting I get a WSOD with the following:

Fatal error: Uncaught exception 'Zend_Loader_PluginLoader_Exception' with message 'Plugin by name 'AutoScript' was not found in the registry; used paths: Zend_View_Helper_: Zend/View/Helper/:./views/helpers/' 

It appears the plugin loader is looking in public/views/helpers/ for the AutoScript.php file even though it should be using the APPLICATION_PATH value as a prefix.

My layout invocation looks like this

<?php $this->AutoScript(); ?>

My AutoScript.php file's class is defined in application/views/helpers/

class Zend_View_Helper_AutoScript extends Zend_View_Helper_Abstract {
  public function AutoScript() {...}
}

My current fix is to copy the AutoScript.php file from application/views/helpers into modules/admin/views/helpers which fixes the issue, but duplicates a file. What am I missing? Do I have to add this view helper path programmatically by creating an _initView function in my bootstrap?

1

1 Answers

1
votes

Typically, you would name your custom view helper with your own prefix, not the Zend_ prefix. Beyond that, there are several choices for where to put and name your view helpers.

If this view-helper is really a single-application helper, then I find it natural for it to reside somewhere in the application folder. Within that possibility space, I would ask if the view-helper will be used in a single module or across multiple modules.

If the view-helper is intended for use in a single module, then I depend upon the build-in resource-autoloader mappings and place my view-helper class Mymodule_View_Helper_Myhelper in the file application/modules/mymodule/views/helpers/Myhelper.php.

If the view-helper is intended for use across multiple modules , I might pull it up a little higher than the modules folder, say Application_View_Helper_Myhelper (assuming an appnamespace of Application) stored in application/views/helpers/Myhelper.php. In this case, we need to tell the view that there are helpers with prefix Application_View_Helper_ in that directory. This can be done at bootstrap:

protected function _initViewHelperPaths()
{
    $this->bootstrap('view');
    $view = $this->getResource('view');
    $view->addHelperPath(APPLICATION_PATH . '/views/helpers', 'Application_View_Helper_');
}

Sometimes, you need a view-helper in one module that exists in another module and you cannot - in practical terms - move the original one around. In that case, one workaround is to define an empty shell of a view-helper in your consuming module extending your unmovable view-helper. In file application/mymodule/views/helpers/MyHelper.php:

class Mymodule_View_Helper_Myhelper extends Othermodule_View_Helper_Myhelper
{
}

This way, the code for the helper implementation is not duplicated. The module-specific resource-autoloader mappings will allow all those classes to be found when they invoked as view-helpers from a view-script.

Finally, if this view helper is to be used in multiple projects, then there is an argument for placing it outside of application scope, out in in the library folder. So perhaps a class MyLibrary_View_Helper_Myhelper stored in the file library/MyLibrary/View/Helper/Myhelper.php. As before, you would need to inform the view - probably at bootstrap or in a front-controller plugin - of the prefix/path mapping:

$view->addHelperPath(APPLICATON_PATH . '/../library/MyLibrary/View/Helper', 'MyLibrary_View_Helper_');

Note that in all cases above, the invocation of the view-helper functionality itself - say, inside a view-script - is:

<?php echo $this->myhelper($params) ?>

Note, in particular, the casing difference between the classname and the invocation.