vynatu / menu
An extendable and async menu package for Laravel
Requires
- php: >=7.0
- illuminate/support: ^5.0
This package is not auto-updated.
Last update: 2024-11-10 03:00:18 UTC
README
Find the API documentation here
Introduction
This package is yet another menu library. This library is different than the others because:
- It is lazy loaded
- Any menu is extendable
- It is not loaded in a middleware
- Each menu declaration is in it's own class
This structure makes it perfect to modularize and extend your menus through the usage of different module libraries the laravel framework can support.
Installation
Vynatu/Menu only uses a single service provider
.
First, install with composer:
composer require vynatu/menu
Then, add the service provider to app.php
:
<?php 'providers' => [ ... Vynatu\Menu\MenuServiceProvider::class, ]
Vynatu/Menu does not require an alias. You can call the menu manager directly using app('menu').
Creating a Menu
Setup the Service Provider
You can register menus in any service provider you use, but I prefer making a new service provider called MenuServiceProvider
.
This allows you to better separate what the AppServiceProvider
does and the new MenuServiceProvider
that is solely used to register and extend menus.
Create a new service provider (using Artisan):
artisan make:provider MenuServiceProvider
Don’t forget to register it in the providers!:
<?php 'providers' => [ ... App\Providers\MenuServiceProvider::class, ]
Create the New Menu
Vynatu/Menu comes with a console command that lets you create menu classes very easily.
artisan make:menu MainMenu
We suggest you put your Menus in a sub-folder (app/Menus).
Or you can make the class yourself:
<?php namespace App\Menus; use Vynatu\Menu\MenuInstance; class AdminMainMenu extends MenuInstance { public function generate() { // } }
After creating your menu class, an instance of
\Vynatu\Menu\RootMenuItem
will automatically be injected in yourMenuInstance
.
Add items to the menu
You can add items to the menu by using the $this->menu
instance.
<?php function generate() { $this->menu->add('Dashboard')->url('/home'); // Method 1 $this->menu->add('My Account', '/'); // Method 2 $this->menu->add('List Users', 'route:users.list'); // Method 3 $this->menu->add('Seperator')->section(); // Method 4 $this->menu->add('Edit Myself', 'route:users.edit|id:5'); // Method 5 $this->menu->add('Logout')->route('auth.logout'); // Method 6 $this->menu->add('Some Other Link', ['url' => '/link']); // Method 7 }
Registering the menu
In the menu service provider you have previously created, add this to the boot method:
<?php function boot(\Vynatu\Menu\MenuManager $menu) { $menu->register('main_menu', \App\Menus\MainMenu::class); }
You don't have to use dependency injection. You can use
app('menu')->register(...)
instead.
Extending a menu
Do the same steps as creating and registering a menu, but instead of using the register method:
<?php function boot(\Vynatu\Menu\MenuManager $menu) { $menu->extend('main_menu', \App\Menus\MainMenuExtender::class); }
Accessing menu items in a menu instance
You can access any menu items in a menu instance this way:
<?php public function generate() { $this->menu->management->add(...); }
The management
variable is created automatically when a new menu item is added. snake_case
is used to create the variable name.
This means that if you created an item like $this->menu->add('Management')
, a new variable called management
will exist and can be accessed by the local menu instance or any menu extender.
If you use _t
to create menu names (which means the slug name will always change), you can set the slug name statically:
<?php public function generate() { $this->menu->add(_t('menus.management'))->route('admin.management')->slug('management'); }
This allow your other extenders to access the management
menu item and, for example, change its icon:
<?php public function generate() { $this->menu->management->icon('fa fa-home'); }
Setting variables to a menu item
There are two ways to do this.
The first one, using a function
. It is useful to conserve the fluent
API:
<?php public function generate() { $this->menu->management->icon('fa fa-home'); }
The second one, using a direct variable assignment
:
<?php public function generate() { $this->menu->management->icon = 'fa fa-home'; }
Everything can be changed in an extender, including the route and URL.
Views
Item iteration in views
Here is an example using bootstrap navbar:
File Name: menus.main_menu
<nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Some Menu Example</a> </div> <div id="navbar" class="navbar-collapse collapse"> <ul class="nav navbar-nav"> @include('menu::bootstrap.default', ['menu' => $menu]) </ul> </div><!--/.nav-collapse --> </div><!--/.container-fluid --> </nav>
File Name: menu_elements (Also available under view('menu::bootstrap.default')
)
@foreach($menu->items() as $item) @if($item->hasSubItems()) <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ $item->title }}<span class="caret"></span></a> <ul class="dropdown-menu"> @include('menu_elements', ['menu' => $item]) </ul> </li> @else <li @if($item->active()) class="active" @endif> <a href="{{ $item->url }}">{{ $item->title }}</a> </li> @endif @endforeach
This should achieve a menu looking like the default bootstrap navbar
Tips
- The
__construct
of your menu class works with dependency injection. Simply type hint the stuff you need in the parameter list and we'll ask Laravel to inject the stuff you need.