>首页> IT >

Laravel如何进行路由分组?6 种路由组织技术分享

时间:2022-10-11 20:06:38       来源:转载

Laravel 路由是开发人员从一开始就学习的特性。但是随着他们项目的增长,管理不断增长的路由文件变得越来越困难,经常需要滚动查找正确的 Route::get()语句。幸运的是,有一些技术可以使路由文件更短、更易读,让我们来看看以不同的方式对路由及其设置进行分组。

我们不会只谈论一般简单的 Route::group(),那是初学者级别。 让我们再深入一点。


(资料图片仅供参考)


分组 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" => [        \App\Http\Middleware\EncryptCookies::class,        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,        \Illuminate\Session\Middleware\StartSession::class,        \Illuminate\View\Middleware\ShareErrorsFromSession::class,        \App\Http\Middleware\VerifyCsrfToken::class,        \Illuminate\Routing\Middleware\SubstituteBindings::class,    ],    // 此组是 Laravel 默认中间件组    "api" => [        // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,        "throttle:api",        \Illuminate\Routing\Middleware\SubstituteBindings::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/HomeControllerUser/HomeController。 如果在路由中使用完整路径,它看起来像这样:

Route::prefix("admin")->middleware("is_admin")->group(function () {    Route::get("home", [\App\Http\Controllers\Admin\HomeController::class, "index"]);});Route::prefix("user")->middleware("is_user")->group(function () {    Route::get("home", [\App\Http\Controllers\User\HomeController::class, "index"]);});
登录后复制

每个控制器都是用了完整的路径这看上去很冗余,对吧? 这就是为什么许多开发人员更喜欢在路由列表中只包含 HomeController::class并在顶部添加类似这样的内容:

use App\Http\Controllers\Admin\HomeController;
登录后复制

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

use App\Http\Controllers\Admin\HomeController;use App\Http\Controllers\User\HomeController;
登录后复制

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

use App\Http\Controllers\Admin\HomeController as AdminHomeController;use App\Http\Controllers\User\HomeController;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("App\Http\Controllers\Admin")->middleware("is_admin")->group(function () {    Route::get("home", [HomeController::class, "index"]);    // ... Admin 命名空间中的其他控制器});Route::prefix("user")->namespace("App\Http\Controllers\User")->middleware("is_user")->group(function () {    Route::get("home", [HomeController::class, "index"]);    // ... 来自用户命名空间的其他控制器});
登录后复制

分组 5. 分离路由文件

如果你觉得 routes/web.phproutes/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.phproutes/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");});
登录后复制

此功能在 Laravel 9 和 Laravel 8 的最新小版本中可用。


就是这样,这些分组技术有望帮助你组织和维护的路由,无论你的项目发展到多大。

【相关推荐:laravel视频教程】

以上就是Laravel如何进行路由分组?6 种路由组织技术分享的详细内容,更多请关注php中文网其它相关文章!

关键词: 命名空间 开发人员