Menu builder for Kirby v5

Hi Community!

I’m with a Kirby 5 plain install and I would like to replicate the:

Multiple independent custom menus

and

Two-level custom menu

from this Cookbook:

I’m finding that the information in the Cookbook may not be relevant to version 5.

Being more specific, trying to replicate Multiple independent custom menus y got an error about the type: structure

menus:
  type: structure
  fields:
    menuHeadline:
      type: text
      label: Menu headline
    menuItems:
      type: pages
      label: Menu item

Error:

Invalid section type (“structure”)

I have changed to field, but I’m still getting problems about the other parts of the code.

Could anybody help to update this Cookbook for Kirby v5?

Also, as a newbie in Kirby, I would like to do a suggestion. Specifying what’s the path for every code block shown in guides and documentation would be extremely helpful. I’m a bit struggling with this. Kirby have great docs and guides but (unfortunately) I have really few time available, so the lack of the file path data related to each block of code presented, makes the random access consultation pretty harder.

Thank you very much for the effort in delivering and maintaining this great project. <3

Right, menu needs to be a field.

What exactly?

I pasted this code inside kirby5plain/site/templates/default.php

<?php $menus = $site->menus()->toStructure(); ?>
<?php if ($menus->isNotEmpty()): ?>
    <?php foreach ($menus as $menu): ?>

        <?php $menuItems = $menu->menuItems()->toPages(); ?>
        <?php if ($menuItems->isNotEmpty()): ?>
            <nav class="footer-menu">
                <h4><?= $menu->menuHeadline()->html() ?></h4>
                <ul>
                    <?php foreach ($menuItems as $menuItem): ?>
                        <li><a <?php e($menuItem->isOpen(), 'aria-current="page"') ?> href="<?= $menuItem->url() ?>"><?= $menuItem->title() ?></a></li>
                    <?php endforeach ?>
                </ul>
            </nav>
        <?php endif ?>

    <?php endforeach ?>
<?php endif ?>

<h1><?= $page->title() ?></h1>

And I’m getting nothing new printed in the page.

If i put a <pre><?php var_dump($site); ?></pre>

This is what I get:

object(Kirby\Cms\Site)#84 (9) {
  ["content"]=>
  object(Kirby\Content\Content)#246 (3) {
    ["title"]=>
    string(10) "Site Title"
    ["menuheadline"]=>
    string(0) ""
    ["menuitems"]=>
    string(77) "- page://bnp0bgiocomomhia
- page://tq90bjha1bksxnfn
- page://lai9xrwcqapopaml"
  }
  ["translations"]=>
  array(1) {
    ["en"]=>
    array(4) {
      ["code"]=>
      string(2) "en"
      ["content"]=>
      array(3) {
        ["title"]=>
        string(10) "Site Title"
        ["menuheadline"]=>
        string(0) ""
        ["menuitems"]=>
        string(77) "- page://bnp0bgiocomomhia
- page://tq90bjha1bksxnfn
- page://lai9xrwcqapopaml"
      }
      ["exists"]=>
      bool(true)
      ["slug"]=>
      NULL
    }
  }
  ["children"]=>
  object(Kirby\Cms\Pages)#231 (3) {
    [0]=>
    string(5) "areas"
    [1]=>
    string(5) "error"
    [2]=>
    string(4) "home"
  }
  ["errorPage"]=>
  string(5) "error"
  ["files"]=>
  object(Kirby\Cms\Files)#250 (0) {
  }
  ["homePage"]=>
  string(4) "home"
  ["page"]=>
  string(4) "home"
  ["title"]=>
  string(10) "Site Title"
  ["url"]=>
  string(21) "http://localhost:8080"
}

By the way, I added the part mentioned above to kirby5plain/site/blueprints/site.yml

title: Site

sections:
  pages:
    type: pages
    layout: table
    search: true
  areas:
    extends: sections/areas
  menus:
    type: fields
    fields:
      menuHeadline:
        type: text
        label: Menu headline
      menuItems:
        type: pages
        label: Menu item

Could you post the complete resulting site.yml, please?

Sure, I updated my previous port. Thanks

This should work:

title: Site

sections:
  pages:
    type: pages
    layout: table
    search: true
  areas:
    extends: sections/areas
  menus:
    type: fields
    fields:
      menu:
        type: structure
        fields:
          menuHeadline:
            type: text
            label: Menu headline
          menuItems:
            type: pages
            label: Menu item
1 Like

Thanks both. I think Iḿ pretty close to what I need.

I finally have separated the menus.yml

title: Menus

sections:
  menus:
    type: pages
    template: menu
    layout: cardlets

and menu.yml

title: Menu

sections:
  menus:
    type: fields
    fields:
      menu:
        type: structure
        fields:
          menuHeadline:
            type: text
            label: Menu headline
          menuItems:
            type: pages
            label: Menu item

from the site.yml

title: Site

sections:
  pages:
    type: pages
    layout: table
    search: true
  areas:
    extends: sections/areas

Now this is how the setup looks like in the back end:

What I still don’t have figured out is how can I access this menu data from the front end.

At the moment I’m testing it on the: kirby5plain/site/templates/default.php

<?php $menus = $site->menus()->toStructure(); ?>
<?php if ($menus->isNotEmpty()): ?>
    <?php foreach ($menus as $menu): ?>

        <?php $menuItems = $menu->menuItems()->toPages(); ?>
        <?php if ($menuItems->isNotEmpty()): ?>
            <nav class="footer-menu">
                <h4><?= $menu->menuHeadline()->html() ?></h4>
                <ul>
                    <?php foreach ($menuItems as $menuItem): ?>
                        <li><a <?php e($menuItem->isOpen(), 'aria-current="page"') ?> href="<?= $menuItem->url() ?>"><?= $menuItem->title() ?></a></li>
                    <?php endforeach ?>
                </ul>
            </nav>
        <?php endif ?>

    <?php endforeach ?>
<?php endif ?>

<h1><?= $page->title() ?></h1>

$site->menus() does not show anything.

Thank you again for your help.

If the menus are no longer stored in $site but in the menus page, you need to fetch the data from that page. So replace $site with page('menus/main-navigation')->menu()->toStructure()

For some reason it’s not working.

So I have tried <?php var_dump(page('menus/main-navigation')) ?>

and I get NULL

Hm, if I understand your structure right, you now have a page called menus, and a subpage for every menu like main-navigation etc?

Make sure that the from the parent to the child is correct in the page()helper.

Yes @texnixe that’s how it is, so it should work i suppose..

I post this, maybe it would help guessing what am I doing wrong:

<pre><?php var_dump(page('menus')) ?></pre>
object(Kirby\Cms\Page)#235 (15) {
  ["content"]=>
  object(Kirby\Content\Content)#250 (2) {
    ["title"]=>
    string(5) "menus"
    ["uuid"]=>
    string(16) "kqmxaurppyf5ygw1"
  }
  ["translations"]=>
  object(Kirby\Content\Translations)#256 (1) {
    [0]=>
    string(2) "en"
  }
  ["children"]=>
  object(Kirby\Cms\Pages)#252 (0) {
  }
  ["files"]=>
  object(Kirby\Cms\Files)#247 (0) {
  }
  ["id"]=>
  string(5) "menus"
  ["mediaUrl"]=>
  string(39) "http://localhost:8080/media/pages/menus"
  ["mediaRoot"]=>
  string(61) "/home/ant0nio/Projects/english1/kirby5plain/media/pages/menus"
  ["num"]=>
  NULL
  ["parent"]=>
  NULL
  ["slug"]=>
  string(5) "menus"
  ["template"]=>
  object(Kirby\Template\Template)#251 (3) {
    ["defaultType":protected]=>
    string(4) "html"
    ["name":protected]=>
    string(7) "default"
    ["type":protected]=>
    string(4) "html"
  }
  ["uid"]=>
  string(5) "menus"
  ["uri"]=>
  string(5) "menus"
  ["url"]=>
  string(27) "http://localhost:8080/menus"
  ["siblings"]=>
  object(Kirby\Cms\Pages)#231 (4) {
    [0]=>
    string(5) "areas"
    [1]=>
    string(5) "error"
    [2]=>
    string(4) "home"
    [3]=>
    string(5) "menus"
  }
}

Maybe some error in my .yml files here: Menu builder for Kirby v5 - #7 by riverboat

Ah, ok, sorry, I missed that the children are still drafts, so you need to fetch them via

$kirby->page('menus/main-navigation')

I have just figured out if was because of their draft status. I took note of your suggestion for those cases $kirby->page(‘menus/main-navigation’)

Many thanks for your help @texnixe and @silvan !

1 Like