Maison >développement back-end >tutoriel php >Créer des menus dynamiques et maintenables dans Laravel

Créer des menus dynamiques et maintenables dans Laravel

Patricia Arquette
Patricia Arquetteoriginal
2024-12-14 22:28:12164parcourir

La gestion des menus de navigation peut devenir difficile dans les applications Laravel à mesure qu'elles se développent, en particulier avec des éléments dynamiques tels que les contrôles d'accès basés sur les rôles. Cet article de blog explique comment simplifier et structurer vos menus à l'aide d'un système Menu Builder, ce qui les rend plus faciles à maintenir, à étendre et à faire évoluer.


Le problème

Dans de nombreux projets Laravel, les modèles Blade gèrent la visibilité des menus à l'aide de conditions :

@can('viewAdmin')
    <a href="{{ route('administration.index') }}">
        {{ __('Administration') }}
    </a>
@endcan

Bien que cette approche fonctionne pour des applications simples, elle devient encombrée et ingérable à mesure que le nombre de menus augmente.


La solution

Un système Menu Builder encapsule la logique du menu dans des classes réutilisables, améliorant :

  1. Maintenabilité : Définitions de menus centralisées.
  2. Évolutivité : génération dynamique de menus basés sur des rôles ou des autorisations.
  3. Réutilisabilité : partage de menus entre les vues.

Soutenez ma mission visant à responsabiliser la communauté des développeurs en parrainant mon travail : vos contributions m'aident à créer et à partager des outils, des informations et des ressources précieux : pour en savoir plus, cliquez ici.


Mise en œuvre étape par étape

1. Définir une porte pour viewAdmin

Pour contrôler l'accès au menu d'administration, définissez une porte viewAdmin dans votre AuthServiceProvider :

use Illuminate\Support\Facades\Gate;
use App\Models\User;

class AuthServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $this->registerPolicies();

        Gate::define('viewAdmin', function (User $user) {
            return $user->hasRole('admin'); // Replace with your app's role-checking logic
        });
    }
}

2. Créez la classe MenuItem

La classe MenuItem définit tous les attributs d'un élément de menu, tels que l'étiquette, l'URL, l'icône et la visibilité :

<?php

namespace App\Actions\Builder;

use CleaniqueCoders\Traitify\Contracts\Builder;
use InvalidArgumentException;

class MenuItem implements Builder
{
    private string $label;
    private string $url;
    private string $target = '_self';
    private array $attributes = [];
    private array $children = [];
    private string $icon = 'o-squares-2x2';
    private ?string $description = null;
    private ?string $tooltip = null;
    private $visible = true;
    private array $output = [];

    public function setLabel(string $label): self
    {
        $this->label = $label;

        return $this;
    }

    public function setUrl(string $url): self
    {
        $this->url = $url;

        return $this;
    }

    public function setTarget(string $target): self
    {
        $this->target = $target;

        return $this;
    }

    public function addAttribute(string $key, string $value): self
    {
        $this->attributes[$key] = $value;

        return $this;
    }

    public function addChild(MenuItem $child): self
    {
        $this->children[] = $child;

        return $this;
    }

    public function setIcon(string $icon): self
    {
        $this->icon = $icon;

        return $this;
    }

    public function setDescription(string $description): self
    {
        $this->description = $description;

        return $this;
    }

    public function setTooltip(string $tooltip): self
    {
        $this->tooltip = $tooltip;

        return $this;
    }

    public function setVisible($visible): self
    {
        if (! is_bool($visible) && ! is_callable($visible)) {
            throw new InvalidArgumentException('The visible property must be a boolean or a callable.');
        }

        $this->visible = $visible;

        return $this;
    }

    public function isVisible(): bool
    {
        return is_callable($this->visible) ? call_user_func($this->visible) : $this->visible;
    }

    public function build(): self
    {
        $this->output = [
            'label' => $this->label,
            'url' => $this->url,
            'target' => $this->target,
            'attributes' => $this->attributes,
            'icon' => $this->icon,
            'description' => $this->description,
            'tooltip' => $this->tooltip,
            'children' => array_filter(
                array_map(fn (MenuItem $child) => $child->build()->toArray(), $this->children),
                fn (array $child) => ! empty($child) 
            ),
        ];

        return $this;
    }

    public function toArray(): array
    {
        return $this->output;
    }

    public function toJson(int $options = 0): string
    {
        return json_encode($this->toArray(), $options, 512);
    }
}


3. Créez le générateur de menus

Le générateur de menus résout et construit les menus de manière dynamique :

namespace App\Actions\Builder;

class Menu
{
    public static function make()
    {
        return new self;
    }

    public function build(string $builder)
    {
        $class = match ($builder) {
            'navbar' => Navbar::class,
            'sidebar' => Sidebar::class,
            'administration' => Administration::class,
            default => Navbar::class,
        };

        $builder = new $class;
        return $builder->build();
    }
}

Accédez aux menus à l'aide d'une fonction d'assistance :

<?php

use App\Actions\Builder\Menu;

if (! function_exists('menu')) {
    function menu(string $builder)
    {
        return Menu::make()->build($builder)->menus();
    }
}

4. Menu d'administration

Définissez les éléments de menu spécifiques à l'administration dans la classe Administration :

<?php

namespace App\Actions\Builder\Menu;

use App\Actions\Builder\MenuItem;
use CleaniqueCoders\Traitify\Contracts\Builder;
use CleaniqueCoders\Traitify\Contracts\Menu;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Gate;

class Administration implements Builder, Menu
{
    private Collection $menus;

    public function menus(): Collection
    {
        return $this->menus;
    }

    public function build(): self
    {
        $this->menus = collect([
            (new MenuItem)
                ->setLabel(__('Issues'))
                ->setUrl(url(config('telescope.path')))
                ->setTarget('_blank')
                ->setVisible(fn () => Gate::allows('viewTelescope'))
                ->setTooltip(__('View Telescope issues'))
                ->setDescription(__('Access application issues using Laravel Telescope'))
                ->setIcon('o-bug'), // Heroicon outline for a bug

            (new MenuItem)
                ->setLabel(__('Queues'))
                ->setUrl(url(config('horizon.path')))
                ->setTarget('_blank')
                ->setVisible(fn () => Gate::allows('viewHorizon'))
                ->setTooltip(__('Manage queues'))
                ->setDescription(__('Access Laravel Horizon to monitor and manage queues'))
                ->setIcon('o-cog'), // Heroicon outline for settings/tasks

            (new MenuItem)
                ->setLabel(__('Access Control'))
                ->setUrl(route('security.access-control.index'))
                ->setVisible(fn () => Gate::allows('viewAccessControl'))
                ->setTooltip(__('Manage access control'))
                ->setDescription(__('Define and manage access control rules'))
                ->setIcon('o-lock-closed'), 

            (new MenuItem)
                ->setLabel(__('Users'))
                ->setUrl(route('security.users.index'))
                ->setVisible(fn () => Gate::allows('viewUser'))
                ->setTooltip(__('Manage users'))
                ->setDescription(__('View and manage user accounts'))
                ->setIcon('o-user-group'), 

            (new MenuItem)
                ->setLabel(__('Audit Trail'))
                ->setUrl(route('security.audit-trail.index'))
                ->setVisible(fn () => Gate::allows('viewAudit'))
                ->setTooltip(__('View audit trails'))
                ->setDescription(__('Audit logs for security and activity tracking'))
                ->setIcon('o-document-text'), 
        ])->reject(fn (MenuItem $menu) => ! $menu->isVisible())
            ->map(fn (MenuItem $menu) => $menu->build()->toArray());

        return $this;
    }
}

5. Définir des itinéraires

Ajoutez la configuration de route suivante pour la page d'administration :

<?php

use Illuminate\Support\Facades\Route;

Route::middleware(['auth:sanctum', 'verified', 'can:viewAdmin'])
    ->as('administration.')
    ->prefix('administration')
    ->group(function () {

        Route::view('/', 'administration.index')->name('index');

    });

6. Utilisation dans les modèles de lame

Menu de navigation (navigation-menu.blade.php) :

@can('viewAdmin')
    <a href="{{ route('administration.index') }}">
        <x-icon name="o-computer-desktop" />
        {{ __('Administration') }}
    </a>
@endcan

Menu d'administration (administration/index.blade.php) :

<x-app-layout>
    <x-slot name="header">{{ __('Administration') }}</x-slot>
    <div>




<hr>

<p><strong>Sortie</strong></p>

<p>Voici le résultat final que vous pouvez avoir :</p>

<p><img src="https://img.php.cn/upload/article/000/000/000/173418649412401.jpg" alt="Building Dynamic and Maintainable Menus in Laravel"></p><blockquote>
<p>Soutenez ma mission visant à responsabiliser la communauté des développeurs en parrainant mon travail : vos contributions m'aident à créer et à partager des outils, des informations et des ressources précieux : pour en savoir plus, cliquez ici.</p>
</blockquote>


<hr>

<h3>
  
  
  <strong>Conclusion</strong>
</h3>

<p>Ce <strong>Système Menu Builder</strong> simplifie la gestion de la navigation dans Laravel en :</p>

<ol>
<li>Centralisation des définitions de menus pour une meilleure maintenabilité.</li>
<li>Contrôle dynamique de la visibilité des menus à l'aide de rôles ou d'autorisations.</li>
<li>Réutilisation de la logique de menu dans les vues et les mises en page.</li>
</ol>

<p>En adoptant cette approche, vous pouvez faire évoluer votre système de navigation de manière transparente, même dans des applications complexes. </p>

<p>Vous souhaiterez peut-être charger les détails de votre menu à partir de la base de données et créer les menus de votre choix. Mais pour moi, c'est assez bien. Je n'ai pas de projets qui m'obligent à utiliser la configuration de menu basée sur une base de données.</p>

<p>Les codes peuvent être trouvés ici. </p>

<p>Essayez-le et partagez vos impressions ! ?</p>


<hr>

<p>Photo par LinedPhoto sur Unsplash</p>


          

            
  

            
        

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn