Laravel怎么进行路由分组

2023-06-15 laravel 路由 分组

这篇“Laravel怎么进行路由分组”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Laravel怎么进行路由分组”文章吧。

分组 1. Route::resource 和 Route::apiResource

让我们从房间里的大象开始:这可能是最常用的分组。如果您围绕一个模型有一组典型的 CRUD 操作,则应该将它们分组到 资源控制器

此类控制器包含 多达 7 种方法(但可能更少):

  • index()

  • create()

  • store()

  • show()

  • edit()

  • update()

  • destroy()

因此,如果您的路由集对应于这些方法,请不要使用:

Route::get('books', [BookController::class, 'index'])->name('books.index');
Route::get('books/create', [BookController::class, 'create'])->name('books.create');
Route::post('books', [BookController::class, 'store'])->name('books.store');
Route::get('books/{book}', [BookController::class, 'show'])->name('books.show');
Route::get('books/{book}/edit', [BookController::class, 'edit'])->name('books.edit');
Route::put('books/{book}', [BookController::class, 'update'])->name('books.update');
Route::delete('books/{book}', [BookController::class, 'destroy'])->name('books.destroy');

… 您可能只有一行:

Route::resource('books', BookController::class);

如果您使用 API 项目,则不需要用于创建 / 编辑的可视化表单,因此您可以使用

apiResource()
的涵盖 7 种方法中的 5 种不同语法:

Route::apiResource('books', BookController::class);

此外,我建议您考虑资源控制器,即使您有 2-4 个方法,而不是完整的 7 个。只是因为它保持标准命名约定 - 对于 URL、方法和路由名称。 例如,在这种情况下,您不需要手动提供名称:

Route::get('books/create', [BookController::class, 'create'])->name('books.create');
Route::post('books', [BookController::class, 'store'])->name('books.store');

// 相反,这里的名称“books.create”和“books.store”是自动分配的
Route::resource('books', BookController::class)->only(['create', 'store']);

分组 2.  嵌套子路由组

当然,一般的 路由分组 大家都知道。 但对于更复杂的项目,一级分组可能还不够。

实际示例:您希望授权路由与

auth
中间件进行分组,但在内部您需要分隔更多子组,例如管理员和简单用户。

Route::middleware('auth')->group(function() {

   Route::middleware('is_admin')->prefix('admin')->group(function() {
    Route::get(...) // administrator routes
   });

   Route::middleware('is_user')->prefix('user')->group(function() {
    Route::get(...) // user routes
   });
});

分组 3. 将重复的中间件分组

如果你有很多中间件,有一些在路由组中重复出现怎么办?

Route::prefix('students')->middleware(['auth', 'check.role', 'check.user.status', 'check.invoice.status', 'locale'])->group(function () {
   // ... 学生路由
});

Route::prefix('managers')->middleware(['auth', 'check.role', 'check.user.status', 'locale'])->group(function () {
   // ... 管理员路由
});

如您所见,有 5 个中间件,其中 4 个是重复的。因此,在

app/Http/Kernel.php
文件里,我们可以将这 4 个移动到单独的中间件组中:

protected $middlewareGroups = [
   // 此组是 Laravel 默认中间件组
   'web' => [
       AppHttpMiddlewareEncryptCookies::class,
       IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
       IlluminateSessionMiddlewareStartSession::class,
       IlluminateViewMiddlewareShareErrorsFromSession::class,
       AppHttpMiddlewareVerifyCsrfToken::class,
       IlluminateRoutingMiddlewareSubstituteBindings::class,
   ],

   // 此组是 Laravel 默认中间件组
   'api' => [
       // LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful::class,
       'throttle:api',
       IlluminateRoutingMiddlewareSubstituteBindings::class,
   ],

   // 这是我们新的中间件组
   'check_user' => [
       'auth',
       'check.role',
       'check.user.status',
       'locale'
   ],
];

所以将我们的中间件组命明为

check_user
,现在我们可以缩写路由:

Route::prefix('students')->middleware(['check_user', 'check.invoice.status'])->group(function () {
   // ... student routes
});

Route::prefix('managers')->middleware(['check_user'])->group(function () {
   // ... manager routes
});

分组 4. 同名控制器,不同命名空间

很常见的情况是,例如,为不同的用户角色设置了

HomeController
,例如
Admin/HomeController
User/HomeController
。 如果在路由中使用完整路径,它看起来像这样:

Route::prefix('admin')->middleware('is_admin')->group(function () {
   Route::get('home', [AppHttpControllersAdminHomeController::class, 'index']);
});

Route::prefix('user')->middleware('is_user')->group(function () {
   Route::get('home', [AppHttpControllersUserHomeController::class, 'index']);
});

每个控制器都是用了完整的路径这看上去很冗余,对吧? 这就是为什么许多开发人员更喜欢在路由列表中只包含

HomeController::class
并在顶部添加类似这样的内容:

use AppHttpControllersAdminHomeController;

但是这里的问题是我们有相同的控制器类名! 所以,这行不通:

use AppHttpControllersAdminHomeController;
use AppHttpControllersUserHomeController;

哪一个是「管理后台」的控制器?好吧,一种方法是更改名称并为其中之一分配别名:

use AppHttpControllersAdminHomeController as AdminHomeController;
use AppHttpControllersUserHomeController;

Route::prefix('admin')->middleware('is_admin')->group(function () {
   Route::get('home', [AdminHomeController::class, 'index']);
});

Route::prefix('user')->middleware('is_user')->group(function () {
   Route::get('home', [HomeController::class, 'index']);
});

但是,就个人而言,更改顶部类的名称让我很困惑,我喜欢另一种方法:为控制器的子文件夹添加一个命名空间():

Route::prefix('admin')->namespace('AppHttpControllersAdmin')->middleware('is_admin')->group(function () {
   Route::get('home', [HomeController::class, 'index']);
   // ... Admin 命名空间中的其他控制器
});

Route::prefix('user')->namespace('AppHttpControllersUser')->middleware('is_user')->group(function () {
   Route::get('home', [HomeController::class, 'index']);
   // ... 来自用户命名空间的其他控制器
});

分组 5. 分离路由文件

如果你觉得

routes/web.php
routes/api.php
太大了,可以把一些路由放到一个单独的文件中,你可以为它任意命名,例如
routes/admin.php

要加载该文件,有两种方法:我称之为 「Laravel 方式」 和 「PHP 方式」 。

如果你想遵循 Laravel 构建其默认路由文件的结构,查看 app/Providers/RouteServiceProvider.php

public function boot()
{
   $this->configureRateLimiting();

   $this->routes(function () {
       Route::middleware('api')
           ->prefix('api')
           ->group(base_path('routes/api.php'));

       Route::middleware('web')
           ->group(base_path('routes/web.php'));
   });
}

routes/api.php
routes/web.php
都在这里,但设置略有不同。因此,你只需要在此处添加 admin 文件:

$this->routes(function () {
   Route::middleware('api')
       ->prefix('api')
       ->group(base_path('routes/api.php'));

   Route::middleware('web')
       ->group(base_path('routes/web.php'));

   Route::middleware('is_admin')
       ->group(base_path('routes/admin.php'));
});

如果你不想深入研究 服务提供者,还有一种更简单的方法 - 只需 include/require 您的路由文件到另一个文件中,就像你在 Laravel 框架之外的任何 PHP 文件。

事实上,这是由 Taylor Otwell 完成的,只需将

routes/auth.php
文件直接放入 Laravel Breeze 路由:

routes/web.php:

Route::get('/', function () {
   return view('welcome');
});

Route::get('/dashboard', function () {
   return view('dashboard');
})->middleware(['auth'])->name('dashboard');

require __DIR__.'/auth.php';

分组 6. Laravel 9 中的新功能: Route::controller ()

如果你的 Controller 中有一些方法,但它们不遵循标准的 Resource 结构,您仍然可以对它们进行分组,而无需为每个方法重复 Controller 名称。

取而代之的是:

Route::get('profile', [ProfileController::class, 'getProfile']);
Route::put('profile', [ProfileController::class, 'updateProfile']);
Route::delete('profile', [ProfileController::class, 'deleteProfile']);

登录后复制

您可以这样做:

Route::controller(ProfileController::class)->group(function() {
   Route::get('profile', 'getProfile');
   Route::put('profile', 'updateProfile');
   Route::delete('profile', 'deleteProfile');
});

相关文章