As a follow up to my previous post on per module based layout settings for Zend Framework, I’ve updated the code to require less configuration then before (not that it required more that a few lines in your application configuration!).
Again we make use of a Zend Controller Action Helper invoking it from the bootstrap as follows:
/** * Sets up layout scripts on a per-module basis */ protected function _initLayoutHelper() { $this->bootstrap('frontController'); $layout = Zend_Controller_Action_HelperBroker::addHelper( new Pro_Controller_Action_Helper_SetLayoutPath(APPLICATION_PATH)); }
Almost exactly the same as before except this time we pass the constant APPLICATION_PATH into the constructor as our base path.
Next the controller action helper itself now looks as follows:
/** * Sets the layout path on a per-module basis * * @author Lloyd Watkin * @since 16/02/2010 * @package Pro * @subpackage Controller_Action_Helper */ /** * Sets the layout path on a per-module basis * * @author Lloyd Watkin * @since 16/02/2010 * @package Pro * @subpackage Controller_Action_Helper */ class Pro_Controller_Action_Helper_SetLayoutPath extends Zend_Controller_Action_Helper_Abstract { /** * Base path * * @var string */ protected $_path; /** * Construct * * @param string $path */ public function __construct($path) { $this->setBasePath($path); } /** * Set base path * * @param string $path */ public function setBasePath($path) { if (!is_string($path) || empty($path)) { throw new Exception('Excepted string for base path'); } $this->_path = $path; } /** * Get the base path * * @return string */ protected function _getBasePath() { if (is_null($this->_path)) { if (!defined('APPLICATION_PATH')) { throw new Exception('Base path can not be determined'); } $this->_path = APPLICATION_PATH; } return $this->_path; } /** * Sets layout path based on module */ public function preDispatch() { $module = preg_replace( '/[^A-Z]/i', '', $this->getRequest()->getModuleName() ); if ($bootstrap = $this->getActionController() ->getInvokeArg('bootstrap')) { $view = $bootstrap->getResource('view'); $layoutPath = $this->_getBasePath() . "/modules/{$module}/layouts/scripts/"; /* If layout directory exists then apply it, otherwise just fall * back on the default */ if (is_dir($layoutPath)) { $this->getActionController() ->getHelper('layout') ->setLayoutPath($layoutPath); $view->headLink()->appendStylesheet( "/styles/{$module}/style.css" ); } } } }
Note the passing of our base path (cf. APPLICATION_PATH) in the constructor, we also have a getter and setter for the base path. Unlike the previous version of the code if the layouts path does not exist then the code will fall back the default layout path. If the base path is not set it will try to determine the base path from the constant APPLICATION_PATH, otherwise an exception is thrown. I’ve also cheekily thrown in a module-based style sheet for good measure
The module based layout is determined from whether the layout script path exists (obviously this method can be changed easily). This does add a little overhead from the application.ini setup (however if the layout path exists PHP will cache the result for performance*) but in return you gain the added convenience of more easily dropping in new modules.
That’s it, not much different, but you don’t need to add a new configuration entry each time you wish to add a new module :)
*To clear this cache (if required) use the clearstatcache function.