大型 Laravel 项目中如何组织你的路由

原文连接: https://learnku.com/laravel/t...

讨论请前往专业的 Laravel 开发者论坛: https://learnku.com/Laravel

想象一下一个拥有 100 多个路由的 Laravel 项目,其中包括访客,用户,管理员等分离的模块。你真的要将全部内容写在在一个文件中吗?那么如何将它们分组,而且为 URL 添加前缀呢?看看有哪些办法。php


1. 分离 WEB 和 API 路由

这个简单,由于 Laravel 已经帮你作了。有以下两个文件:前端

所以,若是你的项目同时具备前端页面和 API (使用场景愈来愈广),请把 API 的路由放在 api.php 里。laravel

例如,若是你有 /users 页面,又有 /api/users/ 端点,把他们分别写在本身属于本身路由文件里,以避免在同一文件中出现同一相同名称而产生混淆。git

但我最近仍是从 官方 Laravel 项目中看到了反例。在 Laravel Horizon 中,Taylor 只有 API 路由,但他没有分开写,仍是写在了 routes/web.php :github

另外一个例子证实 Laravel 仍是很是的我的化,甚至 Taylor 本身也没有 100% 按照标准来。web


2. 把 routes/web.php 文件分组结构化

下面例子也是来自 Laravel 官方文档 的示例:api

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // 使用 first 和 second 中间件
    });

    Route::get('user/profile', function () {
        // 使用 first 和 second 中间件
    });
});

最基本的用法是将不一样的路由分组包含在不一样的中间件里面。例如,你但愿一个组默认受 auth 中间件限制,另外一组受单独的 admin 自定义中间件限制等。数组

这样,你还可使用 名称前缀 等路由分组方法。一样,官方文档中给出了示例:app

Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // 匹配 URL 「/admin/users」
    });
});

Route::name('admin.')->group(function () {
    Route::get('users', function () {
        // 路由名为 「admin.users」...
    })->name('users');
});

另外,若是您要将全部中间件 + 名称 + 前缀添加到一个组中,则将它们放入数组中更容易理解:ide

// 而不是这样作: 
Route::name('admin.')->prefix('admin')->middleware('admin')->group(function () {
    // ...
});

// 可使用数组
Route::group([
    'name' => 'admin.', 
    'prefix' => 'admin', 
    'middleware' => 'auth'
], function () {
    // ...
});

咱们将其结合为一个拥有三个路由分组的真实示例:

  • 带有 / front / XXXXX URL 且没有中间件的「访客」组
  • 带有 / user / XXXXX URL 和 auth 中间件的「用户」组
  • 带有 / admin / XXXXX URL 和自定义 admin 中间件的「管理员」组

如下是将全部内容分组到 routes / web.php 文件中的一种方法:

Route::group([
    'name' => 'admin.',
    'prefix' => 'admin',
    'middleware' => 'admin'
], function () {

    // URL连接:/admin/users
    // 路由名称:admin.users
    Route::get('users', function () {
        return 'Admin: user list';
    })->name('users');

});

Route::group([
    'name' => 'user.',
    'prefix' => 'user',
    'middleware' => 'auth'
], function () {

    // URL连接:/user/profile
    // 路由名称:user.profile
    Route::get('profile', function () {
        return 'User profile';
    })->name('profile');

});

Route::group([
    'name' => 'front.',
    'prefix' => 'front'
], function () {

    // 这里没有中间件
    // URL连接:/front/about-us
    // 路由名称:front.about
    Route::get('about-us', function () {
        return 'About us page';
    })->name('about');

});

3. 使用命名空间对控制器进行分组

在上面的例子中,咱们没有使用控制器,只是返回了静态文本做为示例。 让咱们添加一个控制器,来点小花样 — 咱们会将它们构造到各自不一样的命名空间的文件夹中,以下所示:

而后咱们能够在路由文件中使用它们:

Route::group([
    'name' => 'front.',
    'prefix' => 'front'
], function () {
    Route::get('about-us', 'Front.boutController@index')->name('about');
});

可是若是在这个组中咱们有不少控制器呢? 咱们应该一直添加Front.omeController 吗? 固然不是。您也能够将命名空间做为参数之一。

Route::group([
    'name' => 'front.',
    'prefix' => 'front',
    'namespace' => 'Front',
], function () {
    Route::get('about-us', 'AboutController@index')->name('about');
    Route::get('contact', 'ContactController@index')->name('contact');
});

4. 组嵌套组

上面的状况,分为了3个组,实际上这是被简化的, 实际项目的结构稍有不一样 – 是  个组:frontauth 。 而后在 auth 中,有两个子组:user 和 admin 。为此, 咱们能够在 routes/web.php中建立子组,并分配不一样的中间件/前缀等。

Route::group([
    'middleware' => 'auth',
], function() {

    Route::group([
        'name' => 'admin.',
        'prefix' => 'admin',
        'middleware' => 'admin'
    ], function () {

        // URL: /admin/users
        // Route name: admin.users
        Route::get('users', 'UserController@index')->name('users');

    });

    Route::group([
        'name' => 'user.',
        'prefix' => 'user',
    ], function () {

        // URL: /user/profile
        // Route name: user.profile
        Route::get('profile', 'ProfileController@index')->name('profile');

    });

});

咱们甚至能够多层嵌套,这是开源项目的一个示例。 Akaunting:

Route::group(['middleware' => 'language'], function () {
    Route::group(['middleware' => 'auth'], function () {
        Route::group(['prefix' => 'uploads'], function () {
            Route::get('{id}', 'Common.ploads@get');
            Route::get('{id}/show', 'Common.ploads@show');
            Route::get('{id}/download', 'Common.ploads@download');
        });

        Route::group(['middleware' => 'permission:read-admin-panel'], function () {
            Route::group(['prefix' => 'wizard'], function () {
                Route::get('/', 'Wizard.ompanies@edit')->name('wizard.index');

        // ...

另外一个例子来自另外一个流行的Laravel CRM,名为Monica:

Route::middleware(['auth', 'verified', 'mfa'])->group(function () {
    Route::name('dashboard.')->group(function () {
        Route::get('/dashboard', 'DashboardController@index')->name('index');
        Route::get('/dashboard/calls', 'DashboardController@calls');
        Route::get('/dashboard/notes', 'DashboardController@notes');
        Route::get('/dashboard/debts', 'DashboardController@debts');
        Route::get('/dashboard/tasks', 'DashboardController@tasks');
        Route::post('/dashboard/setTab', 'DashboardController@setTab');
    });

5. RouteServiceProvider 中的全局设置

有一个服务于全部路由设置的文件 – app/Providers/RouteServiceProvider.php. 它具备绑定两个路由文件 – web 和 API 的 map() 方法:

public function map()
    {
        $this->mapApiRoutes();
        $this->mapWebRoutes();
    }

    protected function mapWebRoutes()
    {
        Route::middleware('web')
             ->namespace($this->namespace)
             ->group(base_path('routes/web.php'));
    }

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

您是否注意到方法中说起的 middlewarenamespace 和 prefix ? 这是您能够为整个文件设置全局配置的地方,所以没必要为文件中的每一个路由组重复这些设置。

它主要用于 API 路由,由于它们的设置一般是相同的,以下所示:

protected function mapApiRoutes()
{
    Route::group([
        'middleware' => ['api'],
        'namespace' => $this->namespace,
        'prefix' => 'api/v1',
    ], function ($router) {
        require base_path('routes/api.php');
    });
}

上述方法将在全部 API URLs 的开头加上 api/v1/ 前缀。


6. 分组成更多文件 – 这值得吗?

若是您有大量的路由,而且但愿将它们分组到单独的文件中,那么您可使用上一节中提到的相同文件 – app/Providers/RouteServiceProvider.php。若是您仔细查看它的 map() 方法,您将在末尾看到注释位置:

public function map()
{
    $this->mapApiRoutes();

    $this->mapWebRoutes();

    //
}

若是愿意,您能够将其解释为添加更多文件的“邀请”。所以,您能够在此文件内建立另外一个方法,例如 mapAdminRoutes(),而后将其添加到 map() 方法, 您的文件将被自动注册并加载。

可是,就我我的而言,我看不出这种方法有什么优点,并且我也没有常常看到这种作法。它会带来更多的路由分离,但有时您会迷失在那些文件中,不肯定在哪里查找特定的路由。


7. 使用 Artisan route:list 命令查找特定路由

说到更大的路由并迷失在那里,咱们有一个 Artisan 命令能够帮助定位某个路由。

您可能知道 php artisan route:list 将展现项目中的全部路由

但您知道还有更多的过滤功能来找到您想要的东西吗? 只需添加带参数的 –method, 或 –name, 或 –path 。

经过 method 过滤 – GET, POST 等:

按名称或 URL 部分过滤:


这就是我所能告诉的关于在大型项目中分组路由的所有内容。你还有其余例子吗?请在评论中分享。

原文连接: https://learnku.com/laravel/t...

讨论请前往专业的 Laravel 开发者论坛: https://learnku.com/Laravel
相关文章
相关标签/搜索