Dynamically add pages to Zend_Navigation container at runtime
In a continuation on my last post about Zend_Navigation, Route requests for sitemap.xml to custom controller/action, this post is about dymnamically adding pages to a Zend_Navigation container at runtime/script execution.
Its all well and good specifying your pages in a ini or xml file but at some point you’re going to have changing pages in your site that you want as part of a menu, sitemap, or to be included in your breadcrumb trail. Therefore what we need to do is add pages to our Zend_Navigation container at runtime. Examples for this would be in adding news items, blog posts, or page comments, etc.
In this example I’m going to add some news posts to my statically defined ini config. To get my news post page configurations I’ve used a class which returns an array in the following format:
$pagesToAdd = array (
0 =>
array (
'label' => 'Fake news story #5...',
'module' => 'www',
'route' => 'www-index',
'action' => 'view',
'controller' => 'news',
'params' => array (
'id' => '5-Fake-news-story--5' )
),
1 =>
array ( /* More page details */ ),
);
As you’ll notice that the function has returned an array in which are contained arrays which make up the config arrays for Zend_Navigation_Page_Mvc. Therefore, by looping over the array new Zend_Navigation pages can be created from the config array. The next thing to do as part of the loop is to to add the pages in the correct position (alternatively pages can be added in bulk by using ->addPages() method).
To do this, locate the page you wish to add the sub-pages to and simply add the pages. In this case I have used the following code to find my page:
$container->findOneBy('label', 'Latest News')->addPage($page);
My overall navigation initialisation in the bootstrap therefore looks like this:
/**
* used for handling top-level navigation
*
* @return Zend_Navigation
*/
protected function _initNavigation()
{
$this->bootstrap('layout');
$layout = $this->getResource('layout');
$view = $layout->getView();
$config = new Zend_Config_Ini(
APPLICATION_PATH . '/configs/navigation.ini', APPLICATION_ENV);
$container = new Zend_Navigation($config->default);
// Now add the last 25 news reports
$news = new News();
$pages = $news->getNavigationEntries();
foreach ($pages AS $page) {
$page = new Zend_Navigation_Page_Mvc($page);
$container->findOneBy('label', 'Latest News')->addPage($page);
}
$view->navigation($container);
}
On thing that needs to be added is some form of caching (using Zend_Cache presumably ;)) otherwise this is going to be quite expensive with each page load.
















































That’s just what i was looking for – thanks for a really clear example. Cheers. G
Nice post! I’ve some trouble initiating a model class in the bootstrap. Any clue why application/model classes are not available from the bootstrap? Your class is called ‘new News()’, instead I’d like to add the navigation pages by getting a navigation tree from a model class. If you have an idea, please let me know! ;)
My model was edited for the post, its correct name in the code is Pro_News and is picked up by the autoloader.
Guessing you’re not using modules? But if so your model should be called _News for ZF to pick up by default (I don’t use this system myself).
I’d suggest checking the include path from your bootstrap method to see if it contains “application/models” or include the file manually.
Well I use modules, my bad. But you suggest autoloading should work? Well, I’ve to dig into it a bit deeper. At the moment I use the addPage function in the BaseControllers, which is not really performance friendly…hehe. Thanks for your reply.
Ensure your module model is named correctly_News (for example) and it should pick up using autoloading.
My model was edited for the post, its correct name in the code is Pro_News and is picked up by the autoloader.
Guessing you’re not using modules? But if so your model should be called_News for ZF to pick up by default (I don’t use this system myself).
I’d suggest checking the include path from your bootstrap method to see if it contains “application/models” or include the file manually.