# Nested breadcrumb using zend-navigation

**URL:** <https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363>\
**Category:** Components & MVC\
**Tags:** zend-mvc, zend-navigation\
**Created:** [November 9, 2017, 12:05pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363 "2017-11-09T12:05:09Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [November 9, 2017, 12:05pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/1 "2017-11-09T12:05:10Z")

</div>

Hello  
I have a problem using my navigation via zend-navigation, my concept of site hierarchy is such below:  
blog -\>category-\>posts  
when im in the category page the breadcrumb shown is correct  
blog \> category  
but when im in the posts the breadcrumb shows this:  
blog -\> posts  
as you can see the ‘category’ is missing.  
the ‘navigation’ key is here:

```
     'navigation' => [
    'default' => [
        [
            'label' => 'Home',
            'route' => 'home',
        ],
        [
            'label' => 'blog',
            'route' => 'blog',
            'pages' => [
                [
                    'label' => 'all',
                    'route' => 'blog',
                    'action' => 'index',
                ],
                [
                    'route' => 'blog/detail',
                    'action' => 'detail',
                ],
                [
                    'route'=>'blog/category',
                    'action'=>'category',
                ],
                /*[
                    'label' => 'Delete',
                    'route' => 'album',
                    'action' => 'delete',
                ],*/
            ],
        ],
    ],];

```

it says i have two main pages called ‘home’ and ‘blog’ and under the ‘blog’ i have pages like ‘all’ and ‘category’ and ‘detail’ that represents posts.  
how should i use nested like approach to work it out?  
thank you

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [November 9, 2017, 1:10pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/2 "2017-11-09T13:10:20Z")

</div>

> [@erfan](#):
>
> but when im in the posts the breadcrumb shows this:
> 
> `blog > posts`

In your configuration for the navigation container is no “posts”?!

Example:

```
$navigation = new Zend\Navigation\Navigation(
    [
        [
            'label' => 'Blog',
            'uri' => 'blog',
            'pages' => [
                [
                    'label' => 'Detail',
                    'uri' => 'blog/detail',
                ],
                [
                    'label' => 'Category',
                    'uri' => 'blog/category',
                    'pages' => [
                        [
                            'label' => 'Posts',
                            'uri' => 'blog/category/posts',
                        ],
                    ],
                ],
            ],
        ],
    ]
);

```

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [November 9, 2017, 4:30pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/3 "2017-11-09T16:30:01Z")

</div>

thank you for your response but i am planning to use dynamic breadcrumb as I want to have a page builder structure in the future that accepts some parameter in one page to dynamically change the view.anyway, how should I use this $navigation in my view script?

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [November 9, 2017, 4:50pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/4 "2017-11-09T16:50:13Z")

</div>

> [@erfan](#):
>
> i am planning to use dynamic breadcrumb

You mean dynamic navigation? Add one detail page and then update the label and parameter of the detail page in your view script. Example:

```
/** @var \Zend\Navigation\Page\Mvc $page */
$page = $this->navigation('default')->findOneBy('route', 'blog/detail');
$page->setParams(['id' => $post->getId()]);
$page->setLabel($post->getTitle());

```

After this you can output the breadcrumbs.

> [@erfan](#):
>
> how should I use this $navigation in my view script

You do not need a new navigation container. Extend your configuration and you will get the same results.

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [November 10, 2017, 10:57am UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/5 "2017-11-10T10:57:44Z")

</div>

thank you for your patience but here is the deal:  
i have module directory set to Application as default module and Blog.  
As the documentation said I put my ‘navigation’ container code in the Application-\>config-\>module.config.php and the default code is:

```
'navigation' => [
    'default' => [
        [
            'label' => 'Home',
            'route' => 'home',
        ],
        [
            'label' => 'Blog',
            'route' => 'blog',
            'pages' => [
                [
                    'label' => 'All',
                    'route' => 'blog',
                    'action' => 'index',
                ],
                [
                    'route' => 'blog/detail',
                    'action' => 'detail',
                ],
                [
                    'route'=>'blog/category',
                    'action'=>'category',
                ],

            ],
        ],
    ],

```

in my Blog module the config file under Blog-\>config-\>module.config.php the route is like this:

```
    'router' => [
    // Open configuration for all possible routes
    'routes' => [
        // Define a new route called "blog"
        'blog' => [
            // Define a "literal" route type:
            'type' => Literal::class,
            // Configure the route itself
            'options' => [
                // Listen to "/blog" as uri:
                'route' => '/blog',
                // Define default controller and action to be called when
                // this route is matched
                'defaults' => [
                    'controller' => Controller\ListController::class,
                    'action' => 'index',
                ],
            ],
            'may_terminate' => true,
            'child_routes'=> [
                'detail'=>[
                    'type'=>segment::class,
                    'options'=>[
                        'route'=>'/single/:id',
                        'defaults'=>[
                            'action'=>'detail',
                        ],
                        'constraints'=>[
                            'id'=>'[1-9]\d*',
                        ],
                    ],

                ],
                'category'=>[
                    'type'=>segment::class,
                    'options'=>[
                        'route'=>'/subpage-category/id-:cid/:title',
                        'defaults'=>[
                            'action'=>'category',
                        ],
                        'constraints'=>[
                            //'catTitle'=>'[a-zA-Z][a-zA-Z0-9_-]*',
                            'cid'=>'[1-9]\d*',
                        ],
                    ],

                ],

            ],
        ],
    ],
],

```

I have put the code you recommended in Application config like this:

```
      use Zend\Navigation\Navigation;
$navigation = new Navigation(
    [
        'default'=>[
            [
                'label'=>'Home',
                'route'=>'home',
            ],
            [
                'label'=>'Blog',
                'route'=>'blog',
                'pages'=> [
                    'label'=>'category',
                    'route'=>'blog/category',
                    'pages'=>[
                        'label'=>'Detail',
                        'route'=>'blog/detail',
                    ],
                ]
            ]
        ]

    ]);
return [
    'router' => [
        'routes' => [
            'home' => [
                'type' => Literal::class,
                'options' => [
                    'route' => '/',
                    'defaults' => [
                        'controller' => Controller\IndexController::class,
                        'action' => 'index',
                    ],
                ],
            ],
            'application' => [
                'type' => Segment::class,
                'options' => [
                    'route' => '/application[/:action]',
                    'defaults' => [
                        'controller' => Controller\IndexController::class,
                        'action' => 'index',
                    ],
                ],
            ],
        ],
    ],
    'controllers' => [
        'factories' => [
            Controller\IndexController::class => InvokableFactory::class,
        ],
    ],
    'view_manager' => [
        'display_not_found_reason' => true,
        'display_exceptions' => true,
        'doctype' => 'HTML5',
        'not_found_template' => 'error/404',
        'exception_template' => 'error/index',
        'template_map' => [
            'layout/layout' => __DIR__. '/../view/layout/layout.phtml',
            'application/index/index' => __DIR__. '/../view/application/index/index.phtml',
            'error/404' => __DIR__. '/../view/error/404.phtml',
            'error/index' => __DIR__. '/../view/error/index.phtml',
        ],
        'template_path_stack' => [
            __DIR__. '/../view',
        ],
    ],

    /*'navigation' => [
        'default' => [
            [
                'label' => 'Home',
                'route' => 'home',
            ],
            [
                'label' => 'Blog',
                'route' => 'blog',
                'pages' => [
                    [
                        'label' => 'All',
                        'route' => 'blog',
                        'action' => 'index',
                    ],
                    [
                        'route' => 'blog/detail',
                        'action' => 'detail',
                    ],
                    [
                        'route'=>'blog/category',
                        'action'=>'category',
                    ],

                ],
            ],
        ],

    ],*/

    $navigation
];

```

and used the $page in the detail page here:

```
$page = $this->navigation('default')->findOneBy('route', 'blog/detail');
$page->setParams(['id' => $post->getId()]);
$page->setLabel($post->getTitle());

```

but it does not work where am i wrong?

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [November 10, 2017, 11:24am UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/6 "2017-11-10T11:24:23Z")

</div>

> [@erfan](#):
>
> I have put the code you recommended in Application config like this:

You misunderstood me! Extend your **configuration array** in `Application/config/module.config.php ` and do not add an extra navigation object!  
Please remove this and then check again.

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [November 10, 2017, 12:46pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/7 "2017-11-10T12:46:38Z")

</div>

what is the differences between using ‘navigation’ as a key in configuration array in Application/config/module.config.php ,as the file returns an array, and $navigation = new Zend\Navigation\Navigation([])? I know how to use the ‘navigation’ key in script but i cannot put nested ‘pages’ in this way:

```
'navigation' => [
    'default' => [
        [
            'label' => 'Home',
            'route' => 'home',
        ],
        [
            'label' => 'Blog',
            'route' => 'blog',
            'pages' => [
                [
                    'label' => 'All',
                    'route' => 'blog',
                    'action' => 'index',
                ],

                [
                    'label'=>'category',
                    'route'=>'blog/category',
                    'action'=>'category',
                    'pages'=>[
                            'label'=>'detail',
                            'route' => 'blog/detail',
                            'action' => 'detail',

                    ]
                ],

            ],
        ],
    ],

],

```

the ‘page’ under the label ‘category’ causes an error. my main problem I don’t exactly know how to use the code you provided as an example with $navigation = new Zend\Navigation\Navigation([]) in the configuration array.would you please give me a sample to bring me out of this confusion?

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [November 10, 2017, 1:51pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/8 "2017-11-10T13:51:59Z")

</div>

> [@erfan](#):
>
> what is the differences between using ‘navigation’ as a key in configuration array in Application/config/module.config.php ,as the file returns an array, and $navigation = new Zend\Navigation\Navigation()?

Only the configuration array will work in the config file. To be clear: my code was only an example and not for copy and paste!

> [@erfan](#):
>
> the ‘page’ under the label ‘category’ causes an error.

Compare the `pages` array under “blog” and the `pages` array under “category”. Brackets (new array) are missing!  
The name is “page **s** ” – plural. You can add more than one page.

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [November 12, 2017, 1:42pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/9 "2017-11-12T13:42:44Z")

</div>

i really appreciate your help it seems to work but i receive an error that says ‘cid’ is missing in my detail.php and that is caused by the parent of detail page `category`, because in the category 's action in controller is called when i want to use detail in navigation container and it seems that i have to pass the required parameter through params[].  
is there anywhere not to do so?  
I mean prevent action to be called in category page?  
thank you in advance

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [November 13, 2017, 11:28am UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/10 "2017-11-13T11:28:21Z")

</div>

> [@erfan](#):
>
> i receive an error that says ‘cid’ is missing in my detail.php and that is caused by the parent of detail page category

Then do the same for the category page:

```
$category = $post->getCategory(); // maybe like this (!)

$categoryPage = $this->navigation('default')->findOneBy('route', 'blog/category');
$categoryPage->setParams(['cid' => $category->getId()]);
$categoryPage->setLabel($category->getName());

```

Btw. if you need this function calls more than once, then a listener which uses the [`MvcEvent::EVENT_RENDER`](https://docs.zendframework.com/zend-mvc/mvc-event/#mvceventevent_render-render) is a better choice.

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [November 14, 2017, 3:47pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/11 "2017-11-14T15:47:15Z")

</div>

it works all the way thank you for your Big help!😍

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [November 15, 2017, 9:44am UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/12 "2017-11-15T09:44:05Z")

</div>

I think, we should add this as example to the documentation and also an example with a listener which sets the parameters.

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [November 15, 2017, 2:01pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/13 "2017-11-15T14:01:35Z")

</div>

that’s wise! let me know if you would like to cooperate to achieve it. I’m looking forward to hearing from you.

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [November 23, 2017, 2:42pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/14 "2017-11-23T14:42:28Z")

</div>

> [@froschdesign](#):
>
> an example with a listener which sets the parameters.

could you please provide me a sample on how to do it!?

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [November 23, 2017, 3:58pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/15 "2017-11-23T15:58:44Z")

</div>

In the bug tracker of zend-navigation you can find an example for a listener:

> <https://github.com/zendframework/zend-navigation/issues/55#issuecomment-271313270>

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [December 6, 2017, 10:39am UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/16 "2017-12-06T10:39:30Z")

</div>

hi, I’ve been trying for weeks to get to know with event manager mechanism, although there are lots of documentation out there, I couldn’t work with it. I read your example but there are few things I can’t handle.  
the case is I want to add a listener which reacts to MvcEvent::EVENT\_RENDER, I mean I want to get to URL and output them automatically in view template.  
this is my listener in NavigationListener.php :

```
 namespace Blog\Events;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;
use Zend\Mvc\MvcEvent;

class NavigationListener implements ListenerAggregateInterface
{
    protected $listener;
    public function attach(EventManagerInterface $events,$priority = 1){
        $shared = $events->getSharedManager();
        $shared->attach('Zend\Mvc\View\Console\DefaultRenderingStrategy',
            MvcEvent::EVENT_RENDER,[$this,'addParams']
            ,1000);
        //$this->listener[] = $events->attach(MvcEvent::EVENT_RENDER
          // ,[$this,'addParams']
            //,1000);
    }
    public function detach(EventManagerInterface $events){}
    public function addParams(MvcEvent $event){
        // Get request URI
        $uri = $event->getResult()->getUri();
        return $uri;
    }
} 

```

first of all, I know when we want to listen to a private Event we have to use shared event manager, is this particular event private?  
second of all, is it a MUST to register this listener via onBootstrap() or init() methods?  
I put this code in module.config.php of my module:

```
'service_manager' => [
    
    'invokables'=>[
        Events\NavigationListener::class => Events\NavigationListener::class,
    ]
],
'listeners'=> [
    Events\NavigationListener::class,
],

```

how should I know what are MvcEvent::EVENT\_RENDER parameters? what is the target of this event that is to set as Identifires(I used ‘Zend\Mvc\View\Console\DefaultRenderingStrategy’)?  
how to get the return value in the listener method at the end?

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [December 6, 2017, 11:06am UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/17 "2017-12-06T11:06:12Z")

</div>

> [@erfan](#):
>
> I mean I want to get to URL and output them automatically in view template.

Sorry, maybe I misunderstand something here, but the output of a single URL has nothing to do with a navigation!  
Please stay in your original posting: [https://discourse.zendframework.com/t/getting-uri-using-eventmanager/385](https://discourse.zendframework.com/t/getting-uri-using-eventmanager/385)

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [December 6, 2017, 12:05pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/18 "2017-12-06T12:05:22Z")

</div>

> [@erfan](#):
>
> public function addParams(MvcEvent $event){  
> // Get request URI  
> $uri = $event-\>getResult()-\>getUri();  
> return $uri;  
> }

thanks, what about this method?does it work? if so where can I retrieve the $uri parameter?

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [December 6, 2017, 1:39pm UTC](https://discourse.laminas.dev/t/nested-breadcrumb-using-zend-navigation/363/19 "2017-12-06T13:39:15Z")

</div>

Again: this is the wrong topic!
