Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.
/ menu-builder Public archive

Build hierarchical menu's in PHP based on a single database table and query

License

Notifications You must be signed in to change notification settings

vdhicts/menu-builder

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Menu

This package allows you to easily build a hierarchical menu from PHP. It's inspired by Crisp's blogpost but further implemented.

Requirements

This package requires PHP 7.4+ and the renderers make use of vdhicts/html-element.

Installation

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

Usage

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();

Renderers

There are 3 renderers available by default:

List group

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>

List inline

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>

Navbar

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>

Custom renderer

You can use your own renderer as long as it implements the Renderer interface.

Database

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.

database structure

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.

Tests

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

Contribution

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.

Security

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.

License

This package is open-sourced software licensed under the MIT license.

About vdhicts

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.