A quick way to create menus in Laravel
A quick and easy way to create menus in Laravel 6, 7 and 8
For Laravel 4.x, check version 1.5.0
composer require lavary/laravel-menuIf you are in Laravel 5.5 you won't need to edit your config/app.php, if you are in a previous version of Laravel, please do the following:
Append Laravel Menu service provider to providers array in config/app.php.
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Foundation\Providers\ArtisanServiceProvider::class,
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
...
Lavary\Menu\ServiceProvider::class,
...
],At the end of config/app.php add 'Menu' => Lavary\Menu\Facade::class to the $aliases array:
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
...
'Menu' => Lavary\Menu\Facade::class,
],This registers the package with Laravel and creates an alias called Menu.
To use your own settings, publish config.
php artisan vendor:publish --provider="Lavary\Menu\ServiceProvider"You can define the menu definitions inside a laravel middleware. As a result anytime a request hits your application, the menu objects will be available to all your views.
php artisan make:middleware GenerateMenusBe sure to also add the middleware to the app\Http\Kernel.php
protected $middlewareGroups = [
'web' => [
//...
\App\Http\Middleware\GenerateMenus::class,
],
//...
];Open the middleware you just created app\Http\Middleware\GenerateMenus.php
Then add a basic menu declaration. For example:
public function handle($request, Closure $next)
{
\Menu::make('MyNavBar', function ($menu) {
$menu->add('Home');
$menu->add('About', 'about');
$menu->add('Services', 'services');
$menu->add('Contact', 'contact');
});
return $next($request);
}Finally, open a view and add:
{!! $MyNavBar->asUl() !!}Your menu will be created and displayed on the page.
Note: $MyNavBar is just a hypothetical name used in these examples; You may name your menus whatever you please.
In the above example Menu::make() creates a menu named MyNavBar, Adds the menu instance to the Menu::collection and ultimately makes $myNavBar object available across all application views.
This method accepts a callable inside which you can define your menu items. add method defines a new item. It receives two parameters, the first one is the item title and the second one is options.
The second parameter, options, can be a simple string representing a URL or an associative array of options and HTML attributes which we'll discuss shortly.
You can use Menu::exists() to check if the menu already exists.
Menu::exists('primary'); // returns false
Menu::make('primary', function(){});
Menu::exists('primary'); // returns trueYou can use Menu::makeOnce() to ensure the make callback is only called if a menu by the given name does not yet exist. This can be useful if you are creating the same menu in multiple places conditionally, and are unsure whether other conditions have caused the menu to be created already.
Menu::makeOnce('primary', function(){}); // Creates primary, and executes callback.
Menu::makeOnce('primary', function(){}); // No operation.To render the menu in your view:
Laravel-menu provides three rendering methods out of the box. However you can create your own rendering method using the right methods and attributes.
As noted earlier, laravel-menu provides three rendering formats out of the box, asUl(), asOl() and asDiv(). You can read about the details here.
{!! $MyNavBar->asUl() !!}You can also access the menu object via the menu collection:
{!! Menu::get('MyNavBar')->asUl() !!}This will render your menu like so:
Home
About
Services
Contact
And that's all about it!
You can simply assign a URL to your menu item by passing the URL as the second argument to add method:
$menu->add('About Us', 'about-us');laravel-menu supports named routes as well:
This time instead of passing a simple string to add(), we pass an associative with key route and a named route as value:
// Suppose we have these routes defined in our app/routes.php file
//...
Route::get('/', ['as' => 'home.page', function(){...}]);
Route::get('about', ['as' => 'page.about', function(){...}]);
//...
// Now we make the menu:
Menu::make('MyNavBar', function($menu){
$menu->add('Home', ['route' => 'home.page']);
$menu->add('About', ['route' => 'page.about']);
});Laravel Menu supports controller actions as well.
You will just need to set action key of your options array to a controller action:
Suppose we have these routes defined in our routes/web.php or the older app/Http/routes.php file:
Route::get('services', 'ServiceController@index');Then to refer to this route, we can pass the action into the options array.
$menu->add('services', ['action' => 'ServicesController@index']);Additionaly: if you need to send some parameters to routes, URLs or controller actions as a query string, you can simply include them in an array along with the route, action or URL value:
Menu::make('MyNavBar', function($menu){
$menu->add('Home', ['route' => 'home.page']);
$menu->add('About', ['route' => ['page.about', 'template' => 1]]);
$menu->add('services', ['action' => ['ServicesController@index', 'id' => 12]]);
$menu->add('Contact', 'contact');
});By default, the HTTP vs HTTPS will be determined by Laravel's UrlGenerator which matches the current schema of the page.
If you need to overwrite this behavior, call secure() on the item's link attribute to force https. Alternatively add key secure to the options array and set it to true:
$menu->add('Members', 'members')->link->secure();
// or alternatively use the following method
$menu->add('Members', ['url' => 'members', 'secure' => true]);
The output as would be:
...
Members
...
Items can have sub-items too:
Menu::make('MyNavBar', function($menu){
//...
$menu->add('About', ['route' => 'page.about']);
// these items will go under Item 'About'
// refer to about as a property of $menu object then call `add()` on it
$menu->about->add('Who We are', 'who-we-are');
// or
$menu->get('about')->add('What We Do', 'what-we-do');
// or
$menu->item('about')->add('Our Goals', 'our-goals');
//...
});You can also chain the item definitions and go as deep as you wish:
$menu->add('About', ['route' => 'page.about'])
->add('Level2', 'link address')
->add('level3', 'Link address')
->add('level4', 'Link address');It is possible to add sub items directly using parent attribute:
$menu->add('About', ['route' => 'page.about']);
$menu->add('Level2', ['url' => 'Link address', 'parent' => $menu->about->id]);When you add a new item, a unique ID is automatically assigned to the item. However, there are time when you're loading the menu items from the database and you have to set the ID manually. To handle this, you can call the id() method against the item's object and pass your desired ID:
$menu->add('About', ['route' => 'page.about'])
->id('74398247329487')Alternatively, you can pass the ID as an element of the options array when adding the menu item:
$menu->add('About', ['route' => 'page.about', 'id' => 74398247329487]);When you add a new item, a nickname is automatically assigned to the item for further reference. This nickname is the camel-cased form of the item's title. For instance, an item with the title: About Us would have the nickname: aboutUs.
However there are times when you have to explicitly define your menu items owing to a special character set you're using. To do this, you may simply use the nickname() method against the item's object and pass your desired nickname to it:
$menu->add('About', ['route' => 'page.about'])
->nickname('about_menu_nickname');
// And use it like you normally would
$menu->item('about_menu_nickname');Alternatively, you can pass the nickname as an element of the options array:
$menu->add('About', ['route' => 'page.about', 'nickname' => 'about_menu_nickname']);
// And use it like you normally would
$menu->item('about_menu_nickname'); You can access defined items throughout your code using the methods described below.
Use $menu followed by the item's title in camel case:
$menu->itemTitleInCamelCase
// or
$menu->get('itemTitleInCamelCase')
// or
$menu->item('itemTitleInCamelCase')As an example, let's insert a divider
No open issues yet, or sync has not completed.