Dynamically add pages to Zend_Navigation container at runtime

By , Thursday 7th January 2010 10:50 pm

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.

Liked this post? Follow this blog to get more. 

6 Responses to “Dynamically add pages to Zend_Navigation container at runtime”

  1. Mr Man says:

    That’s just what i was looking for – thanks for a really clear example. Cheers. G

  2. A387 says:

    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.

  3. 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.

Leave a Reply

You must be logged in to post a comment.

Panorama Theme by Themocracy

3 visitors online now
0 guests, 3 bots, 0 members
Max visitors today: 7 at 12:42 am UTC
This month: 31 at 09-06-2017 03:33 pm UTC
This year: 45 at 02-01-2017 10:28 pm UTC
All time: 130 at 28-03-2011 10:40 pm UTC