Cover of the book Symfony 5: The Fast Track

Symfony 5: The Fast Track is the best book to learn modern Symfony development, from zero to production. +300 pages showcasing Symfony with Docker, APIs, queues & async tasks, Webpack, SPAs, etc.

Registering your own provider

3.0 version
Maintained

Registering your own provider

Registering your own menu provider allows you to feed your menu with your own data, accessed by your code. It can for example go through a PHPCR repository and create the corresponding menu elements.

Create first your Provider class, in the Provider directory of your bundle:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
namespace App\Provider;

use Knp\Menu\FactoryInterface;
use Knp\Menu\Provider\MenuProviderInterface;

class CustomMenuProvider implements MenuProviderInterface
{
    /**
     * @var FactoryInterface
     */
    protected $factory = null;


    /**
     * @param FactoryInterface $factory the menu factory used to create the menu item
     */
    public function __construct(FactoryInterface $factory)
    {
        $this->factory = $factory;
    }

    /**
     * Retrieves a menu by its name
     *
     * @param string $name
     * @param array $options
     * @return \Knp\Menu\ItemInterface
     * @throws \InvalidArgumentException if the menu does not exists
     */
    public function get($name, array $options = [])
    {
        if ('demo' == $name) { //several menu could call this provider

            $menu = /* construct / get a \Knp\Menu\NodeInterface */;

            if ($menu === null) {
                throw new \InvalidArgumentException(sprintf('The menu "%s" is not defined.', $name));
            }

            /*
             * Populate your menu here
             */

            $menuItem = $this->factory->createFromNode($menu);

            return $menuItem;
        }
    }

    /**
     * Checks whether a menu exists in this provider
     *
     * @param string $name
     * @param array $options
     * @return bool
     */
    public function has($name, array $options = [])
    {
        $menu = /* find the menu called $name */;

        return $menu !== null;
    }
}

Then, configure the services linked to this new provider.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# config/services.yaml or app/config/services.yml
services:
    app.menu_provider:
        class: App\Provider\CustomMenuProvider
        arguments:
          - '@knp_menu.factory'
        tags:
          - { name: knp_menu.provider }

# ...

Finally, to generate the menu, for example inside a twig template type:

1
{{ knp_menu_render('demo') }}

The Symfony CMF MenuBundle provides a complete working example.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.