# How to override Navigation or Menu View Helper Plugin

**URL:** <https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087>\
**Category:** Components & MVC\
**Tags:** laminas-mvc, laminas-navigation\
**Created:** [February 2, 2021, 12:54pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087 "2021-02-02T12:54:08Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![ALTAMASH80](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/altamash80/32/895_2.png) [@ALTAMASH80](https://discourse.laminas.dev/u/ALTAMASH80)\
**Post date:** [February 2, 2021, 12:54pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/1 "2021-02-02T12:54:08Z")

</div>

Hi, I want to know how to override Navigation helper and it’s plugins, namely Menu, Breadcrumb, Links, SiteMap. In Zf2 this can be done by finding out the configuration key and override it. But in Laminas this is not the case. As Navigation is no longer a built in part of Laminas View and you can see that in `Laminas\View\PluginManager`, if I’m correct. So, how to override Navigation helper and it’s menu. The code which use to work in zf2 was something like below:

```auto
'view_helpers' => [
  'factories' => [
    'navigations' => \Application\View\Navigation::class,
  ]
]

```

But this above code gives error “Bad method call: Unknown method Laminas\Navigation\Navigation::menu”. Even if I change “navigation” to FCQN it gives error. In my `getPluginManager()` method I’ve override the values of the property aliases like below:

```auto
class PluginManager extends LaminasPluginManager{

  protected $aliases = [
        'breadcrumbs' => \Laminas\View\Helper\Navigation\Breadcrumbs::class,
        'links' => \Laminas\View\Helper\Navigation\Links::class,
        'menu' => \Application\View\Helper\Navigation\Menu::class,
        'sitemap' => \Laminas\View\Helper\Navigation\Sitemap::class,
  ];

```

Thanks 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:** [February 2, 2021, 1:34pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/2 "2021-02-02T13:34:06Z")

</div>

Hello and welcome to our forums! 😃

> [@ALTAMASH80](#):
>
> In Zf2 this can be done by finding out the configuration key and override it. But in Laminas this is not the case.

In this case there were no major changes between the different versions like ZF2, ZF3 and Laminas. laminas-view or zend-view always knew only one helper: `Laminas\View\Helper\Navigation` which works as [proxy](https://docs.laminas.dev/laminas-navigation/helpers/navigation/) to the helper like Menu, Sitemap, Links, Breadcrumbs. Therefore, this helper has its own [plugin manager](https://github.com/laminas/laminas-view/blob/c34b15f42cac410f35010163de169ab71c39bf73/src/Helper/Navigation/PluginManager.php#L15-L22).

_At the moment I don’t have a computer in front of me, but I will submit a solution later._

---

<div class="post-metadata">

**Author:** ![ALTAMASH80](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/altamash80/32/895_2.png) [@ALTAMASH80](https://discourse.laminas.dev/u/ALTAMASH80)\
**Post date:** [February 2, 2021, 2:03pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/3 "2021-02-02T14:03:38Z")

</div>

Dear @froschdesign,  
From Zf2 to Zf3 there is a change in Navigation. Navigation was part of Zf2 view but in Zf3 it was removed. Now, in Zf3 and Laminas you’ve to install Navigation as a separate component to be able to use its functionality. But I’m not here to argue, if by any means my sentence gives an impression of argument. For that I apologize. I’ve extended from the same Plugin Manager which you’ve referred. The code of my question is like below:

```auto
class Navigation extends \Laminas\View\Helper\Navigation{
    public function getPluginManager(){
        if (null === $this->plugins) {
            $this->setPluginManager(new \Application\View\Helper\Navigation\PluginManager());
        }
        
        return $this->plugins;
   }
}

// My Plugin Manager Class
use Laminas\View\Helper\Navigation\PluginManager as LaminasPluginManager;
class PluginManager extends LaminasPluginManager{
    protected $aliases = [
        'breadcrumbs' => \Laminas\View\Helper\Navigation\Breadcrumbs::class,
        'links' => \Laminas\View\Helper\Navigation\Links::class,
        'menu' => \Application\View\Helper\Navigation\Menu::class,//Override Default with My Menu Class
        'sitemap' => \Laminas\View\Helper\Navigation\Sitemap::class,
   ];
}
// This above code works in zf2

```

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![ALTAMASH80](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/altamash80/32/895_2.png) [@ALTAMASH80](https://discourse.laminas.dev/u/ALTAMASH80)\
**Post date:** [February 3, 2021, 3:22pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/4 "2021-02-03T15:22:44Z")

</div>

After reading your reply again and focusing on the proxy point which you’ve made. Even after that not able to make it work. **As the point of registering path is not clear in the Navigation document. Which is the end of the second paragraph.** So, what I’ve done is below and it doesn’t work.

```auto
'view_helpers' => [
        'aliases' => [
            'myMenu' => Application\View\Helper\Navigation\Menu::class,
        ],
        'factories' => [
            Application\View\Helper\Navigation\Menu::class => \Laminas\ServiceManager\Factory\InvokableFactory::class,
        ],
]

```

**myMenu class implements Laminas\View\Helper\Navigation\HelperInterface**

in the \*.phtml file, I’ve called it like below.

```auto
$this->navigations('default')->myMenu();

```

This gives error **Fatal error** : Uncaught Laminas\Navigation\Exception\BadMethodCallException: Bad method call: Unknown method Laminas\Navigation\Navigation::myMenu.

Thanks 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:** [February 3, 2021, 4:32pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/5 "2021-02-03T16:32:01Z")

</div>

> [@ALTAMASH80](#):
>
> From Zf2 to Zf3 there is a change in Navigation. Navigation was part of Zf2 view but in Zf3 it was removed.

Some history:  
The navigation component has its own namespace since version 2.0.0 and with version 2.5.0 all components were extracted to their own repositories. But that was a long, long time ago – 2015.  
All in all, the handling of laminas-view and laminas-navigation are the same since version 2.5.0.

* * *

But here my suggestion: you can use a delegator to configure the plugin manager of the navigation proxy helper.

Based on the mvc-skeleton application, you must create a class for the delegator and extend the configuration:

## Delegator

`module/Application/src/Navigation/NavigationHelperDelegator.php`:

```php
namespace Application\Navigation;

use Laminas\View\Helper\Navigation as NavigationHelper;
use Laminas\View\Helper\Navigation\Menu;
use Psr\Container\ContainerInterface;

class NavigationHelperDelegator
{
    public function __invoke(
        ContainerInterface $container,
        string $name,
        callable $callback,
        array $options = null
    ): NavigationHelper {
        /** @var NavigationHelper $helper */
        $helper = $callback();

        // Configure the plugin manager for navigation proxy helper
        $helper->getPluginManager()->setService(
            Menu::class,
            new class() extends NavigationHelper\AbstractHelper {
                public function render($container = null): string
                {
                    return '<nav>Custom menu</nav>';
                }

                public function __invoke($container = null)
                {
                    if (null !== $container) {
                        $this->setContainer($container);
                    }

                    return $this;
                }
            }
        );

        return $helper;
    }
}

```

More informations to delegators can be found in the [documentation of laminas-servicemanager](https://docs.laminas.dev/laminas-servicemanager/delegators/).

## Module Configuration

`module/Application/config/module.config.php`:

```php
return [
    'navigation_helpers' => [
        'delegators' => [
            \Laminas\View\Helper\Navigation::class => [
                \Application\Navigation\NavigationHelperDelegator::class,
            ],
        ],
    ],
    // …
];

```

## Layout Script

`module/Application/view/layout/layout.phtml`:

```php
<?= $this->navigation()->menu() ?>

```

Output:

```html
<nav>Custom menu</nav>

```

---

<div class="post-metadata">

**Author:** ![ALTAMASH80](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/altamash80/32/895_2.png) [@ALTAMASH80](https://discourse.laminas.dev/u/ALTAMASH80)\
**Post date:** [February 4, 2021, 11:11am UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/6 "2021-02-04T11:11:58Z")

</div>

Thanks, @froschdesign. Your answer will help someone but I couldn’t extract the point which I wanted. But someone will find this useful.

---

<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:** [February 4, 2021, 11:17am UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/7 "2021-02-04T11:17:41Z")

</div>

> [@ALTAMASH80](#):
>
> but I couldn’t extract the point which I wanted.

Your initial question was:

> I want to know how to override Navigation helper and it’s plugins, namely Menu, Breadcrumb, Links, SiteMap.

That’s exactly what you can do with it. You can set everything you want to the „setService“ method. See also: [Configuring the service manager - laminas-servicemanager - Laminas Docs](https://docs.laminas.dev/laminas-servicemanager/configuring-the-service-manager/#altering-a-service-managers-config)  
The anonymous class from above is only an example! And as you can see in the layout script, the menu helper is overwritten.

Could you describe what you are missing?

---

<div class="post-metadata">

**Author:** ![ALTAMASH80](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/altamash80/32/895_2.png) [@ALTAMASH80](https://discourse.laminas.dev/u/ALTAMASH80)\
**Post date:** [February 4, 2021, 12:57pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/8 "2021-02-04T12:57:10Z")

</div>

@froschdesign, The thing which I wanted to achieve is to learn how to override and which a part of it you’ve shared. But overriding was just a first step. What I wanted to achieve with override is to just play around with “renderMenu” method. Which I was not able to do with a simple change which is provided in your solution:

```auto
            $helper->getPluginManager()->setService(
            Menu::class,
            // extend from MyMenu class which is extended from Laminas Menu and Laminas Menu is extended from AbstractHelper
            new class() extends MyMenu {
            }

```

You would say that can be done with partial. Why go through all the trouble. True. The second question will be, how can I add my proxies to navigations? So, by playing around with overriding Menu I could have generated menu the way I like according to the project requirement. Also, then be able to contribute it via LM-Commons. Thanks!

---

<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:** [February 4, 2021, 1:17pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/9 "2021-02-04T13:17:25Z")

</div>

> [@ALTAMASH80](#):
>
> …how can I add my proxies to navigations?

To be clear in this case: there is only _one_ proxy helper and this is `Laminas\View\Helper\Navigation`. This helper creates no output, it is the interface to concrete navigation helpers Breadcrumbs, Menu, Links and Sitemap.

This proxy helper uses internally a [plugin manager](https://docs.laminas.dev/laminas-servicemanager/plugin-managers/) to hold the concrete helpers. If you want to override or to add new helpers to this proxy helper, then these custom helpers must be set to the plugin manager.  
The proxy helper will find the helper via the internal plugin manager and you can work with them.

# Example

## Custom helper

`module/Application/src/Navigation/CustomMenuHelper.php`:

```php
namespace Application\Navigation;

use Laminas\View\Helper\Navigation\Menu;

class CustomMenuHelper extends Menu
{
    public function renderMenu($container = null, array $options = []): string
    {
        var_dump('Custom');
        
        return parent::renderMenu(
            $container,
            $options
        );
    }
}

```

## Delegator

`module/Application/src/Navigation/NavigationHelperDelegator.php`:

```php
namespace Application\Navigation;

use Laminas\View\Helper\Navigation as NavigationHelper;
use Laminas\View\Helper\Navigation\Menu;
use Psr\Container\ContainerInterface;

class NavigationHelperDelegator
{
    public function __invoke(
        ContainerInterface $container,
        string $name,
        callable $callback,
        array $options = null
    ): NavigationHelper {
        /** @var NavigationHelper $helper */
        $helper = $callback();

        // Override existing menu helper
        $helper->getPluginManager()->setInvokableClass(
            Menu::class,
            CustomMenuHelper::class
        );

        // Add new helper
        $helper->getPluginManager()->setInvokableClass(
            CustomMenuHelper::class,
            CustomMenuHelper::class
        );
        $helper->getPluginManager()->setAlias(
            'customMenu',
            CustomMenuHelper::class
        );

        return $helper;
    }
}

```

## Layout Script

`module/Application/view/layout/layout.phtml`:

```auto
<?= $this->navigation()->menu() ?>

<?= $this->navigation()->customMenu() ?>

```

This produces the same output.

* * *

I hope the example is not so abstract this time. 😉

---

<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:** [February 4, 2021, 1:21pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/10 "2021-02-04T13:21:51Z")

</div>

> [@ALTAMASH80](#):
>
> Also, then be able to contribute it via LM-Commons.

Why not for the official component? Is there a reason?

---

<div class="post-metadata">

**Author:** ![ALTAMASH80](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/altamash80/32/895_2.png) [@ALTAMASH80](https://discourse.laminas.dev/u/ALTAMASH80)\
**Post date:** [February 4, 2021, 2:18pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/11 "2021-02-04T14:18:47Z")

</div>

@froschdesign, Thanks! The provided overriding code works exactly what I was looking for. Now, to make a bootstrap version of it and contribute. I don’t understand the legality of LM-Commons and Laminas. For me, both are the same. If what I’ll work on gets any reviews or gets accepted then to go for the official component is a good approach. In my opinion. Second, to make it for the official component, I would require to write a test. That is my weak part. But I will learn it in time. As it’s a daunting task. I’ve to take a dive but when I’ve no idea. Maybe contribution will make me learn 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:** [February 4, 2021, 2:40pm UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/12 "2021-02-04T14:40:58Z")

</div>

> [@ALTAMASH80](#):
>
> I don’t understand the legality of LM-Commons and Laminas. For me, both are the same

It is not. Laminas Project is an official [Linux Foundation project](https://www.linuxfoundation.org/en/projects/) and it is the _umbrella_ for Mezzio, laminas-mvc, Components and API Tools.

[https://getlaminas.org](https://getlaminas.org)

And for LM Commons see on GitHub:

> Community developed packages for the Laminas MVC. **This is not an official Laminas Project.**

> **[LM Commons](https://github.com/LM-Commons)**
>
> Community developed packages for the Laminas MVC. This is not an official Laminas Project. - LM Commons

---

<div class="post-metadata">

**Author:** ![ALTAMASH80](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/altamash80/32/895_2.png) [@ALTAMASH80](https://discourse.laminas.dev/u/ALTAMASH80)\
**Post date:** [February 5, 2021, 6:15am UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/13 "2021-02-05T06:15:10Z")

</div>

@froschdesign, I agree that LM-Commons is not the official part of the Laminas umbrella. But the people there are using or maintaining repositories which are built with Laminas and more specifically for Laminas MVC.

Whereas Laminas Mezzio is and as Matthew always said in his talk is a library of individual components. Use whichever you like or use our skeleton MVC. The result of using individual components can be seen in Magento. But developing Magento is not an everyday task. Whereas people like me rely on MVC, therefore I would like to contribute to a repository which can be plug in an MVC skeleton. So, that is my intention. How much I will succeed in it, only time will tell. Thanks!

---

<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:** [February 5, 2021, 9:42am UTC](https://discourse.laminas.dev/t/how-to-override-navigation-or-menu-view-helper-plugin/2087/14 "2021-02-05T09:42:10Z")

</div>

Don’t worry, I know the ecosystem and I have already seen that you are working on [LmcAdmin](https://github.com/LM-Commons/LmcAdmin). Do not forget the tests! 😁
