ZF2 Dynamic Menu with Zend\Navigation\Navigation

13,475

Solution 1

Follow these easy steps to create the multilevel menu dynamically Step 1:create a partial menu.phtml file and save it in layout folder or the module,eg application/view/layout/menu.phtml

 <ul  id="menu" >

    <?php foreach ($this->container as $page): ?>

        <li <?= $page->isActive()? 'class="active"' : 'class="drop"' ?>>

            <?php echo $this->navigation()->menu()->htmlify($page). PHP_EOL ?>

     <div class="dropdown_2columns" >


                           <?php  foreach ($page as $catpage) :?>

                    <div  class="col_1" >

                              <h3 <?= $page->isActive()? 'class="active"' : 'class="drop"' ?> >
            <?= $this->navigation()->menu()->htmlify($catpage). PHP_EOL ?>
                   </h3>
                        <ul  >

                           <?php  foreach ($catpage as $subpage) :?>

                           <li  <?= $subpage->isActive()? 'class="active"' : 'class="drop"' ?>>
            <?= $this->navigation()->menu()->htmlify($subpage). PHP_EOL ?>


                           <?php endforeach; ?>
                        </ul>   

                    </div>

                      <?php endforeach; ?>

                </div><!-- End dropdown container -->

                    </li>

                <?php endforeach; ?>
 </ul>

Step 2 in your module.php

public function getServiceConfig()
    {
        return array(
                'initializers' => array(
                        function ($instance, $sm) {
                            if ($instance instanceof \Zend\Db\Adapter\AdapterAwareInterface) {
                                $instance->setDbAdapter($sm->get('Zend\Db\Adapter\Adapter'));
                            }
                        }
                ),
                'invokables' => array(
                        'menu' => 'Application\Model\MenuTable',

                ),

                'factories' => array(
                        'Navigation' => 'Application\Navigation\YourNavigationFactory'
                )
        );
    } 

in src/navigation folder in your module create YourNavigation.php and YourNavigationFactory.php

namespace Application\Navigation;

use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Navigation\Service\DefaultNavigationFactory;
use Admin\Model\Entity\Tablepages;
class YourNavigation extends DefaultNavigationFactory
{




    protected function getPages(ServiceLocatorInterface $serviceLocator)
    {

        if (null === $this->pages) {

            $fetchMenu = $serviceLocator->get('menu')->fetchAll();


            $configuration['navigation'][$this->getName()] = array();



            foreach($fetchMenu as $key=>$row)
            {

                $subMenu = $serviceLocator->get('menu')->fetchAllSubMenus($row['id']);

           if($subMenu){
              $pages = array();
                foreach($subMenu as $k=>$v)
                {
                    foreach($v as $field=>$value){
                        $page['label'] =$value['heading'];
                        $page['route'] = 'visas';
                        if ($value['path'] == $row['path']){
                        $page['params'] = array('action'=>'index',
                                                 'category'=> $this->$row['path'],

                        );


                        }

                        $subCatMenu = $serviceLocator->get('menu')->fetchAllSubCatMenus($value['id']);

                        $subcatpages = array();
                        $subcatgroup = array();
                        $group = array();
                        if($subCatMenu>0){

                        foreach($subCatMenu as $k=>$v)
                        {
                            foreach($v as $field=>$value1){

                                $subpage['label'] =$value1['heading'];
                                $subpage['route'] = 'visas';
                                if ($value['path'] ==$row['path']){

                                    $subpage['params'] = array('action'=>'index',
                                          'category'=> $row['path'],
                                          'sub_category'=> $value1['path']);


                                }elseif($row['id'] ==76){
                                    $subpage['params'] = array('action'=>'index',
                                            'category'=>$value['path'],
                                            'sub_category'=>$value1['path']);


                                }else{

                                $subpage['params'] = array('action'=>'index',
                                            'category'=> $row['path'],
                                            'sub_category'=> $value['path'],
                                            'id'=> $value1['path']);
                                }

                            }
                            $group[] =$subpage;


                         }

                       $page['pages'] =$group;
                       $pages[] =$page;


                        }


                        }

               }


           }


               $configuration['navigation'][$this->getName()][$row['name']] = array(
                    'label' => $row['name'],

                     'route' => 'visas',
                    'params'       => array(
                            'action' => 'index',
                            'category' => $row['path'],

                    ),

                   'pages' =>  $pages,

                );


            }



            if (!isset($configuration['navigation'])) {

                throw new Exception\InvalidArgumentException('Could not find navigation configuration key');
            }
            if (!isset($configuration['navigation'][$this->getName()])) {

                throw new Exception\InvalidArgumentException(sprintf(
                    'Failed to find a navigation container by the name "%s"',
                    $this->getName()
                ));
            }

            $application = $serviceLocator->get('Application');

            $routeMatch  = $application->getMvcEvent()->getRouteMatch();

            $router      = $application->getMvcEvent()->getRouter();
            $pages       = $this->getPagesFromConfig($configuration['navigation'][$this->getName()]);


            $this->pages = $this->injectComponents($pages, $routeMatch, $router);
        }

        return $this->pages;
    }
}

YourNavigationFactory.php

 namespace Application\Navigation;

    use Zend\ServiceManager\FactoryInterface;
    use Zend\ServiceManager\ServiceLocatorInterface;

        class YourNavigationFactory implements FactoryInterface
        {
            public function createService(ServiceLocatorInterface $serviceLocator)
            {
                $navigation =  new MyNavigation();
                return $navigation->createService($serviceLocator);
            }
        }

in your layout.phtml

 <?php  echo $this->navigation('navigation')->menu()->setPartial('menu')->render();  ?>

to create dynamic sitemap from navigation

    $this->navigation('navigation')
          ->sitemap()
          ->setUseXmlDeclaration(false)
          ->setServerUrl('http://www.yourdomain.com')
          ->setFormatOutput(true);?>

   echo $this->navigation()->menu()->setMinDepth(null)->setMaxDepth(null)->setOnlyActiveBranch(false)->setRenderInvisible(true);

to create breadcrumbs

echo $this->navigation()
                  ->breadcrumbs()
                  ->setLinkLast(true)                 
                  ->setMaxDepth(1)                     
                  ->setSeparator(' ▶' . PHP_EOL);

I Hope it helps you to save your time

Solution 2

For some backgrounds you might read this answer on another, but similar question regarding Zend\Navigation. The point is you want MVC pages and MVC pages in Zend Framework 2 need a way to assemble the url and find our if the url is active or not.

Every MVC page has a route name. The route stack routes the request and gets a route match. You must inject this route match into the navigation, so every page could check its own route against the matched one.

Similar for the url assembly. If you want to convert the route name into an url, you need the route stack ('router'). Inject the router in your application too and you are able to assemble.

In short:

use Zend\Navigation\Service\ConstructedNavigationFactory;

class MyController extends AbstractActionController
{

  public function indexAction()
  {
    $config = array(
      // your config here
    );

    $factory    = new ConstructedNavigationFactory($config);
    $navigation = $factory->createService($this->getServiceLocator());

    return new ViewModel(array(
        'navigation' => $navigation;
    ));
  }
}

And similar as above answer, in your view:

<?php echo $this->navigation($navigation)->menu()?>

Solution 3

My previous answer is not correct. The following code works. For one page. In controller, edit action:

$page = new \Zend\Navigation\Page\Mvc(array(
    'route' => 'application/default',
    'controller' => 'album',
    'action'     => 'edit',
    'use_route_match' => true,
));

$r = $this->getEvent()->getRouter();
$rm = $this->getEvent()->getRouteMatch();
$page->setRouter($r);
$page->setRouteMatch($rm);

echo $page->isActive() ? 'true' : 'false'; // true
echo $page->getHref(); // /test_app/public/application/album/edit/id1
Share:
13,475
struggleendlessly
Author by

struggleendlessly

I am a software developer with 12+ years of experience. While my top and main skill is .Net development, I have also successfully managed development teams and accomplished projects. Working with me you will always get my full and honest point of view on your project, processes, tasks and ideas. My work with such brands like Accenture, Volvo, RWE and Brompton allows me to assure you that every part of your project from whole development plan to smallest details will be done with highest quality.

Updated on June 04, 2022

Comments

  • struggleendlessly
    struggleendlessly almost 2 years

    I want ask you about this problem. What do i need to create Dynamic Menu with Zend\Navigation\Navigation?

    In ZF1 i made like this:

    $container = new Zend_Navigation();
    $pages = array(
    array(
        'label'  => 'Save',
        'action' => 'save',
    ),
    array(
        'label'  => 'Delete',
        'action' => 'delete',
    ),
    );
    // add two pages
    $container->addPages($pages);
    

    and then in view:

    $this->navigation()->menu();
    

    But in ZF2 pages are taking from config. Now i create \config\autoload\nav.global.php and here create page array. But i need to do page array in method and send it into navigation helper, but ii dont know how ((

    i tried to do this in my controller:

    use Zend\Navigation\Navigation;
    $pages =array(
            // All navigation-related configuration is collected in the 'navigation' key
            'navigation' => array(
                // The DefaultNavigationFactory we configured in (1) uses 'default' as the sitemap key
                'default' => array(
                    // And finally, here is where we define our page hierarchy
                    'account' => array(
                        'label' => 'faq',
                        'route' => 'faq',
                        'pages' => array(
                            'news' => array(
                                'label' => 'news',
                                'route' => 'news',
                                ),
                                'manual' => array(
                                'label' => 'manual',
                                'route' => 'manual',
                                ),               
                        ),
                    ),
                ),
            ),
        );
    $Menu = new Navigation($pages);
    

    and then this in view:

    $this->Menu()->menu();
    

    but i have a lot of mistakes...

    i think you understand my problem. please help. sorry for my english.