Zend Framework Action Helpers and Namespaces
In my current Zend Framework project, I am using PHP 5.3’s namespaces for all my library code (It makes sense considering I’m using Doctrine 2 and will attempt to upgrade to ZF 2 when it’s released). I have come across a few compatibility issues when trying to use namespaces, mostly with Zend’s PluginLoader and Phing. Below is how I have my action helpers setup:
site/
library/
Cob/
Controller/
Action/
HelperBroker.php
Helper/
Myhelper.php
HelperAbstract.php
HelperBroker.php
<?php
namespace Cob\Controller\Action;
use \Zend_Controller_Action_HelperBroker;
/**
* Custom implementation of the HelperBroker to provide namespace support
*
* @author Andrew Cobby
*/
class HelperBroker extends Zend_Controller_Action_HelperBroker {
/**
* Add a namespace prefix (works the same as Zend_Helper_BrokerBroker::addPrefix()
*
* @param string $prefix Namespace prefix
*/
static public function addNamespacePrefix($prefix)
{
$prefix = rtrim($prefix, '\\') . '\\';
$path = str_replace('\\', DIRECTORY_SEPARATOR, $prefix);
$path = rtrim($path, '/');
self::getPluginLoader()->addPrefixPath($prefix, $path);
}
/**
* Adds an array of helpers
*
* @param array $helpers Helpers
*/
static public function addHelpers(array $helpers)
{
foreach($helpers as $helper){
parent::addHelper($helper);
}
}
}
HelperAbstract.php
<?php
namespace Cob\Controller\Action\Helper;
use \Zend_Controller_Action_Helper_Abstract;
/**
* Abstract helper for namespaced action helpers
*
* @author Andrew Cobby
*/
class HelperAbstract extends Zend_Controller_Action_Helper_Abstract
{
/**
* Fix to get the correct helper name (Overrides Zend_Controller_Action_HelperAbstract::getName)
*
* @return string
*/
public function getName()
{
$className = get_class($this);
if(strpos($className, '\\') !== false){
$helperName = strrchr($className, '\\');
return ltrim($helperName, '\\');
}elseif(strpos($className, '_') !== false){
$helperName = strrchr($className, '_');
return ltrim($className, '_');
}else{
return $className;
}
}
}
Myhelper.php
<?php
namespace Cob\Controller\Action\Helper;
/**
* Example helper that uses namespaces
*
* @author Andrew Cobby
*/
class Myhelper extends HelperAbstract
{
public function direct()
{
return 'Namespaces are cool!!';
}
}
Before you starting using this, you will need to add your namespace prefix in our new HelperBroker:
<?php
namespace Cob\Controller;
use \Zend_Controller_Action;
use \Cob\Controller\Action\HelperBroker as HelperBroker;
class Action extends Zend_Controller_Action
{
public function preDispatch()
{
HelperBroker::addNamespacePrefix('Cob\Controller\Action\Helper\\'); // remember 2 trailing slashes to fix the escaping
$coolio = $this->_helper->Myhelper(); // calling a helper is still the same
}
}
As you can see, the only real part of the compatibility issue is overriding HelperAbstract::getName(), the methods in HelperBroker are more just for convenience.
Hope this helps!