saeedhosan/laravel-menus

The package is for laravel menu builder

Maintainers

Package info

github.com/saeedhosan/laravel-menus

pkg:composer/saeedhosan/laravel-menus

Statistics

Installs: 300

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.0.0 2026-03-27 14:36 UTC

This package is auto-updated.

Last update: 2026-04-17 17:29:53 UTC


README

Simple, flexible menu builder for Laravel.

Requirements

  • PHP 8.2+
  • Laravel 11, 12, or 13

Installation

composer require saeedhosan/laravel-menus

The service provider is auto-discovered. To publish the config and views:

php artisan vendor:publish --tag=laravel-menus-config
php artisan vendor:publish --tag=laravel-menus-views

Creating a Menu

Create a class that extends MenuBuilder and define your items:

use SaeedHosan\Menus\MenuBuilder;

class AdminMenu extends MenuBuilder
{
    public function items(): array
    {
        return [
            [
                'name' => 'Dashboard',
                'slug' => 'admin.dashboard',
                'link' => route('admin.dashboard'),
                'icon' => '<i class="ki-outline ki-home"></i>',
                'active' => request()->routeIs('admin.dashboard'),
            ],
            [
                'name' => 'Users',
                'slug' => 'admin.users',
                'link' => route('admin.users.index'),
                'active' => request()->routeIs('admin.users.*'),
                'access' => 'manage-users',
            ],
        ];
    }
}

Item Properties

Key Type Description
name string Display label
slug string Unique identifier used for positioning
link string URL (optional)
icon string Icon HTML (defaults to a bullet dot)
active bool Marks item as active
access string|array Permission(s) checked via access callback
badge string|array Badge text, or ['text', 'css-class']
separator bool Renders as a section heading
submenu array Nested menu items

Registering Menus

Register your menus in a service provider:

use SaeedHosan\Menus\Menu;

// Root menu
Menu::create(AdminMenu::class);

// Child menu — items appended to AdminMenu
Menu::create(ReportsMenu::class, AdminMenu::class);

Positioning Child Items

Control where child items are placed using the fluent filter API:

// Insert after a specific slug
Menu::create(ReportsMenu::class, AdminMenu::class)->after('admin.users');

// Insert before a specific slug
Menu::create(ReportsMenu::class, AdminMenu::class)->before('admin.users');

// Insert into a specific item's submenu
Menu::create(ReportsMenu::class, AdminMenu::class)->whereSlug('admin.settings');

// Force as submenu of matched item
Menu::create(ReportsMenu::class, AdminMenu::class)->asSubmenu()->whereSlug('admin.settings');

// Filter which items get merged
Menu::create(ReportsMenu::class, AdminMenu::class)->filter(fn ($item) => $item['slug'] !== 'hidden');

Updating a Menu's Parent

Move an existing menu registration to a different parent:

Menu::update(ReportsMenu::class, NewParentMenu::class)->after('some.slug');

Rendering

As Array

$items = Menu::make()->items();

return view('layouts.app', ['items' => $items]);

As HTML

The package ships with Blade views compatible with Metronic/Bootstrap sidebar menus:

{!! Menu::make()->toHtml() !!}

You can customize the views after publishing them:

php artisan vendor:publish --tag=laravel-menus-views

Views are published to resources/views/vendor/laravel-menus.

Access Control

Items with an access key are filtered through a configurable callback. The default uses Laravel's Gate:

// config/laravel-menus.php
'access_callback' => \SaeedHosan\Menus\Access\GateAccessCallback::class,

Define permissions on your items:

[
    'name' => 'Reports',
    'slug' => 'reports',
    'access' => 'view-reports',        // single permission
    // 'access' => ['view-reports', 'admin'], // multiple permissions
]

To use a custom callback, create an invokable class:

class MyAccessCallback
{
    public function __invoke(string|array $permissions): bool
    {
        // your logic
    }
}

Renderable Condition

Control whether a menu renders at all by overriding renderable():

class AdminMenu extends MenuBuilder
{
    public function renderable(): bool
    {
        return auth()->user()?->isAdmin() ?? false;
    }

    public function items(): array
    {
        return [ /* ... */ ];
    }
}

Badges

MenuBuilder provides badge helpers you can use in your items:

class AdminMenu extends MenuBuilder
{
    public function items(): array
    {
        return [
            [
                'name' => 'Feature',
                'slug' => 'feature',
                'badge' => $this->badgeNew(),    // "New" green badge
                // 'badge' => $this->badgeBeta(),  // "Beta" primary badge
                // 'badge' => $this->badgeSoon(),  // "Soon" light badge
                // 'badge' => $this->badgeInfo(),  // "info" info badge
            ],
        ];
    }
}

Testing

composer test

License

MIT