Skip to content

Add navigation menu

To add a navigation menu to your website, prepare a general layout template in a templates/themes/<theme_name>/pagelayout.html.twig file.

This template can contain things such as header, menu, footer, as well as assets for the whole site, and all other templates extend it.

To select items that should be rendered in the menu, you can use one of the following ways:

Render menu using a query

To create a menu that contains a specific set of content items, for example all content under the root Location, use a Query Type.

First, in src/QueryType, create a custom MenuQueryType.php file that queries for all items that you want in the menu:

 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
<?php declare(strict_types=1);

namespace App\QueryType;

use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery;
use Ibexa\Contracts\Core\Repository\Values\Content\Query;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause;
use Ibexa\Core\QueryType\QueryType;

class MenuQueryType implements QueryType
{
    public function getQuery(array $parameters = [])
    {
        $criteria = new Query\Criterion\LogicalAnd([
            new Query\Criterion\Visibility(Query\Criterion\Visibility::VISIBLE),
            new Query\Criterion\ParentLocationId(2),
        ]);
        $options = [
            'filter' => $criteria,
            'sortClauses' => [
                new SortClause\Location\Priority(LocationQuery::SORT_ASC),
            ],
        ];

        return new LocationQuery($options);
    }

    public static function getName()
    {
        return 'Menu';
    }

    public function getSupportedParameters()
    {
        return [];
    }
}

In this case, it queries for all visible children of Location 2, the root Location, (lines 15-16) and renders them in order according to their Location priority.

The Query Type has the name Menu (line 28). You can use it in the template to render the menu. Add the following ibexa_render_content_query function to the pagelayout_html.twig template:

1
2
3
4
5
6
7
{{ ibexa_render_content_query({
    'query': {
        'query_type': 'Menu',
        'assign_results_to': 'menuItems'
    },
    'template': '@ibexadesign/pagelayout_menu.html.twig',
}) }}

Next, add the templates/themes/<theme_name>/pagelayout_menu.html.twig template, which renders the individual items of the menu:

1
2
3
4
5
{% if menuItems is defined and menuItems is not empty %}
    {% for item in menuItems %}
        <li><a href="{{ ibexa_path(item.valueObject) }}">{{ ibexa_content_name(item.valueObject.contentInfo) }}</a></li>
    {% endfor %}
{% endif %}

Create a MenuBuilder

To make a more configurable menu, where you select the specific items to render, use the KNPMenuBundle that is installed together with the product.

To use it, first create a MenuBuilder.php file in src/Menu:

 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
<?php declare(strict_types=1);

namespace App\Menu;

use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;

class MenuBuilder
{
    private FactoryInterface $factory;

    public function __construct(FactoryInterface $factory)
    {
        $this->factory = $factory;
    }

    public function buildMenu(): ItemInterface
    {
        $menu = $this->factory->createItem('root');

        $menu->addChild('Home', ['route' => 'ibexa.url.alias', 'routeParameters' => [
            'locationId' => 2,
        ]]);
        $menu->addChild('Blog', ['route' => 'ibexa.url.alias', 'routeParameters' => [
            'locationId' => 67,
        ]]);
        $menu->addChild('Search', ['route' => 'ibexa.search']);

        return $menu;
    }
}

In the builder, you can define items that you want in the menu. For example, lines 21-23 add a specific Location by using the ibexa.url.alias route. Line 27 adds a defined system route that leads to the search form.

Next, register the menu builder as a service:

1
2
3
4
services:
    App\Menu\MenuBuilder:
        tags:
            - {name: knp_menu.menu_builder, method: buildMenu, alias: root}

Finally, you can render the menu in pagelayout.html.twig. Identify it by the name that you provided in the Menu Builder's buildMenu() method:

1
{{ knp_menu_render('root') }}