Skip to content

You can set the filters you want to include for rendering the menu using the filters configuration of the config file. You can add your own filters to this array after you've created them. The current default set of menu filters is:

php
'menu_filters' => [
    CodeCoz\AimAdmin\MenuBuilder\Filters\HrefFilter::class,
    CodeCoz\AimAdmin\MenuBuilder\Filters\ActiveFilter::class,
    CodeCoz\AimAdmin\MenuBuilder\Filters\ClassesFilter::class,
],

If you need to use a custom menu filter, you can add your own menu filters to the previous array. This can be useful, for example, when you are using a third-party package for authorization (instead of Laravel's Gate functionality) OR for menu item modification for certain purposes.

Laravel Permission

In order to use Laravel Permission, we are going to show an example of how you can configure. Start by creating your custom filter implementation:

php
<?php

namespace App\Filter;

use Illuminate\Support\Facades\Auth;
use CodeCoz\AimAdmin\Menu\Filters\FilterInterface;

class RolePermissionMenuFilter implements FilterInterface
{
    public function transform($item)
    {
        if (!$this->isVisible($item)) {
            return false;
        }

        return $item['header'] ?? $item;
    }

    protected function isVisible($item)
    {
        $user = Auth::user();

        // Check for roles
        $hasAnyRole = $item['hasAnyRole'] ?? null;
        $hasRole = $item['hasRole'] ?? null;

        if (($hasAnyRole && $user->hasAnyRole($hasAnyRole)) || ($hasRole && $user->hasRole($hasRole))) {
            return true;
        }

        return $this->checkPermissions($item, $user) ?? true;
    }

    protected function checkPermissions($item, $user)
    {
        $hasAnyPermission = $item['hasAnyPermission'] ?? null;
        return $hasAnyPermission ? $user->hasAnyPermission($hasAnyPermission) : null;
    }
}

And then add the following configuration to the config/aim-admin.php file:

php
'filters' => [
    ...
        CodeCoz\AimAdmin\MenuBuilder\Filters\HrefFilter::class,
        CodeCoz\AimAdmin\MenuBuilder\Filters\ActiveFilter::class,
        CodeCoz\AimAdmin\MenuBuilder\Filters\ClassesFilter::class,
        
        \App\Filter\RolePermissionMenuFilter::class,
]

Dynamic Menu Configuration

You can configure the menu dynamically at runtime, such as in the boot method of a service provider or from a controller. This allows you to add new menu items at the end, before or after a specific item, or as a submenu item. This feature is useful when your menu depends on your database or locale configuration.

You can also combine static and dynamic menu configurations. The menu items will be concatenated, and the order of service providers will determine the menu order.

Available Menu Builder Methods

  • add(...$newItems)

    • Adds one or multiple menu items to the sidebar or top navigation menus.
  • addAfter($itemKey, ...$newItems)

    • Adds one or multiple menu items after a specific menu item, identified by its key.
  • addBefore($itemKey, ...$newItems)

    • Adds one or multiple menu items before a specific menu item, identified by its key.
  • addIn($itemKey, ...$newItems)

    • Adds one or multiple menu items inside a specific menu item, as submenu or child items, identified by its key.
  • remove($itemKey)

    • Removes a specific menu item, identified by its key.
  • itemKeyExists($itemKey)

    • Checks if a specific menu item exists, identified by its key.

These methods allow you to dynamically adjust the menu to fit your application's needs.

Here's a basic overview of how to use the menu builder methods. First, add a key attribute to a menu item:

php
[
    'key' => 'tickets',
    'text' => 'Tickets',
    'url' => 'admin/tickets',
    'icon' => 'fas fa-file',
],

This key will be used to identify and manipulate the menu item.

Configuration in Event Service Provider

The event-based approach ensures that the menu is built only when the admin panel is displayed, not on every request (e.g., AJAX calls).

Important

The following examples are somewhat obsolete. In the latest versions of Laravel, it's recommended to define a Listener for the BuildingMenu event as explained in Laravel's Events Documentation. However, the code can still be used as a reference.

To configure the menu at runtime, register a handler or callback for the BuildingMenu event in the boot() method of app/Providers/EventServiceProvider.php

php
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use CodeCoz\AimAdmin\MenuBuilder\Events\BuildingMenu;

class EventServiceProvider extends ServiceProvider
{
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        Event::listen(BuildingMenu::class, function (BuildingMenu $event) {
            // Add some items to the menu...
            $event->menu->add('Settings');
            $event->menu->add([
                'text' => 'Tickets',
                'url' => 'admin/tickets',
            ]);
        });
    }
}

Example with More Details using Menu Builder Methods

php
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use CodeCoz\AimAdmin\MenuBuilder\Events\BuildingMenu;

class EventServiceProvider extends ServiceProvider
{
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        Event::listen(BuildingMenu::class, function (BuildingMenu $event) {
            // Add some items to the menu...
            $event->menu->addAfter('tickets', [
                'key' => 'ticket_settings',
                'header' => 'Ticket Settings',
            ]);

            $event->menu->addIn('ticket_settings', [
                'key' => 'ticket_settings_notifications',
                'text' => 'Notifications',
                'icon' => 'fa fa-bell',
                'url' => 'edit/ticket/notifications',
            ]);

            $event->menu->addBefore('ticket_settings_notifications', [
                'key' => 'ticket_settings_permissions',
                'text' => 'Permissions',
                'icon' => 'fa fa-cogs',
                'url' => 'edit/ticket/permissions',
            ]);
        });
    }
}

This example adds menu items dynamically, placing them relative to the tickets menu item:

addAfter('tickets', [...])

Adds a "Ticket Settings" header after the "tickets" item.

addIn('ticket_settings', [...])

Adds a "Notifications" item inside the "Ticket Settings" menu.

addBefore('ticket_settings_notifications', [...])

Adds a "Profile" item before the "Notifications" item within the "Ticket Settings" menu.

Practical Example with Database

Here is a more practical example that uses database data:

php
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use CodeCoz\AimAdmin\MenuBuilder\Events\BuildingMenu;
use App\Models\Ticket;

class EventServiceProvider extends ServiceProvider
{
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        Event::listen(BuildingMenu::class, function (BuildingMenu $event) {

            $items = Ticket::all()->map(function (Ticket $ticket) {
                return [
                    'text' => $ticket['title'],
                    'url' => route('admin.tickets.edit', $ticket)
                ];
            });

            $event->menu->add(...$items);
        });
    }
}

Developed By ❤️ Taki Elias