During my research, I found a convenient way to work with html blocks on the site. Almost every site has a number of blocks that should be present on some pages and absent on others. So, you need a flexible tool for managing the blocks.
I will present my vision of how to manage the blocks under Zend Framework.
Here is the idea.
All available blocks are listed in blocks.ini config. This allows easily to see all the blocks in one place.
I’ll show how looks blocks.ini config. For example, we have config with two defined blocks, the toolbar block and the banner block:
[toolbar]
module=application
controller=toolbar
action=index
[banner]
module=application
controller=banner
action=show
As we can see, each block have specified module, controller and action. We can see where the block will get its data.
All we need to work with blocks is a action controller helper, front controller plugin and blocks.ini config.
With the action helper we specify blocks that will be loaded into layout or unloaded from layout. Front controller plugin directly controls the blocks loading, which occurs immediately after the dispatch of the controller.
So, let’s see to action helper code:
/**
* @author http://torqueo.net/
*/
class Project_Controller_Action_Helper_Block extends Zend_Controller_Action_Helper_Abstract
{
/**
* An instance of Project_Controller_Plugin_Block plugin
* @var object
*/
protected $_blocksPlugin = null;
/**
* Initialize Project_Controller_Plugin_Block plugin
* and blocks config
*/
public function init()
{
$front = Zend_Controller_Front::getInstance();
if (!$front->hasPlugin('Project_Controller_Plugin_Block')) {
$this->_blocksPlugin = new Project_Controller_Plugin_Block();
$front->registerPlugin($this->_blocksPlugin, 93);
} else {
$this->_blocksPlugin = $front->getPlugin('Project_Controller_Plugin_Block');
}
$blocksConfig = new Zend_Config_Ini(APPLICATION_PATH . "/config/blocks.ini");
$this->_blocksPlugin->setConfig( $blocksConfig );
}
/**
* Add block on page by block name
* @param string $blockName
*/
public function add($blockName)
{
$this->_blocksPlugin->add($blockName);
}
/**
* Remove block from page by block name
* @param string $blockName
*/
public function remove($blockName)
{
$this->_blocksPlugin->remove($blockName);
}
/**
* Remove all blocks from page
*/
public function removeAll()
{
$this->_blocksPlugin->removeAll();
}
}
Then let’s look at the front controller plugin, which controls the blocks loading into layout.
/**
* @author http://torqueo.net/
*/
class Project_Controller_Plugin_Block extends Zend_Controller_Plugin_Abstract
{
/**
* Here's a states for each block (enabled or disabled)
* @var array
*/
protected $_blocks = array();
/**
* Blocks config with specified module, controller
* and action for each block
* @var array
*/
protected $_config = array();
/**
* Enable block by block name (set enabled flags)
* @param string $blockName
* @return void
*/
public function add($blockName)
{
$this->_blocks[ $blockName ] = true;
}
/**
* Disable block by block name (set disabled flags)
* @param string $blockName
* @return void
*/
public function remove($blockName)
{
$this->_blocks[ $blockName ] = false;
}
/**
* Disable all blocks (set disabled flags to all)
* @param string $blockName
* @return void
*/
public function removeAll()
{
foreach ($this->_blocks as $blockName=>$blockEnabled) {
$this->_blocks[ $blockName ] = false;
}
}
/**
* Hook on postDispatch event. Disable or enable blocks.
* @param Zend_Controller_Request_Abstract $request
* @return void
*/
public function postDispatch(Zend_Controller_Request_Abstract $request)
{
if (!$request->isXmlHttpRequest() && !empty($this->_config)) {
$this->_layout = Zend_Layout::getMvcInstance();
$this->_view = $this->_layout->getView();
foreach ($this->_config as $blockName=>$options) {
if (isset($this->_blocks[ $blockName ]) && $this->_blocks[ $blockName ] === true) {
$this->_layout->{$blockName} = $this->_view->action(
$options['action'],
$options['controller'],
$options['module'],
$request->getParams()
);
}
}
}
}
/**
* Set blocks config
* @param Zend_Config $config
* @return void
*/
public function setConfig(Zend_Config $config)
{
$this->_config = $config->toArray();
}
}
As a result, in any controller of our application, we can work with blocks like this:
class NewsController extends Zend_Controller_Action
{
public function preDispatch()
{
// Add toolbar block on page
$this->_helper->block->add('toolbar');
// Add banners block on page
$this->_helper->block->add('banner');
}
public function viewNews()
{
// Disable banners block in this action
$this->_helper->block->remove('banner');
// ... or disable all blocks
$this->_helper->block->removeAll();
}
}
We can output any block in layout by block name:
<?=$this->layout()->toolbar?>
<?=$this->layout()->banner?>
By comments in the code should be clear how to work with blocks. You can even add to the action helper addAll() method to be able to load all the blocks at once, in a contrast to the removeAll() method - but it’s on your taste.
Also interesting
Tags: Action Controller Helper, Blocks, zend framework, ZF, zf front controller plugin, zf layout
This is a very good idea. In magento, it uses a very similar idea. thats when I found your code becouse I was trying to implement something similar. GOOD JOB!
exactly what i was looking for, i havent done any project in zendframework till now but have worked in magento the block concept of magento is really great i wanted to implement it in ZF
Great idea,
I think that it’s an elegant way to handle it.
Thanks for sharing.