laniakea / middleware-priority
更灵活地管理Laravel的HTTP中间件优先级。
Requires
- php: ^8.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.21.1
- orchestra/testbench: ^9.0.0
- pestphp/pest: ^2.15
This package is auto-updated.
Last update: 2024-08-29 20:55:30 UTC
README
此包为Laravel 11+应用提供了更灵活地管理HTTP中间件优先级的方法。
请注意,此包仅与全新的Laravel 11+应用兼容(或已升级到Laravel 11+且具有新目录结构和/或应用引导的应用)。
您可以将中间件简单地追加/前置到优先级列表,或者进行更复杂的事情,例如:
- 将中间件添加到特定中间件之前或之后;
- 交换两个中间件的位置;
- 从优先级列表中删除中间件。
此包提供了默认的Laravel优先级列表(最新更新:Laravel 11.0.7;请查看DefaultMiddlewarePriority
类),因此您可以用它作为自定义优先级列表的基础。
安装
您可以通过composer安装此包
composer require laniakea/middleware-priority
用法
此包旨在与Laravel的Application::configure()
构建器(位于bootstrap/app.php
文件中)一起使用。
<?php use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { // Manage priority list here. }) ->withExceptions(function (Exceptions $exceptions) { // })->create();
创建优先级管理器
在withMiddleware
回调内部创建Laniakea\MiddlewarePriority\MiddlewarePriorityManager
的新实例,以开始使用中间件优先级管理器。请注意,默认情况下优先级列表将为空(除非您在创建管理器实例之前修改了它)。
<?php use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; use Laniakea\MiddlewarePriority\MiddlewarePriorityManager; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { $manager = new MiddlewarePriorityManager($middleware); // Manage priority list here. }) ->withExceptions(function (Exceptions $exceptions) { // })->create();
使用Laravel的默认优先级
如果您想使用Laravel的默认优先级列表,可以使用静态方法MiddlewarePriorityManager::withDefaults
创建具有默认优先级列表的管理器实例。
withDefaults()
方法的第二个参数接受用户定义的默认中间件优先级列表(如果为null
或未传递,则使用默认的Laravel优先级列表)。
<?php use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; use Laniakea\MiddlewarePriority\MiddlewarePriorityManager; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { $manager = MiddlewarePriorityManager::withDefaults($middleware); // create manager with default Laravel's priority list // $manager = MiddlewarePriorityManager::withDefaults($middleware, ['App\\SomeMiddleware']); // create manager with custom priority list // Manage priority list here. }) ->withExceptions(function (Exceptions $exceptions) { // })->create();
追加中间件
以下假设在
withMiddleware
回调内部创建了并使用了管理器。
使用append(string|array $middleware)
方法将中间件追加到优先级列表。
<?php use App\Http\Middleware\FirstMiddleware; use App\Http\Middleware\SecondMiddleware; use App\Http\Middleware\ThirdMiddleware; $manager = MiddlewarePriorityManager::withDefaults($middleware); $manager->append(FirstMiddleware::class); // priority list: [..., FirstMiddleware::class] $manager->append([SecondMiddleware::class, ThirdMiddleware::class]); // priority list: [..., FirstMiddleware::class, SecondMiddleware::class, ThirdMiddleware::class]
前置中间件
使用prepend(string|array $middleware)
方法将中间件前置到优先级列表。
<?php use App\Http\Middleware\FirstMiddleware; use App\Http\Middleware\SecondMiddleware; use App\Http\Middleware\ThirdMiddleware; $manager = MiddlewarePriorityManager::withDefaults($middleware); $manager->prepend(FirstMiddleware::class); // priority list: [FirstMiddleware::class, ...] $manager->prepend([SecondMiddleware::class, ThirdMiddleware::class]); // priority list: [SecondMiddleware::class, ThirdMiddleware::class, FirstMiddleware::class, ...]
在特定中间件之前添加中间件
使用before(string $middleware, string|array $newMiddleware)
方法在特定中间件之前添加中间件。
<?php use App\Http\Middleware\FirstMiddleware; use Illuminate\Routing\Middleware\SubstituteBindings; $manager = MiddlewarePriorityManager::withDefaults($middleware); $manager->before(SubstituteBindings::class, FirstMiddleware::class); // priority list: [..., FirstMiddleware::class, SubstituteBindings::class, ...]
您也可以将中间件数组作为第二个参数使用。在这种情况下,新中间件将按照数组的顺序添加。
<?php use App\Http\Middleware\FirstMiddleware; use App\Http\Middleware\SecondMiddleware; use Illuminate\Routing\Middleware\SubstituteBindings; $manager = MiddlewarePriorityManager::withDefaults($middleware); $manager->before(SubstituteBindings::class, [FirstMiddleware::class, SecondMiddleware::class]); // priority list: [..., FirstMiddleware::class, SecondMiddleware::class, SubstituteBindings::class, ...]
在特定中间件之后添加中间件
使用after(string $middleware, string|array $newMiddleware)
方法在特定中间件之后添加中间件。
<?php use App\Http\Middleware\FirstMiddleware; use Illuminate\Routing\Middleware\SubstituteBindings; $manager = MiddlewarePriorityManager::withDefaults($middleware); $manager->after(SubstituteBindings::class, FirstMiddleware::class); // priority list: [..., SubstituteBindings::class, FirstMiddleware::class, ...]
您也可以将中间件数组作为第二个参数使用。在这种情况下,新中间件将按照数组的顺序添加。
<?php use App\Http\Middleware\FirstMiddleware; use App\Http\Middleware\SecondMiddleware; use Illuminate\Routing\Middleware\SubstituteBindings; $manager = MiddlewarePriorityManager::withDefaults($middleware); $manager->after(SubstituteBindings::class, [FirstMiddleware::class, SecondMiddleware::class]); // priority list: [..., SubstituteBindings::class, FirstMiddleware::class, SecondMiddleware::class, ...]
交换中间件位置
使用swap(string $what, string $with)
方法交换两个中间件的位置。
<?php use App\Http\Middleware\FirstMiddleware; use App\Http\Middleware\SecondMiddleware; $manager = MiddlewarePriorityManager::withDefaults($middleware, [FirstMiddleware::class, SecondMiddleware::class]); // priority list: [FirstMiddleware::class, SecondMiddleware::class] $manager->swap(FirstMiddleware::class, SecondMiddleware::class); // priority list: [SecondMiddleware::class, FirstMiddleware::class]
删除中间件
使用remove(string|array $what)
方法从优先级列表中删除中间件。
<?php use App\Http\Middleware\FirstMiddleware; use App\Http\Middleware\SecondMiddleware; $manager = MiddlewarePriorityManager::withDefaults($middleware, [FirstMiddleware::class, SecondMiddleware::class]); // priority list: [FirstMiddleware::class, SecondMiddleware::class] $manager->remove(FirstMiddleware::class); // priority list: [SecondMiddleware::class]
您也可以使用中间件数组。所有列出的中间件都将从优先级列表中删除。
<?php use App\Http\Middleware\FirstMiddleware; use App\Http\Middleware\SecondMiddleware; use App\Http\Middleware\ThirdMiddleware; use Illuminate\Routing\Middleware\SubstituteBindings; $manager = MiddlewarePriorityManager::withDefaults($middleware); $manager->remove([SecondMiddleware::class, ThirdMiddleware::class]); // priority list: [FirstMiddleware::class]
在从优先级列表中删除中间件后,其位置将由分组中间件中的注册顺序决定。请参见以下示例。
<?php use App\Http\Middleware\FirstMiddleware; use App\Http\Middleware\SecondMiddleware; use App\Http\Middleware\ThirdMiddleware; use App\Http\Middleware\FourthMiddleware; use App\Http\Middleware\FifthMiddleware; $middleware->appendToGroup('web', [ FirstMiddleware::class, SecondMiddleware::class, ThirdMiddleware::class, FourthMiddleware::class, FifthMiddleware::class, ]); $manager = MiddlewarePriorityManager::withDefaults($middleware); $manager->prepend(FirstMiddleware::class); // priority list: [FirstMiddleware::class, ...] $manager->prepend(SecondMiddleware::class); // priority list: [SecondMiddleware::class, FirstMiddleware::class, ...] $manager->before(FirstMiddleware::class, FourthMiddleware::class); // priority list: [SecondMiddleware::class, FourthMiddleware::class, FirstMiddleware::class, ...] $manager->after(FourthMiddleware::class, ThirdMiddleware::class); // priority list: [SecondMiddleware::class, FourthMiddleware::class, ThirdMiddleware::class, FirstMiddleware::class, ...] $manager->remove(FourthMiddleware::class); // priority list: [SecondMiddleware::class, ThirdMiddleware::class, FirstMiddleware::class, ...] /* * Middleware will be called in following order: * * 1. FourthMiddleware::class (was removed from the priority list); * 2. FifthMiddleware::class (was not added to the priority list in first place); * 3. SecondMiddleware::class (by priority list order); * 4. ThirdMiddleware::class (by priority list order); * 5. FirstMiddleware::class (by priority list order). */
获取当前优先级列表
如果您需要检索当前优先级列表,可以使用getPriority()
方法。
<?php $manager = MiddlewarePriorityManager::withDefaults($middleware); // Manage priority list here. $currentPriority = $manager->getPriority();
完整示例
<?php use App\Http\Middleware\FirstMiddleware; use App\Http\Middleware\SecondMiddleware; use App\Http\Middleware\ThirdMiddleware; use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; use Laniakea\MiddlewarePriority\MiddlewarePriorityManager; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { // First you need to register middleware to some group. $middleware->appendToGroup('web', [ FirstMiddleware::class, SecondMiddleware::class, ThirdMiddleware::class, ]); // Now you can manage priority list. $manager = MiddlewarePriorityManager::withDefaults($middleware); $manager->prepend(FirstMiddleware::class); $manager->before(\Illuminate\Routing\Middleware\SubstituteBindings::class, SecondMiddleware::class); $manager->after(\Illuminate\Auth\Middleware\Authorize::class, ThirdMiddleware::class); if (thirdMiddlewareNotRequired()) { $manager->remove(ThirdMiddleware::class); } elseif (thirdMiddlewareShouldBeFirst()) { $manager->remove(ThirdMiddleware::class) ->prepend(ThirdMiddleware::class); } elseif (thirdAndFirstMiddlewareShoudBeSwapped()) { $manager->swap(FirstMiddleware::class, ThirdMiddleware::class); } \Log::debug('[app.php@withMiddleware] Priority list generated.', ['priority' => $manager->getPriority()]); }) ->withExceptions(function (Exceptions $exceptions) { // })->create();
测试
composer test
变更日志
请参见变更日志以获取有关最近更改的更多信息。
致谢
许可证
MIT许可证(MIT)。请参见许可证文件以获取更多信息。