Issues

ZF-8611: Zend_navigation should support different containers

Description

In my case I want create a head navigation and main navigation with Zend_Navigaiton with plugins. The head and main naviagtion is created my themselves. So they have no connection with each other. So it would be good that Zend_Navigation supports more than one container because I also want use all the functionality of this component.

Here is some example code how I want create these navigations. Here I load the data from a model in the background.

head navigation:

<?php

    class Plugin_NavigationHead extends Zend_Controller_Plugin_Abstract {

        public function preDispatch(Zend_Controller_Request_Abstract $request){

            $container = new Zend_Navigation();

$view = Zend_Layout::getMvcInstance()->getView();            

            $container->addPage(array("label" => "MainMenu",
                                         "module" => "default",
                                           "controller" => "index",
                                         "action" => "index"));

            $container->addPage(array("label" => "Submenu",
                                               "module" => "default",
                                            "controller" => "index",
                                          "action" => "index"));

            $container->addPage(array("label" => "NextSubMenu",
                                               "module" => "default",
                                            "controller" => "index",
                                          "action" => "index"));

            $view->navigation_head = $view->navigation($container)
                                     ->breadcrumbs()
                                  ->setSeparator(" -> ")->render();

    }
    }

?> 

main navigation:

<?php

    class Plugin_NavigationMain extends Zend_Controller_Plugin_Abstract {

        public function preDispatch(Zend_Controller_Request_Abstract $request){

$view = Zend_Layout::getMvcInstance()->getView();

            $container = new Zend_Navigation();
                        
            $container->addPage(array("label" => "Main-Menu",
                                        "module" => "default",
                                         "controller" => "index",
                                     "action" => "index"));

            $container->addPage(array("label" => "Main-Submenu",
                                        "module" => "default",
                                     "controller" => "index",
                                        "action" => "index"));

            $view->navigation_head = $view->navigation($container)->menu()->render();

    }
    }

?> 

in my layout file I try to view these navigation but like I wrote above only the main menu is rendered.

layout.phtml file:

<?= $this->navigation_main; ?>
<?= $this->navigation_head; ?>

But the problem is that only the main menu is rendered but not the breadcrumbs navigation. This support of different containers should only be activated if the navigation()-method was set more than one time. For the other case everything could be like now.

Comments

Hi Hans, I can not reproduce your problem.


// Navigation
$containerOne = new Zend_Navigation(array(
    array(
        'label' => 'Home',
        'uri'   => 'home',
    ),
    array(
        'label' => 'Contact',
        'uri'   => 'contact',
    ),
    array(
        'label' => 'Imprint',
        'uri'   => 'imprint',
    ),
));

$containerTwo = new Zend_Navigation(array(
    array(
        'label' => 'Products',
        'uri'   => 'products',
        'pages' => array(
            array(
                'label'  => 'DVD',
                'uri'    => 'dvd',
                'active' => true,
            ),
            array(
                'label' => 'Games',
                'uri'   => 'games',
            ),
        ),
    ),
));

// View
$view = new Zend_View();

// Render
echo $view->navigation($containerOne)->menu();
echo $view->navigation($containerTwo)->breadcrumbs();

Home Products > DVD

You need a parent and an activated page. Or you can use the "minDepth":


$containerTwo = new Zend_Navigation(array(
    array(
        'label' => 'Products',
        'uri'   => 'products',
        'active' => true,
        'pages' => array(
            array(
                'label' => 'DVD',
                'uri'   => 'dvd',
            ),
            array(
                'label' => 'Games',
                'uri'   => 'games',
            ),
        ),
    ),
));

echo $view->navigation($containerTwo)->breadcrumbs()->setMinDepth(0);

Products

If you want to use the same helper with different containers, then the following must be respected:

You must set the container not for the proxy helper "Navigation". Set the container to the concrete helper (e.g. "Menu", "Breadcrumbs", ...).


// Render
echo $view->navigation()->menu($containerOne);
echo $view->navigation()->menu($containerTwo);

ul class="navigation">
    
        Home
    
    
        Contact
    
    

        Imprint
    


Products DVD Games

During loading a helper the container is set to the new concrete navigation helper (e.g. "Menu", "Breadcrumbs", ...). But when the helper is loaded, then no new container is set/inject.


public function findHelper($proxy, $strict = true)
{
    if (isset($this->_helpers[$proxy])) {
        return $this->_helpers[$proxy];
    }

    // ...

    $this->_inject($helper);
    $this->_helpers[$proxy] = $helper;

    return $helper;
}

protected function _inject(Zend_View_Helper_Navigation_Helper $helper)
{
    if ($this->getInjectContainer() && !$helper->hasContainer()) {
        $helper->setContainer($this->getContainer());
    }

    // ...
}