Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Knp Menu Laravel Package

knplabs/knp-menu

View on GitHub
Deep Wiki
Context7

Iterating over Menus

The simplest way to iterate over your item object is to iterate over its direct children, thanks to the IteratorAggregate implementation. But the PHP iterators allow much more powerful options to deal with our tree structure.

All the examples in this chapter will use the following tree:

         A
       /   \
     /       \
   B          C
 / | \      /   \
D  E  F    G     H
|          |
I          J

Iterating recursively

The Knp\Menu\Iterator\RecursiveItemIterator allows you to iterate recursively over a tree of items. Using it is really easy: give it an item, and you will have a recursive iterator on this item.

<?php

$menu = /* get your root item from somewhere */;

// create the iterator
$itemIterator = new \Knp\Menu\Iterator\RecursiveItemIterator($menu);

// iterate recursively on the iterator
$iterator = new \RecursiveIteratorIterator($itemIterator, \RecursiveIteratorIterator::SELF_FIRST);

foreach ($iterator as $item) {
    echo $item->getName() . " ";
}

The output will be:

B D I E F C G J H

Changing the second argument to \RecursiveIteratorIterator::CHILD_FIRST allows you to visit children before their parents and will produce the following order:

I D E F B J G H C

NOTE If you iterate over the RecursiveItemIterator without wrapping it in the \RecursiveIteratorIterator, it will simply give you the direct children like when using the iterator of the item.

As you can see, the final iterator does not contain the root item (A). The reason is simple: the recursive iteration started only on its children. Fortunately, the RecursiveItemIterator accept any iterator over menu items, not only items themselves. This allows you to add the root item in the final iterator by changing the iterator wrapped in the RecursiveItemIterator:

<?php

$menu = /* get your root item from somewhere */;

// create an iterator containing only the root item
$rootIterator = new \ArrayIterator([$menu]);

// create the item iterator
$itemIterator = new \Knp\Menu\Iterator\RecursiveItemIterator($rootIterator);

// iterate recursively on the iterator
$iterator = new \RecursiveIteratorIterator($itemIterator, \RecursiveIteratorIterator::SELF_FIRST);

foreach ($iterator as $item) {
    echo $item->getName() . " ";
}

The output will now contain the root item:

A B D I E F C G J H

Filtering only current items

Getting the current items is easy with the Knp\Menu\Iterator\CurrentItemFilterIterator. It is a filter iterator applied to another iterator.

<?php

$root = /* get your root item from somewhere */;
$menu = $root['B'];

$itemMatcher = new \Knp\Menu\Matcher\Matcher();

// create the iterator
$iterator = new \Knp\Menu\Iterator\CurrentItemFilterIterator($menu->getIterator(), $itemMatcher);

foreach ($iterator as $item) {
    echo $item->getName() . " ";
}

Assuming that D and F are current whereas E is not, this will output D F.

Getting the current item of the whole tree is simply done by applying the filter on the previous recursive iterator:

<?php

$menu = /* get your root item from somewhere */;

$itemMatcher = new \Knp\Menu\Matcher\Matcher();

$treeIterator = new \RecursiveIteratorIterator(
    new \Knp\Menu\Iterator\RecursiveItemIterator(
        new \ArrayIterator([$menu])
    ),
    \RecursiveIteratorIterator::SELF_FIRST
);

$iterator = new \Knp\Menu\Iterator\CurrentItemFilterIterator($treeIterator, $itemMatcher);

foreach ($iterator as $item) {
    echo $item->getName() . " ";
}

Filtering only displayed items

The Knp\Menu\Iterator\DisplayedItemFilterIterator allows you to filter items to keep only the displayed ones. As hiding an item also hides its children, this filter is a recursive filter iterator and is applied on the recursive iterator, not on the flattened iterator.

<?php

$menu = /* get your root item from somewhere */;

// create an iterator containing only the root item
$rootIterator = new \ArrayIterator([$menu]);

// create the item iterator
$itemIterator = new \Knp\Menu\Iterator\RecursiveItemIterator($rootIterator);

// wrap the iterator in the filter iterator
$filteredIterator = new \Knp\Menu\Iterator\DisplayedItemFilterIterator($itemIterator);

// iterate recursively on the iterator
$iterator = new \RecursiveIteratorIterator($filteredIterator, \RecursiveIteratorIterator::SELF_FIRST);

foreach ($iterator as $item) {
    echo $item->getName() . " ";
}

Assuming that E and F are hidden, and that C is displayed but hides its children, the output will be:

A B D I C
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin