This package allows you to easily build a hierarchical menu from PHP. It's inspired by Crisp's blogpost but further implemented.
This package requires PHP 7.4+ and the renderers make use of vdhicts/html-element.
This package can be used in any PHP project or with any framework.
You can install the package via composer:
composer require vdhicts/menu-builder
use Vdhicts\Menu;
$item = new Menu\Item(1, 'Search engines');
$subItemGoogle = new Menu\Item(2, 'Google', 'http://www.google.com', $item->getId());
$subItemBing = new Menu\Item(3, 'Bing', 'http://www.bing.com', $item->getId());
$itemCollection = new Menu\ItemCollection();
$itemCollection->addItem($item)
->addItem($subItemGoogle)
->addItem($subItemBing);
$renderer = new Menu\Renderers\Navbar();
$menuBuilder = new Menu\Builder($itemCollection, $navbar);
$menuBuilder->generate();
There are 3 renderers available by default:
Usefull for things like sidebars or sidemenu's. Renders the menu as a Bootstrap list-group component:
<ul class="list-group">
<li class="list-group-item">Search engines
<ul class="list-group">
<li class="list-group-item">
<a href="http://www.google.com">Google</a>
</li>
<li class="list-group-item list-group-item-divider"></li>
<li class="list-group-item">
<a href="http://www.bing.com">Bing</a>
</li>
</ul>
</li>
</ul>
Usefull for things like footers. Renders the menu as a Bootstrap list-inline component:
<ul class="list-inline">
<li>Search engines
<ul class="list-inline">
<li>
<a href="http://www.google.com">Google</a>
</li>
<li class="list-inline-divider"></li>
<li>
<a href="http://www.bing.com">Bing</a>
</li>
</ul>
</li>
</ul>
This generates the content of the navbar, so additional HTML is needed to provide the full navbar.
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Search engines<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>
<a href="http://www.google.com">Google</a>
</li>
<li class="divider" role="separator"></li>
<li>
<a href="http://www.bing.com">Bing</a>
</li>
</ul>
</li>
</ul>
You can use your own renderer as long as it implements the Renderer
interface.
When storing the data in a database, you should at least have an id
, parentId
and name
. The id isn't limited to
integers so a UUID or slug should work too.
To help you get started, use the following sql to generate the menu tables.
CREATE TABLE `menu` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `menu_items` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`target` varchar(255) DEFAULT NULL,
`is_divider` tinyint(1) unsigned NOT NULL DEFAULT '0',
`parent_id` int(10) unsigned DEFAULT NULL,
`menu_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `menu_items_could_have_a_parent` (`parent_id`),
KEY `menu_items_could_belongs_to_a_menu` (`menu_id`),
CONSTRAINT `menu_items_could_belongs_to_a_menu` FOREIGN KEY (`menu_id`) REFERENCES `menu` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT `menu_items_could_have_a_parent` FOREIGN KEY (`parent_id`) REFERENCES `menu_items` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
This generates a menu table in which you can store the menu itself. This enables you to have several different menu's. Also the menu items table is generated which has a foreign key to the menu and to its parent menu item.
To retrieve the items, just execute the following query:
SELECT
`id`,
`parent_id`,
`name`
FROM
`menu_items`
WHERE
`menu_id` = 1
ORDER BY
`parent_id`, `name`
In which you should replace the menu id.
Unit tests are available in the tests
folder. Run with:
composer test
When you want a code coverage report which will be generated in the build/report
folder. Run with:
composer test-coverage
Any contribution is welcome, but it should meet the PSR-12 standard and please create one pull request per feature/bug. In exchange, you will be credited as contributor on this page.
If you discover any security related issues in this or other packages of Vdhicts, please email security@vdhicts.nl instead of using the issue tracker.
This package is open-sourced software licensed under the MIT license.
Vdhicts is the name of my personal company for which I work as freelancer. Vdhicts develops and implements IT solutions for businesses and educational institutions.