Welcome to Abdul Malik Ikhsan's Blog

Zend Framework 2 : Dynamic Navigation using Zend\Navigation

Posted in Tutorial PHP, Zend Framework 2 by samsonasik on November 18, 2012

Zend Framework 2 provide Navigation component to generate menu. It can utilize by creating static config in autoload/*.global.php. Sometime, we need dynamic menu to be generated in our application. I will give you a simple example to do that.

For example, i want structure menu like this :

So, we should do step by step like the following :
1. Create a menu Table (I’m using postgresql, you can specify yourself for your database )

CREATE TABLE menu
(
  id bigserial NOT NULL,
  name character varying(255),
  label character varying(255),
  route character varying(255),
  CONSTRAINT pk_menu PRIMARY KEY (id )
)
WITH (
  OIDS=FALSE
);
ALTER TABLE menu
  OWNER TO postgres;

2. Insert the data like the following :

3. create a Model :

namespace ZendSkeletonModule\Model;

use Zend\Db\Adapter\Adapter;
use Zend\Db\ResultSet\HydratingResultSet;
use Zend\Db\TableGateway\AbstractTableGateway;
use Zend\Db\Sql\Select;
use Zend\Db\Adapter\AdapterAwareInterface;

class MenuTable extends AbstractTableGateway
    implements AdapterAwareInterface
{
    protected $table = 'menu';

    public function setDbAdapter(Adapter $adapter)
    {
        $this->adapter = $adapter;
        $this->resultSetPrototype = new HydratingResultSet();

        $this->initialize();
    }

    public function fetchAll()
    {
        $resultSet = $this->select(function (Select $select){
                $select->order(array('id asc'));
        });

        $resultSet = $resultSet->toArray();

        return $resultSet;
    }
}

4. Extends Zend\Navigation\Service\DefaultNavigationFactory and override getPages() function.

namespace ZendSkeletonModule\Navigation;

use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Navigation\Service\DefaultNavigationFactory;

class MyNavigation extends DefaultNavigationFactory
{
    protected function getPages(ServiceLocatorInterface $serviceLocator)
    {
        if (null === $this->pages) {
            //FETCH data from table menu :
            $fetchMenu = $serviceLocator->get('menu')->fetchAll();

            foreach($fetchMenu as $key=>$row)
            {
                $configuration['navigation'][$this->getName()][$row['name']] = array(
                    'label' => $row['label'],
                    'route' => $row['route'],
                );
            }
            
            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;
    }
}

5. Create Your Navigation Factory

namespace ZendSkeletonModule\Navigation;

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

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

6. Register MenuTable model, and your Navigation in ServiceManager :

class Module
{
    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' => 'ZendSkeletonModule\Model\MenuTable' 
            ),
            'factories' => array(
                'Navigation' => 'ZendSkeletonModule\Navigation\MyNavigationFactory'
            )
          );
    }

    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }
 
    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                     __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                ),
            ),
        );
    }
}

6. Configuration done, let’s call from layout:

<div class="nav-collapse">
<?php echo $this->navigation('Navigation')->menu()->setUlClass('nav'); ?>
</div>

Done !

97 Responses

Subscribe to comments with RSS.

  1. Ernesto Quintero said, on November 19, 2012 at 10:58 pm

    Excelente, Very good

  2. Dragos said, on November 20, 2012 at 2:58 am

    Tank you very much, I appreciate.

  3. Fredrik Wahlqvist (@FredWahlqvist) said, on November 20, 2012 at 6:02 am

    Really good examples, would be great to get examples on GitHub as well

  4. samsonasik said, on November 20, 2012 at 9:09 am

    You can follow my github account : https://github.com/samsonasik

  5. Jurian Sluiman said, on November 23, 2012 at 6:13 pm

    You might take a look at ensemble as well (http://ensemble.github.com). The kernel (https://github.com/ensemble/EnsembleKernel) does exactly this, together with two more options:

    1. Navigation can be a tree and not only a flat structure
    2. Like the tree structure of the navigation component, routes can be hierarchical as well

    The kernel implements an adapter pattern where currently only a doctrine one exists, but it’s easy to make one for Zend\Db as well.

    • samsonasik said, on November 24, 2012 at 12:40 pm

      great!, my post is just a sample to who are need simple implementation of dynamic navigation.

  6. Dragos said, on November 27, 2012 at 11:47 pm

    I apologize if too bold but may I suggest another blog post: Multi step form

  7. […] Zend Framework 2 : Dynamic Navigation using ZendNavigation Автор: Abdul Malik Ikhsan Перевод: Лобач […]

  8. Ashish Saxena said, on December 22, 2012 at 3:28 pm

    it would have been great if you explained the code ..
    not in details but few lines below each block explaining what is was doing.
    Must have really helped the beginners. Anyways nice post indeed .. 🙂

  9. myth said, on January 3, 2013 at 5:03 pm

    HJ samsonasik!

    has error how to fix?
    Fatal error: Uncaught exception ‘Zend\Db\TableGateway\Exception\RuntimeException’ with message ‘This table does not have an Adapter setup’ in E:\webproject\ZendFramework2\library\Zend\Db\TableGateway\AbstractTableGateway.php:104 Stack trace: #0 E:\webproject\ZendFramework2\library\Zend\Db\TableGateway\AbstractTableGateway.php(187): Zend\Db\TableGateway\AbstractTableGateway->initialize() #1 E:\webproject\htdocs\zf2shopcms\backend\Admin\src\Admin\Model\MenuTable.php(27): Zend\Db\TableGateway\AbstractTableGateway->select(Object(Closure)) #2 E:\webproject\htdocs\zf2shopcms\backend\Admin\src\Admin\Navigation\MyNavigation.php(13): Admin\Model\MenuTable->fetchAll() #3 E:\webproject\ZendFramework2\library\Zend\Navigation\Service\AbstractNavigationFactory.php(40): Admin\Navigation\MyNavigation->getPages(Object(Zend\ServiceManager\ServiceManager)) #4 E:\webproject\htdocs\zf2shopcms\backend\Admin\src\Admin\Navigation\MyNavigationFactory.php(12): Zend\Navigation\Service\AbstractNavigationFactory->createService(Object(Zend\ServiceMana in E:\webproject\ZendFramework2\library\Zend\ServiceManager\ServiceManager.php on line 733

    • samsonasik said, on January 3, 2013 at 6:27 pm

      You have to set adapter first.

      • myth said, on January 5, 2013 at 1:50 pm

        thank you for support!

        i’m write getServiceConfig() in module.php file:

        public function getServiceConfig()
        {
        return array(
        ‘factories’ => array(
        ‘Admin\Model\Users’ => function($sm) {
        $dbAdapter = $sm->get(‘Zend\Db\Adapter\Adapter’);
        $table = new Users($dbAdapter);
        return $table;
        },
        ‘Admin\Model\GroupUsers’ => function($sm) {
        $dbAdapter = $sm->get(‘Zend\Db\Adapter\Adapter’);
        $table = new GroupUsers($dbAdapter);
        return $table;
        },
        ),
        // menu config
        ‘invokables’ => array(
        ‘menu’ => ‘Admin\Model\MenuTable’
        ),
        ‘factories’ => array(
        ‘Navigation’ => ‘Admin\Navigation\MyNavigationFactory’
        )

        );
        }

        code remaining write like you!
        i’m not understand code is not running
        sorry english me not good 😀

      • samsonasik said, on January 5, 2013 at 2:05 pm

        You should set adapter first. please take a look zf2 manual : http://zf2.readthedocs.org/en/latest/user-guide/database-and-models.html

  10. joenilson said, on January 13, 2013 at 11:29 am

    Hi, has you work with zend framework 2 and postgres database with multiple schemas?, i’m using zf2 v2.0.6 but always add double quotes to the schema.table name, i llok in the zf2 issue tracker but i dont see nothing like this. i’m using pdo driver to connect.

    • samsonasik said, on January 13, 2013 at 11:57 am

      in setDbAdapter, re-define the $table with TableIdentifier :

          public function setDbAdapter(Adapter $adapter)
          {
              $this->table = new \Zend\Db\Sql\TableIdentifier('menu', 'yourschema');
              $this->adapter = $adapter;
              $this->resultSetPrototype = new HydratingResultSet();
              
              $this->initialize();
          }
      
  11. Pouyan Az said, on February 7, 2013 at 8:06 pm

    Hi, very good tutorial, but I have now problem adding a second navigation bar. Is it posible to do that when yes how, I have read this but dosn’t help.

    http://stackoverflow.com/questions/12972316/how-to-set-up-2-navigations-in-zf2

  12. Dhananjay said, on February 8, 2013 at 4:00 am

    hey man your all tutorials are wonderfull. I followed your blog but i’m getting on issue that the address of all links showing only to home(www.weblogz2.loc). what could be the possible reason. please help me to rectify this issue.

    • samsonasik said, on February 8, 2013 at 1:46 pm

      check your module.config.php on route section, try with Literal first instead of Segment.

      • Dhananjay said, on February 9, 2013 at 4:06 am

        I’m really very thankful to you for reply, you are great instructor. This is my module.config.php file address http://pastie.org/6098043 Please if possible have a look of it and suggest me where i have to change for proper link address. i’m really messed up with this thing. if you can, then please mail me the changed file.

      • samsonasik said, on February 10, 2013 at 6:00 pm

        with your config. your call-ing route in navigation should be ‘album’ . and it should be work.

  13. aydinhassan said, on February 26, 2013 at 6:15 am

    Hi, I’ve just attempted this tutorial and It seems the Navigation factory never gets called. I put some debug in the factory and nothing prints. I’m using the latest version of Zend Framework 2, is this still the correct way to do it? Code is as follows: https://gist.github.com/anonymous/5034200

    The var_dump in DefaultNavigationFactory never happens.

    • aydinhassan said, on February 26, 2013 at 8:46 am

      NM, I got it to work.

      • Ricci said, on January 12, 2014 at 8:26 pm

        I ve got this problem but not get the solution …. What is your solution ?

  14. Bharat said, on March 9, 2013 at 10:20 pm

    Hi Samsonasik,

    I’m new in ZF2 (2.1.3).
    I follow entire step provided by you. But, I’m getting following error:

    ( ! ) Fatal error: Uncaught exception ‘Zend\Navigation\Exception\InvalidArgumentException’ with message ‘Invalid argument: Unable to determine class to instantiate’ in D:\wamp\www\zend\2.x\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php on line 744
    ( ! ) Zend\Navigation\Exception\InvalidArgumentException: Invalid argument: Unable to determine class to instantiate in D:\wamp\www\zend\2.x\vendor\zendframework\zendframework\library\Zend\Navigation\Page\AbstractPage.php on line 225

    Thanks
    Bharat

    • samsonasik said, on March 10, 2013 at 7:25 pm

      add the following common functions to your module class :

          public function getConfig()
          {
              return include __DIR__ . '/config/module.config.php';
          }
      
          public function getAutoloaderConfig()
          {
              return array(
                  'Zend\Loader\StandardAutoloader' => array(
                      'namespaces' => array(
                          __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                      ),
                  ),
              );
          }
      

      and don’t forget to set your db adapter. read the docs http://zf2.readthedocs.org/en/latest/user-guide/database-and-models.html

  15. Michael said, on March 31, 2013 at 9:35 pm

    Hello, samsonasik!

    I follow entire step provided by you and I’m getting error:

    Fatal error: Uncaught exception ‘Zend\ServiceManager\Exception\ServiceNotCreatedException’ with message ‘While attempting to create navigation(alias: Navigation) an invalid factory was registered for this instance type.’ in W:\domains\lp.loc\vendor\ZF2\library\Zend\ServiceManager\ServiceManager.php:871

    Thanks!

    • samsonasik said, on March 31, 2013 at 10:04 pm

      you should be aware with namespace you used.

      • cedricus said, on August 13, 2013 at 4:29 pm

        Hi!
        Same trouble.
        Did you solve it?

        Thanks.

  16. MarianoV said, on April 18, 2013 at 1:28 am

    Hi, very nice code!!! how can I get the current or active module from here? thank you!!!

    • MarianoV said, on April 18, 2013 at 2:19 am

      I did it like this: $routeMatch->getMatchedRouteName();
      I have other question, if I want to invocate a function like this:
      echo $this->navigation(‘MyNavigation’)->testFunction();
      from layout.phtml, how can I did it?
      Thanks again!

      • samsonasik said, on April 18, 2013 at 3:33 am

        i don’t think so, don’t use it even possible, use view_helpers!

      • samsonasik said, on April 18, 2013 at 3:38 am

        i don’t think so. use view_helpers !

  17. samsonasik said, on April 18, 2013 at 3:34 am

    i don’t think so, use view_helpers to do something like that !

  18. Mauricio Silva said, on April 20, 2013 at 9:35 pm

    Hi, great code… helps a lot.
    But, I am wondering on how to make it work on two separate menus (default and admin) in a fancy way (with submenu and icons).
    I have made it work on a static way.

    • samsonasik said, on April 21, 2013 at 7:47 pm

      you can add class/id or/and other attributes beside of label and route.

  19. james said, on April 25, 2013 at 3:45 pm

    hi sam.
    could you show me how to use BREADCRUMBS by navigation . thanks a lot !!

  20. Philip said, on May 16, 2013 at 2:51 pm

    Awesome! Great work mate, keep it up!

    1 more thing, if you get a chance or you have free time maybe you can add another feature. Like implementing the BjyAuthorize(ACL) in navigation. It would be a great help for all beginners like me. Again, Thank you for this helpful blog!

  21. tomekk2k4 said, on June 20, 2013 at 7:06 pm

    Hi Samsonasik

    i have two questions for you.

    i want to add a search item to a navigation from configuration. do you know if this is possible?
    So instead of a item i want to have a input field for a search action.

    the second question:
    can i create a navigation/ menu from a module and just display it on specific pages within that module?
    I want to implement a “show step of a process” bar, that the user knows on which step it is currently working…
    like when you get to the order process within a shop system, you always get a bar displayed, where you can see on which step you are currently (select paymentmethod, confirm the order, finish payment)

    i hope my english is not too bad and the questions are enough detailed 🙂

  22. ravindar singh said, on June 30, 2013 at 10:21 pm

    Hi Samsonasik,

    i have one questions for you. how can pass extra parameters on fatchAll($data);

    Because i need to condition base data fatch

    protected function getPages(ServiceLocatorInterface $serviceLocator)
    {
    if (null === $this->pages) {
    //FETCH data from table menu :
    $fetchMenu = $serviceLocator->get(‘menu’)->fetchAll();

    $configuration[‘navigation’][$this->getName()] = array();
    foreach($fetchMenu as $key=>$row)
    {
    $configuration[‘navigation’][$this->getName()][$row[‘name’]] = array(
    ‘label’ => $row[‘label’],
    ‘route’ => $row[‘route’],
    );
    }

    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;
    }

    $fetchMenu = $serviceLocator->get(‘menu’)->fetchAll(‘How can pass the condition data like(array)’);

    Please can you help me 🙂

    • samsonasik said, on July 2, 2013 at 12:25 am

      if conditional parameter is segment parameter, you can do this :

      $paramnameValue =  $serviceLocator->get('Router')
                                                                   ->match( $serviceLocator->get('Request'))
                                                                   ->getParam('paramName')
      
      $fetchMenu = $serviceLocator->get(‘menu’)->fetchAll(array('paramname' => $paramnameValue));
      

      and just modify your fetchAll($param) code at TableModel :

          public function fetchAll($parameter)
          {
              $resultSet = $this->select(function (Select $select)  use ($parameter) {
                     $select->where($parameter); 
                     $select->order(array('id asc'));
              });
       
              $resultSet = $resultSet->toArray();
       
              return $resultSet;
          }
      
  23. Beneetha TA said, on July 11, 2013 at 7:13 pm

    hi

    I am trying to get the navigation for main category and sub category… Could u please help me

  24. ajith said, on November 4, 2013 at 1:07 pm

    Uncaught exception ‘Zend\ServiceManager\Exception\ServiceNotCreatedException’ with message ‘While attempting to create navigation(alias: Navigation) an invalid factory was registered for this instance type.’ in C:\wamp\www\nav\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php on line 1031

    will u clear this issue,

  25. ajith said, on November 4, 2013 at 4:05 pm

    Uncaught exception ‘Zend\ServiceManager\Exception\ServiceNotFoundException’ with message ‘Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Db\Adapter\Adapter’ in C:\wamp\www\nav\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php on line 518

    if ($instance instanceof \Zend\Db\Adapter\AdapterAwareInterface) {
    $instance->setDbAdapter($sm->get(‘Zend\Db\Adapter\Adapter’));
    }

    • Bhuvanesh said, on November 5, 2013 at 1:02 pm

      check ur factories whether in local or module…

  26. Bhuvanesh said, on November 5, 2013 at 12:47 pm

    hai sam,
    good post,

    for submenu I coded in mod.cong.php $pages=array(….);but it not works

  27. Bharath said, on November 14, 2013 at 7:46 pm

    hi, i’m try to develeop navigation in zf2 to use of container and uri. i got fatel error generating that has

    Fatal error: Uncaught exception ‘Zend\Navigation\Exception\InvalidArgumentException’ with message ‘Could not find navigation configuration key’ in C:\Apache\htdocs\SMBERP\vendor\zendframework\zendframework\library\Zend\Navigation\Service\AbstractNavigationFactory.php:57 Stack trace: #0 C:\Apache\htdocs\SMBERP\vendor\zendframework\zendframework\library\Zend\Navigation\Service\AbstractNavigationFactory.php(36): Zend\Navigation\Service\AbstractNavigationFactory->getPages(Object(Zend\ServiceManager\ServiceManager)) #1 [internal function]: Zend\Navigation\Service\AbstractNavigationFactory->createService(Object(Zend\ServiceManager\ServiceManager), ‘navigation’, ‘navigation’) #2 C:\Apache\htdocs\SMBERP\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php(852): call_user_func(Array, Object(Zend\ServiceManager\ServiceManager), ‘navigation’, ‘navigation’) #3 C:\Apache\htdocs\SMBERP\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php(982): Zend\ServiceManager\ServiceManager- in C:\Apache\htdocs\SMBERP\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php on line 859

    wat i have did wrong? plz give me a detailed explanation for how to use container with uri….

  28. bharath said, on November 16, 2013 at 5:50 pm

    i got menu but i want to seperate datas from database by aline datas in ULClass.give me a details….
    sry for bad english……

  29. bhuvanesh said, on November 19, 2013 at 8:40 pm

    Uncaught exception ‘Zend\Db\TableGateway\Exception\InvalidArgumentException’ with message ‘Invalid method (_get) called, caught by Zend\Db\TableGateway\AbstractTableGateway::__call()

    my codings
    public function fetchAll()
    {
    $resultSet = $this->_get(function($select){
    $select=”SELECT*
    FROM menu AS parent
    LEFT JOIN menu AS child
    ON child.matches = parent.id
    WHERE parent.id
    ORDER BY parent.id, child.id”;
    // $select->where(array(‘id =1’));

    });
    $resultSet = $resultSet->toArray();
    return $resultSet;
    }

    any idea,,,,,,,,

  30. Arvind Kumar said, on November 20, 2013 at 6:33 pm

    Commenting again because html html data not showing.

    Using navigation in zend create html like this

    Menu

    but If i want data like

    Menu

  31. Arvind Kumar said, on November 20, 2013 at 6:35 pm

    Html data is not showing here again.By the way my question is if i want to add a span tag before achar tag then what i have to do?

  32. Bình Phạm Văn said, on December 3, 2013 at 11:38 am

    Thanks for tips. Now, I want to add param to navigation, example, article id, category alias….. So how to do?

  33. Glutera said, on December 17, 2013 at 10:18 am

    character varying nya apa harus 225 semua ya

    • samsonasik said, on December 17, 2013 at 11:20 pm

      ga

      • Sam said, on December 19, 2013 at 3:15 pm

        Hi samsonasik,

        Do you have any separate tutorial on creating a complete DB based ACL Navigation ?

        I m trying to create one but it is having a lot of issues. Finally I m trying to start with this codeset and modify it. Any inputs will be welcomed.

        I followed the steps above but getting this error –

        [Thu Dec 19 00:52:36 2013] [error] [client xxx.xx.xxx.xxxPHP Fatal error: Uncaught exception ‘Zend\\ServiceManager\\Exception\\ServiceNotCreatedException’ with message ‘While attempting to create navigation(alias: navigation) an invalid factory was registered for this instance type.’ in /usr/local/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:1031\nStack trace:\n#0 /usr/local/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php(601): Zend\\ServiceManager\\ServiceManager->createFromFactory(‘navigation’, ‘navigation’)\n#1 /usr/local/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php(561): Zend\\ServiceManager\\ServiceManager->doCreate(‘navigation’, ‘navigation’)\n#2 /usr/local/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php(503): Zend\\ServiceManager\\ServiceManager->create(Array)\n#3 /usr/local/project/vendor/zendframework/zendframework/library/Zend/View/Helper/Navigation/A in /usr/local/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php on line 1031

        Thanks in advance. You are doing a great job as a Teacher. I m already your followed on twitter

  34. Sam said, on December 20, 2013 at 1:34 am

    My requirement –

    A user is part of multiple GROUPS (or ROLES).

    I need to implement ACL which reads completely from Database and not from configuration file.

    Is there any article you can help me with ?

    Scenario:

    User1 => Role1, Role2
    User2 => Role2
    User3 => Role3

    Resource1 Access -> Role1

    Resource2 Access -> Role1 and Role2

    Resource3 Access -> Role3

    Appropriately I need to render the Navigation Menu. Remember there may n number of sub menus.

  35. linh said, on February 27, 2014 at 1:38 pm

    hello . samsonasik !!
    I misstake when add submenu. i wan’t like about example. but i can’t . your can do like about example or can do zend navigation contaner

  36. jcropp said, on March 6, 2014 at 2:53 am

    Thanks for this code, samsonasik!

    I found that when I implemented it, it didn’t render the way I wanted it to using the default bootstrap skin. The fix is to add the navbar-nav class to the layout.phtml statement.

    Instead of:
    navigation(‘Navigation’)->menu()->setUlClass(‘nav’); ?>

    Use:
    navigation(‘Navigation’)->menu()->setUlClass(‘nav navbar-nav’); ?>

  37. jcropp said, on March 7, 2014 at 1:39 am

    Thanks again for this code, samsonasik!

    Can you tell me if there is a way to pass options to the route variable (or to some other variable) in the container configuration? For instance, the ZF2 Album module tutorial suggests that “/album/edit/2” is the route to the edit page for id 2. However, in the basic module “/album/edit/2” is NOT the route: “album” is the route and “action” and “id” are options. If “/album/edit/2” is entered in the route field in the menu table, your code throws an error because “/edit/2” is not part of the route. Similarly, the example you’ve given in your sample database above won’t work for “SampleModule/default” unless the “/default” segment is set up as a child_route and not an action.

    There are probably a number of solutions. One might be to reconfigure the router array in module.config.php to identify sub segments as child_routes instead of options (although I’m not sure how to inject an id variable as a route name). Another solution is to use the uri variable instead of the route variable in the table and in the container configuration. However, I would like to know if there’s a way of passing something like “/album?action=edit&id=2” through the route variable, or if there are other variables available to pass option metadata.

  38. jcropp said, on March 7, 2014 at 2:05 am

    Thanks again for this code, samsonasik!

    Is there a way to instruct the navigation container to generate the HTML for a dropdown menu?

    I have forked your code in order to develop submenus and my new code looks something like this:

    namespace Menu\Navigation;

    use Zend\ServiceManager\ServiceLocatorInterface;
    use Zend\Navigation\Service\DefaultNavigationFactory;

    class MyNavigation extends DefaultNavigationFactory
    {
    protected function getPages(ServiceLocatorInterface $serviceLocator)
    {
    if (null === $this->pages) {
    //FETCH data from table menu :
    $fetchMainMenu = $serviceLocator->get(‘menu’)->fetchMainMenu();

    $configuration[‘navigation’][$this->getName()] = array();
    foreach($fetchMainMenu as $MainMenuItem=>$MainMenuField)
    {

    $fetchSubMenu = $serviceLocator->get(‘menu’)->fetchSubMenu($MainMenuField[‘ml1’]);
    $subMenu = array();
    foreach($fetchSubMenu as $SubMenuItem=>$SubMenuField)
    {
    array_push($subMenu,
    array(
    ‘label’ => $SubMenuField[‘label’],
    ‘uri’ => $SubMenuField[‘uri’],
    ‘title’ => $SubMenuField[‘title’],
    ‘active’ => false,
    )
    );
    }

    $configuration[‘navigation’][$this->getName()][$MainMenuField[‘name’]] = array(
    ‘label’ => $MainMenuField[‘label’],
    ‘uri’ => $MainMenuField[‘uri’],
    ‘pages’ => $subMenu,
    ‘title’ => $MainMenuField[‘title’],
    ‘active’ => false,
    );
    }

    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;
    }
    }

    The code above generates the following HTML:

    Home

    Knowledgebase

    page 1

    page 2

    page 3

    However, for the dropdown menu to expand and collapse, we want to generate this code:

    Home

    Knowledgebase

    page 1

    page 2

    page 3

    Is there a way to pass instructions to identify the appropriate li’s as class=”dropdown”, the appropriate ul’s as class=”dropdown-menu ” and the appropriate a’s as class=” dropdown-toggle”; and to insert a symbol in the dropdown item tag?

    Thanks.

  39. jcropp said, on March 7, 2014 at 2:09 am

    Oops. WordPress converted the HMTL code in my comment. Here’s another try.
    The code above generates the following HTML:

    
      
        Home
      
      
        Knowledgebase
        
          
            page 1
          
          
            page 2
          
          
            page 3
          
        
      
    
    

    However, we want to generate this code:

    
      
        Home
      
      
        Knowledgebase 
        
          
            page 1
          
          
            page 2
          
          
            page 3
          
        
      
    
    
  40. jcropp said, on March 7, 2014 at 2:12 am

    Nope, that didn’t work either. Sorry, there’s not a function to allow me to delete or edit my comments. Please edit my comment so it renders as code.

  41. sanstorm said, on October 15, 2014 at 8:07 am

    i need examply with doctrine2

  42. Jairo García said, on November 10, 2014 at 5:41 pm

    Hi samsonasik,

    I´ve spent a few days trying to get this navigation working. I have read all the replys and a lot of forums but I still have a problem.

    I have created the table on the database and the files MenuTable, MyNavigation, MyNavigationFactory under src/Application/Model.

    The namespaces for each file are:

    MenuTable: Application\Model
    MyNavigation: Application\Navigation
    MyNavigationFactory: Application\Navigation

    I’ve modified Application/Module.php following your instructions with these namespaces:

    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\Model\MyNavigationFactory’ /* here I have had to change the path to avoid uncaught exception errors */
    )
    );
    }

    At last, I have insrted the following lines for the layout:

    navigation(‘Navigation’)->menu()->setUlClass(‘nav’); ?>

    When I run the application, both the webpage and Z-Ray show me the following error:

    Fatal error: Cannot redeclare class Application\Navigation\MyNavigationFactory in /usr/local/zend/apache2/htdocs/my_viena/module/Application/src/Application/Model/MyNavigationFactory.php on line 7

    It seems like I have already declared this class…

    Could you please help me with this issue? Is this a matter of namespaces? Did I create the files in the wrong folder?

    I will really appreciate your help.

    Thanks in advance,
    Jairo García

  43. Max Gulturyan said, on December 19, 2014 at 9:19 pm

    In ZendSkeletonModule\Navigation\MyNavigation::getPages()
    if (!isset($configuration[‘navigation’])) and
    if (!isset($configuration[‘navigation’][$this->getName()]))

    will never called, because in previous line you initialize this array:
    $configuration[‘navigation’][$this->getName()] = array();

    • samsonasik said, on December 20, 2014 at 5:56 am

      Thanks ;), I’ve fixed it by removing the initialization.

  44. Adham said, on January 26, 2015 at 2:51 am

    Thanks for this tutorial very helpful
    I’m new to ZF
    And I have a problem I do not understand.

    When I set navigation to “route”
    $configuration[‘navigation’][$this->getName()][$row[‘name’]] = array(
    ‘label’ => $row[‘label’],
    ‘route’ => $row[‘route’],
    );
    i get message
    Fatal error: Zend\Mvc\Router\Exception\RuntimeException: Route with name “” not found in

    When I set navigation to “uri” all work good
    $configuration[‘navigation’][$this->getName()][$row[‘name’]] = array(
    ‘label’ => $row[‘label’],
    ‘uri’ => $row[‘route’],
    );

    Application router

    ‘router’ => array(
    ‘routes’ => array(
    ‘home’ => array(
    ‘type’ => ‘Literal’,
    ‘options’ => array(
    ‘route’ => ‘/’,
    ‘defaults’ => array(
    ‘controller’ => ‘Application\Controller\Index’,
    ‘action’ => ‘index’,
    ),
    ),
    ),
    ‘application’ => array(
    ‘type’ => ‘Literal’,
    ‘options’ => array(
    ‘route’ => ‘/application’,
    ‘defaults’ => array(
    ‘__NAMESPACE__’ => ‘Application\Controller’,
    ‘controller’ => ‘Index’,
    ‘action’ => ‘index’,
    ),
    ),
    ‘may_terminate’ => true,
    ‘child_routes’ => array(
    ‘default’ => array(
    ‘type’ => ‘Segment’,
    ‘options’ => array(
    ‘route’ => ‘/[:controller[/:action]]’,
    ‘constraints’ => array(
    ‘controller’ => ‘[a-zA-Z][a-zA-Z0-9_-]*’,
    ‘action’ => ‘[a-zA-Z][a-zA-Z0-9_-]*’,
    ),
    ‘defaults’ => array(
    ),
    ),
    ),
    ),
    ),
    ),
    ),

    • samsonasik said, on January 26, 2015 at 6:49 am

      check the data first of $fetchMenu with var_dump if data grabbed. and debug it.

  45. 70578k8 (@70578k8) said, on February 3, 2015 at 6:25 am

    I am project manager. m team built a web site in Zend. it conains a menu on left. when we click any item in menu, whole page gets reload. Can we make it that the menu stays there and the resulting page is loaded in a separate div instead?

  46. Camilo Calderon said, on March 9, 2015 at 3:10 am

    Hi samsonasik,
    First let me thank you for sharing this post,
    I followed the steps carefully and finally render the menu as expected, but also gives the following error:
    C:\xampp\htdocs\outPruebas\vendor\zendframework\zendframework\library\Zend\Navigation\Page\AbstractPage.php:232
    message:
    Invalid argument: Unable to determine class to instantiate
    I’ve tried with mvc and uri type pages.
    I have run the project with debug and does not go through line 232, the variables $hasUri or $hasMvc are set correctly, and fails in method run () class MVC\Application.php

    Thank you in advance.

    • samsonasik said, on March 10, 2015 at 1:17 am

      I tried many times, and worked. You probably need to check your php version or other requirements.

  47. Hema said, on June 18, 2015 at 12:55 pm

    Hi samsonasik,

    how create a dynamic breadcrumbs using db or xml in zf2.

    Thank you in advance.

  48. shaiesh said, on June 28, 2015 at 5:47 pm

    How to solve this bug.

    Fatal error: Uncaught exception ‘Zend\Loader\Exception\InvalidArgumentException’ with message ‘Map file provided does not exist. Map file: “C:\xampp\htdocs\new\module\Album/autoload_classmap.php”‘ in C:\xampp\htdocs\new\vendor\zendframework\zend-loader\src\ClassMapAutoloader.php:171 Stack trace: #0 C:\xampp\htdocs\new\vendor\zendframework\zend-loader\src\ClassMapAutoloader.php(81): Zend\Loader\ClassMapAutoloader->loadMapFromFile(‘C:\\xampp\\htdocs…’) #1 C:\xampp\htdocs\new\vendor\zendframework\zend-loader\src\ClassMapAutoloader.php(117): Zend\Loader\ClassMapAutoloader->registerAutoloadMap(‘C:\\xampp\\htdocs…’) #2 C:\xampp\htdocs\new\vendor\zendframework\zend-loader\src\ClassMapAutoloader.php(60): Zend\Loader\ClassMapAutoloader->registerAutoloadMaps(Array) #3 C:\xampp\htdocs\new\vendor\zendframework\zend-loader\src\ClassMapAutoloader.php(46): Zend\Loader\ClassMapAutoloader->setOptions(Array) #4 C:\xampp\htdocs\new\vendor\zendframework\zend-loader\src\AutoloaderFactory.php(99): Zend\Loader\ClassMapAutoloader->__construc in C:\xampp\htdocs\new\vendor\zendframework\zend-loader\src\ClassMapAutoloader.php on line 171

  49. Daniel Gomes said, on February 18, 2016 at 1:54 am

    Hi samsonasik,

    This article has been helping very much, but a have I question and I’ll be pleased if you can reply.

    I’ve created a dynamic navigation to a category table
    category1
    subcategory
    subsubcategory
    category2

    However I don’t know how I can write the routes correctly

    module.config

    ‘home’ => array(
    ‘type’ => ‘Literal’,
    ‘options’ => array(
    ‘route’ => ‘/’,
    ‘defaults’ => array(
    ‘controller’ => ‘Application\Controller\Index’,
    ‘action’ => ‘index’
    )
    ),
    ‘may_terminate’ => true,
    ‘child_routes’ => array(
    ‘catalog’ => array(
    ‘type’ => “Segment”,
    ‘options’ => array(
    ‘route’ => “catalog/[:slug1[/:slug2[/:slug3]]]”,
    ‘defaults’ => array(
    ‘controller’ => ‘Application\Controller\CatalogCategory’,
    ‘action’ => ‘index’,
    ‘slug1’ => ”,
    ‘slug2’ => ”,
    ‘slug3’ => ”,
    ),
    ),
    ‘may_terminate’ => true,
    ),
    ),
    ),

    I think another away most clean to do it.

    • samsonasik said, on February 27, 2016 at 7:21 pm

      I personally prefer query params rather than too many segment as you may need to check all the slash path when not filled.

  50. Iyngaran said, on March 4, 2016 at 12:40 pm

    I was able to manage to get the breadcrumbs and menu with static navigation. But for dynamic navigation, I followed the steps and navigation is working. But the breadcrumbs not showing.

    navigation(‘frontend_main_navigation’)->breadcrumbs()->setMinDepth(0); ?>

    returns empty pages

  51. Alexander said, on July 27, 2016 at 6:34 pm

    Hello Sam! I use zend about month. And i try to do this in ZF3 How I can implement that inZF3
    $application = $serviceLocator->get(‘Application’);
    $routeMatch = $application->getMvcEvent()->getRouteMatch();
    $router = $application->getMvcEvent()->getRouter();


Leave a reply to Glutera Cancel reply