> 백엔드 개발 > PHP 튜토리얼 > Laravel에서 동적이며 유지 관리 가능한 메뉴 만들기

Laravel에서 동적이며 유지 관리 가능한 메뉴 만들기

Patricia Arquette
풀어 주다: 2024-12-14 22:28:12
원래의
162명이 탐색했습니다.

Laravel 애플리케이션이 성장함에 따라 탐색 메뉴 관리가 어려울 수 있으며, 특히 역할 기반 액세스 제어와 같은 동적 요소가 있는 경우 더욱 그렇습니다. 이 블로그 게시물에서는 메뉴 빌더 시스템을 사용하여 메뉴를 단순화하고 구조화하여 유지 관리, 확장 및 확장을 더 쉽게 만드는 방법을 살펴봅니다.


문제

많은 Laravel 프로젝트에서 블레이드 템플릿은 조건문을 사용하여 메뉴 가시성을 처리합니다.

@can('viewAdmin')
    <a href="{{ route('administration.index') }}">
        {{ __('Administration') }}
    </a>
@endcan
로그인 후 복사

이 접근 방식은 간단한 애플리케이션에는 효과적이지만 메뉴 수가 증가하면 복잡해지고 관리하기 어려워집니다.


솔루션

메뉴 빌더 시스템은 메뉴 로직을 재사용 가능한 클래스로 캡슐화하여 다음을 개선합니다.

  1. 유지관리성: 중앙 집중식 메뉴 정의.
  2. 확장성: 역할이나 권한에 따라 메뉴를 동적으로 생성합니다.
  3. 재사용성: 여러 뷰에서 메뉴를 공유합니다.

저의 작업을 후원하여 개발자 커뮤니티에 힘을 실어주겠다는 제 사명을 지지해 주세요. 여러분의 기여는 귀중한 도구, 통찰력, 리소스를 구축하고 공유하는 데 도움이 됩니다. 여기에서 자세히 알아보세요.


단계적 구현

1. viewAdmin에 대한 게이트 정의

관리 메뉴에 대한 액세스를 제어하려면 AuthServiceProvider에서 viewAdmin 게이트를 정의하세요.

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. MenuItem 클래스 생성

MenuItem 클래스는 라벨, URL, 아이콘, 가시성 등 메뉴 항목의 모든 속성을 정의합니다.

<?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. 메뉴 빌더 만들기

메뉴 빌더는 메뉴를 동적으로 확인하고 구성합니다.

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();
    }
}
로그인 후 복사

도우미 기능을 사용하여 메뉴에 액세스:

<?php

use App\Actions\Builder\Menu;

if (! function_exists('menu')) {
    function menu(string $builder)
    {
        return Menu::make()->build($builder)->menus();
    }
}
로그인 후 복사

4. 관리메뉴

관리 클래스에서 관리 관련 메뉴 항목 정의:

<?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. 경로 정의

관리 페이지에 다음 경로 구성을 추가하세요.

<?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. 블레이드 템플릿에서의 사용법

탐색 메뉴(navigation-menu.blade.php):

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

관리 메뉴(administration/index.blade.php):

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




<hr>

<p><strong>출력</strong></p>

<p>여기서 얻을 수 있는 최종 출력은 다음과 같습니다.</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>저의 작업을 후원하여 개발자 커뮤니티에 힘을 실어주겠다는 제 사명을 지지해 주세요. 여러분의 기여는 귀중한 도구, 통찰력, 리소스를 구축하고 공유하는 데 도움이 됩니다. 여기에서 자세히 알아보세요.</p>
</blockquote>


<hr>

<h3>
  
  
  <strong>결론</strong>
</h3>

<p>이 <strong>메뉴 빌더 시스템</strong>은 다음을 통해 Laravel의 탐색 관리를 단순화합니다.</p>

<ol>
<li>더 나은 유지 관리를 위해 메뉴 정의를 중앙 집중화합니다.</li>
<li>역할이나 권한을 사용하여 메뉴 가시성을 동적으로 제어합니다.</li>
<li>뷰와 레이아웃 전반에 걸쳐 메뉴 로직을 재사용합니다.</li>
</ol>

<p>이 접근 방식을 채택하면 복잡한 애플리케이션에서도 내비게이션 시스템을 원활하게 확장할 수 있습니다. </p>

<p>데이터베이스에서 메뉴 세부정보를 로드하고 원하는 메뉴를 구성할 수 있습니다. 하지만 나에게는 이 정도면 충분하다. 데이터베이스 기반 메뉴 구성을 사용해야 하는 프로젝트가 없습니다.</p>

<p>코드는 여기에서 확인할 수 있습니다. </p>

<p>사용해보고 의견을 공유해 보세요! ?</p>


<hr>

<p>사진: LinedPhoto, Unsplash</p>


          

            
  

            
        
로그인 후 복사

위 내용은 Laravel에서 동적이며 유지 관리 가능한 메뉴 만들기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿