Zend Navigation: Breadcrumbs minimum depth

Creating breadcrumbs with Zend Framework is really easy:

  1. Create a menu structure (ini file, php array, …)
  2. add a small peace of code in the view file: “echo $this->navigation()->breadcrumbs()”
  3. open your page and you see… nothing

This is what happened to me on the home page of my most recent project.  All though the ZF manual indicates you just have to echo the breadcrumbs, nothing appeared.

The problem was this: my menu started at level zero, and ZF sets the minimum level that will be displayed to one. Luckily there is the documentation, but it is really annoying that the method “setMinDepth()” is not in the API, so it took me much longer to find out this method existed.

Implementing a menu with Zend_Navigation

A few weeks ago I saw a very good ZendCast about Zend_Navigation.

This was a very good start for me to use Zend_Navigation for the menu and breadcrumbs in my application.

Performance

While developing there were some performance issues that came up:

  1. parsing a .ini or .xml file makes the application slower
  2. for Ajax-requests, the menu should not be loaded

The solution for the first problem is a simple array. I created a function getMenu() that returns a Zend_Navigation object, and this object contains my menu array. The array is less readable than a .ini or .xml file, I have to admit, but it’s still very easy to work with.

private function getMenu()
{
    return new Zend_Navigation(array(
        array(
            'label' => 'Home',
            'id' => 'home',
            'visible' => false,
            'controller' => 'index',
            'action' => 'index'
        ),
        array(
            'label' => 'Page 1',
            'id' => 'page_1',
            'uri' => '',
            'pages' => array(
                array(
                    'label' => 'Page 1.1',
                    'id' => 'page_1_1',
                    'controller' => 'general',
                    'action' => 'index'
                )
            )
        )
    ));
}

For the second problem I had to dig a little bit deeper into Zend Framework.
Normally the Zend_Layout and Zend_View are created in the bootstrap. And this is also the place where I would initialize Zend_Navigation.
For an Ajax request, I disable the layout.

$this->_helper->layout->disableLayout();
$this->getHelper('viewRenderer')->setNoRender();

Does it make sense to first create the layout and view, then add the menu to the view, and afterwards disable the layout if the application do an Ajax request?

My solution was this: I created a plugin for the menu. This plugin checks if the layout is enabled or disabled, and only creates the menu when the layout is enabled. The plugin uses the postDispatch method, because only then the layout can be checked if it is enabled or disabled. In the preDispatch it is always enabled.

public function postDispatch(Zend_Controller_Request_Abstract $request)
{
    $layout = Zend_Layout::getMVCInstance();
    $view = $layout->getView();
 
    if ($layout->isEnabled() && Zend_Auth::getInstance()>hasIdentity()) {
        $view->navigation($this->getMenu());
    }
}

Difference between URI and MVC

This is a very simple difference.

Zend_Navigation_Page_Mvc uses the parameters “controller” and “action” to create the anchors in the menu.
Zend_Navigation_Page_Uri uses the “uri” parameter the create the anchor.

I use only Mvc to create my anchors.
I use the Uri for one case: if I want a menu item that has no anchor. If the “uri” parameter is left blank, Zend_Navigation will display the label, but it will not create anchor tags around it, so you can create a nice menu with menu titles that are not linkable, and menu items with links underneath