ixianming/laravel-route-service-provider

Laravel的路由管理扩展,支持Laravel 5.3及以上版本,包括Laravel 6、Laravel 7、Laravel 8和Laravel 9。基于Laravel的路由服务提供者,提供更方便、更强大的路由管理服务。请阅读README.MD获取更多详细信息。

1.4.0 2022-06-13 06:09 UTC

This package is auto-updated.

Last update: 2024-09-13 11:45:20 UTC


README

该文档详细说明了扩展包的功能,信息丰富,但并不复杂。

通常,默认配置可以满足大部分需求,因此您在安装扩展包后无需设置。您只需熟悉默认规则即可使用它。

[目录]

关于扩展包

扩展包的ServiceProvider继承了Laravel的App\Providers\RouteServiceProvider。因此,在安装扩展包后,App\Providers\RouteServiceProvider中boot()方法定义的路由模型显式绑定、过滤器、自定义解析逻辑等仍然可用。

请注意,对App\Providers\RouteServiceProvidermap()mapApiRoutes()mapWebRoutes()的更改无效,因为扩展包覆盖了map()方法,而map()方法不再引用mapApiRoutes()mapWebRoutes()

特性

  • 您可以设置允许匹配路由文件的中间件组。

    扩展包使用默认或自定义规则将这些路由文件分配给这些中间件组并执行加载。

  • 您可以为同一中间件组创建多个路由文件,并将这些路由文件放置在routes目录中的任何位置。

    路由文件的名称可以使用默认规则,或者开发者可以自定义路由文件与中间件组之间的匹配规则。

  • 您可以将异常信息的响应格式设置为全局默认Json输出,或者可以独立设置允许匹配路由文件的每个中间件组的异常信息响应格式为Json(独立设置优先级高于全局默认设置)。

  • 检查所有路由中的重复URL(带域名限制的完整URL)。

  • 您可以设置是否允许注册基于闭包的路由。

  • 您可以设置命名路由的名称是否可以重复。

  • 您可以设置是否允许控制器重用。

  • 您可以自定义允许匹配路由文件的每个中间件组使用的根命名空间namespace

  • 您可以自定义允许匹配路由文件的每个中间件组使用的子域名domain

  • 您可以自定义允许匹配路由文件的每个中间件组使用的路由前缀prefix

  • 您可以自定义允许匹配路由文件的每个中间件组使用的路由名称前缀name

  • 您可以自定义允许匹配路由文件的每个中间件组使用的路由参数正则表达式约束where

安装

安装条件

  • PHP >= 7.0

  • Laravel >= 5.3

    Laravel 6 / Laravel 7 / Laravel 8 / Laravel 9可以安装和使用!

安装

composer require ixianming/laravel-route-service-provider

使用包自动发现

  • Laravel 5.5+使用包自动发现,因此不需要手动添加ServiceProvider

  • 您不需要注释Laravel的路由服务提供者(除非扩展包抛出提示)。

不使用包自动发现

如果Laravel版本低于5.5或未使用包自动发现功能

  • config/app.php文件中的providers数组中注释掉Laravel的路由服务提供者 App\Providers\RouteServiceProvider::class

  • 将扩展包的服务提供者 Ixianming\Routing\RouteServiceProvider::class 添加到config/app.php文件中的providers数组,位于原始路由服务提供者 App\Providers\RouteServiceProvider::class 下方。

'providers' => [
    /*
     * Laravel Framework Service Providers...
     */

    /*
     * Package Service Providers...
     */

    /*
     * Application Service Providers...
     */

    // App\Providers\RouteServiceProvider::class,
    Ixianming\Routing\RouteServiceProvider::class,

 ]

手动添加函数以处理异常信息的输出格式

App\Exceptions\Handler类的render方法中的return之前添加代码

if (method_exists(\Ixianming\Routing\ExceptionResponse::class, 'wantsJson')) {
    list($request, $exception) = \Ixianming\Routing\ExceptionResponse::wantsJson($request, $exception);
}

修改后,render方法应如下所示

public function render($request, Exception $exception)
{
    // Your code ...

    // Your code must precede this function.
    if (method_exists(\Ixianming\Routing\ExceptionResponse::class, 'wantsJson')) {
        list($request, $exception) = \Ixianming\Routing\ExceptionResponse::wantsJson($request, $exception);
    }
    // There should be no code between the function and `return`.
    return parent::render($request, $exception);
}

卸载注意事项

  • 卸载扩展包后,请记住删除添加到App\Exceptions\Handler类的render方法中处理异常响应输出格式的代码。

  • 卸载扩展包后,请记住删除在App\Providers\RouteServiceProvider中添加的扩展包使用的属性和方法代码。

  • 卸载扩展包后,请记住从config/app.php文件中的providers数组中删除Ixianming\Routing\RouteServiceProvider::class,并取消注释App\Providers\RouteServiceProvider::class

使用

设置允许匹配路由文件的中间件组

扩展包默认的webapi中间件组可以匹配路由文件。

要添加允许匹配路由文件的中间件组,请向app/Providers/RouteServiceProvider.php中添加$allowMatchRouteMiddlewareGroups属性

protected $allowMatchRouteMiddlewareGroups = ['middlewareGroup_1', 'middlewareGroup_2'];
  • $allowMatchRouteMiddlewareGroups属性值为一个一维数组。数组的值是允许匹配路由文件的中间件组名称。

  • $allowMatchRouteMiddlewareGroups属性的值将合并到默认值,因此您只需在$allowMatchRouteMiddlewareGroups属性中定义允许匹配路由文件的新中间件组。

  • $allowMatchRouteMiddlewareGroups属性的值类型错误时,将使用默认值。

设置全局默认异常响应格式是否为Json

在使用此功能之前,请手动在App\Exceptions\Handler类的render方法中添加处理异常信息输出格式的函数,否则此功能无效。

要将全局默认异常信息响应格式设置为Json格式,请向app/Providers/RouteServiceProvider.php中添加$defaultExceptionJsonResponse属性并将其值设置为true

protected $defaultExceptionJsonResponse = true;
  • $defaultExceptionJsonResponse属性的值必须是一个布尔值(true 或 false)

  • $defaultExceptionJsonResponse属性的默认值是false

  • $defaultExceptionJsonResponse属性的值类型错误时,将使用默认值。

  • $defaultExceptionJsonResponse属性的值为true时,应用程序抛出的异常信息的响应格式为Json,当访问未知路由或未自定义异常信息响应格式的中间件组下的路由时。

  • $defaultExceptionJsonResponse属性不存在或值为null或值为false时,当访问未知路由或未自定义异常信息响应格式的中间件组下的路由时,应用程序抛出的异常信息的响应格式由请求头中的Accept参数确定。

  • 当访问具有自定义异常信息响应格式的中间件组下的路由时,无论如何设置 $defaultExceptionJsonResponse 属性的值,应用程序抛出的异常信息响应格式都由中间件组的自定义设置决定。(详情请见以下自定义规则)

设置是否允许注册基于闭包的路由

默认情况下,扩展包允许注册和使用基于闭包的路由。

建议禁止注册和使用基于闭包的路由。

为什么禁止注册和使用基于闭包的路由

  • 当应用程序发布时,Laravel通常会被优化,其中路由缓存是优化项之一。如果Laravel版本低于8.0,路由缓存不适用于基于闭包的路由。如果在Laravel版本低于8.0时使用基于闭包的路由,生成缓存时将报错!为了防止发布代码时路由缓存不可用,最佳解决方案是始终禁用闭包路由。

  • 在团队开发过程中,此配置可以强制限制开发者注册路由的方式,从而降低出错的风险。

要禁止注册和使用基于闭包的路由,请将 $closureRoute 属性添加到 app/Providers/RouteServiceProvider.php 并将其值设置为 false

protected $closureRoute = false;
  • $closureRoute 属性的值必须是 布尔值(truefalse

  • $closureRoute 属性的 默认值是 true

  • $closureRoute 属性的值类型错误时,将使用默认值。

  • $closureRoute 的值为 true 时,表示允许注册使用基于闭包的路由。

  • $closureRoute 的值为 false 时,表示禁止注册和使用基于闭包的路由。

设置命名路由的名称是否允许重复

命名路由的名称默认是唯一的。

注意:命名路由的名称不应以 .(英文句点)结尾。在Laravel中,以 . 结尾将被视为路由名称前缀,而不是完整名称。

为什么命名路由的名称需要唯一

  • 在某些场景下,命名路由用于控制权限或生成URL时,具有相同名称的命名路由可能会导致业务混淆。

  • 在某些场景下,需要确保路由名称唯一时,开发者在没有进行双重检查的情况下定义路由时可能甚至都没有意识到路由名称重复。

  • 如果允许命名路由的名称重复,那么使用 route() 方法生成的命名路由URL可能不是您想要的URL。

要允许命名路由有重复的名称,请将 $uniqueRouteName 属性添加到 app/Providers/RouteServiceProvider.php 并将其值设置为 false

protected $uniqueRouteName = false;
  • $uniqueRouteName 属性的值必须是 布尔值(truefalse

  • $uniqueRouteName 属性的 默认值是 true

  • $uniqueRouteName 属性的值类型错误时,将使用默认值。

  • $uniqueRouteName 属性的值为 true 时,表示命名路由的名称必须是唯一的。

  • $uniqueRouteName 属性的值为 false 时,表示允许命名路由的名称重复。

禁止相同名称的命名路由后,如果所有路由中存在相同名称的命名路由,将抛出错误信息。扩展包还会指出相同名称的命名路由所在的文件路径和行号,以及所属的中间件组,以便快速定位问题。

设置控制器是否可以被复用

默认情况下,控制器可以被重用。

为什么禁止控制器重用

  • 通常,控制器方法对应于业务逻辑。使用相同的控制器处理多个路由意味着该服务可以通过多个URL访问,这不利于URL的管理和维护,并且可能容易导致某些基于URL的应用程序在权限管理中发生泄漏。

  • 如果允许控制器重用。那么使用action()方法生成的控制器URL可能不是您想要的。

如果您需要防止控制器重用,请将$allowReuseAction属性添加到app/Providers/RouteServiceProvider.php中,并将其值设置为false

protected $allowReuseAction = false;
  • $allowReuseAction属性值必须是布尔值(truefalse

  • $allowReuseAction属性默认值为true

  • $allowReuseAction属性的值类型不正确时,将使用默认值。

  • $allowReuseAction属性的值为true时,允许控制器重用。

  • $allowReuseAction属性的值为false时,表示禁止控制器重用。

在禁止控制器重用后,将检查所有路由中的控制器是否被重用。如果被重用,将抛出错误消息。扩展包还将指示重用控制器的路由文件路径和行,以及它所属的中间件组,以便快速定位问题。

检查重复定义的URL

此功能是强制性的,不提供开关选项。

在Laravel中,如果您定义相同的URL,则后面的路由将覆盖现有的路由。重复定义不是我们期望的,因为它会使路由变得混乱,难以维护和管理。

安装扩展包后,扩展包将检查所有路由中的重复URL。如果存在,将抛出异常消息。扩展包还将指示重复URL所在的路由文件路径和行,以及它所属的中间件组,以便快速定位问题。

URL指受域名限制的完整URL。

默认规则

默认路由文件匹配规则

安装扩展包后,将对每个允许匹配路由文件的中间件组进行相应的路由文件自动匹配。这些路由文件可以放置在routes目录的任何位置。

默认匹配规则

  • 命名为{middlewareGroupName}.php

  • {middlewareGroupName}_开头。

  • _{middlewareGroupName}.php结尾。

符合上述规则的路由文件将被分配到相应名称的中间件组。

注意:在默认规则中,路径或文件名不区分大小写。

注意:不允许在routes目录中加载同一路由文件到多个中间件组。

注意:当在routes目录中重复加载同一路由文件超过3次时,扩展包将抛出异常。开发者应检查路由文件是否重复引用。如果自定义了路由匹配规则,也应检查匹配规则的正确性。

例如

routes
   |-- web.php
   |-- api.php
   |-- web_errorTest_api.php
   |-- channels.php
   |-- console.php
   |-- welcome_web.PHP
   |-- welcome_api.PHP
   |-- web_User.php
   |-- api_User.php
   |-- Role
        |-- role_WEB.php
        |-- role_API.php
  • web.phpwelcome_web.PHPweb_User.phpRole/role_WEB.php这些路由文件将被分配到web中间件组。

  • api.phpwelcome_api.PHPapi_User.phpRole/role_API.php这些路由文件将被分配到api中间件组。

  • 当加载 web_errorTest_api.php 路由文件时,由于文件同时被分配给了 webapi 中间件组,扩展包会抛出错误。开发者命名带有默认规则的路由文件时应注意这一点。

默认使用的根命名空间

所有允许匹配路由文件默认值的中间件组的根命名空间默认为 App\Providers\RouteServiceProvider 中的 $namespace 属性值。

默认使用的子域名

所有允许匹配路由文件默认值的中间件组的子域名默认为空。

默认使用的路由前缀

  • web 中间件组的 prefix 默认为空。

  • 允许匹配路由文件的其他中间件组的 prefix 默认使用中间件组的名称。

例如

默认情况下,web 中间件组的 prefix 为空;api 中间件组的 prefix 使用中间件组的名称 api。依此类推。

默认使用的路由名称前缀

所有允许匹配路由文件的中间件组使用的路由名称前缀 name 默认为空。

默认使用的路由参数正则表达式约束

所有允许匹配路由文件的中间件组使用的路由参数正则表达式约束 where 默认为空。

默认异常消息响应格式

在使用此功能之前,请手动在App\Exceptions\Handler类的render方法中添加处理异常信息输出格式的函数,否则此功能无效。

  • api 中间件组的异常消息响应格式默认为 Json。

  • 允许匹配路由文件的其他中间件组的异常消息响应格式由全局默认异常消息响应格式设置决定。

自定义规则

自定义规则将覆盖默认规则,未经自定义的将继续使用默认规则。

提示:设置自定义规则时,如果设置有误,将抛出异常,异常信息的响应格式将由默认规则决定。

自定义规则仅对允许匹配路由文件的中间件组有效。如果一个中间件组不允许匹配路由文件,则即使设置了规则也无用。

要设置自定义规则,请将方法添加到 app/Providers/RouteServiceProvider.php

protected function customMiddlewareGroupsConfig()
{
    return array(
        '{middlewareGroupName}' => array(
            'namespace' => '',
            'domain' => '',
            'prefix' => '',
            'name' => '',
            'where' => [],
            'eJsonResponse' => false,
            'matchRule' => function ($fileRelativePath) {
                // your code ...
                // The return value must be a boolean.
                return false;
            }
        )

        // ...
    );
}

该方法返回一个二维数组。一维键 {middlewareGroupName} 是需要自定义的中间件组名称。

{middlewareGroupName} 的值也是一个数组。可配置的键有 namespacedomainprefixnamewhereeJsonResponsematchRule

自定义中间件组使用的根命名空间

提示:如果中间件组自定义了根命名空间且其值与 App\Providers\RouteServiceProvider 中的 $namespace 属性值不同,则当使用如 action()redirectToAction() 等方法,其中传入的参数是控制器字符串时,如果传入的参数属于该中间件组下的控制器,则应该传入以 \ 开头的完整命名空间控制器字符串。

建议:无论根命名空间是否可自定义,在使用以控制器字符串作为传入参数的方法(如 action()redirectToAction())时,都应该传入以 \ 开头的完整命名空间控制器字符串。

例如

Welcome@index 控制器属于 web 中间件组,并使用默认的根命名空间 App\Http\Controllers

在自定义 web 中间件组的根命名空间之前,使用 action() 方法时,可以调用:action('Welcome@index');action('\App\Http\Controllers\Welcome@index');

自定义根命名空间后,需要调用:action('\CustomNamespace\Welcome@index');

如果您需要自定义中间件组使用的根命名空间,请在中间件组的配置数组下设置 namespace 键值对。

  • namespace 的值必须是一个 字符串或 null

  • 如果 namespace 的值类型错误,将会抛出异常。

如果您不需要自定义中间件组的根命名空间,请勿在中间件组的配置数组下设置此项目的键值对,否则默认值将被覆盖。

自定义中间件组使用的子域名

要自定义中间件组使用的子域名限制,请在该中间件组的配置数组下设置 domain 键值对。

  • domain 的值必须是一个 字符串或 null

  • 如果 domain 的值类型错误,将会抛出异常。

如果您不需要自定义中间件组的子域名限制,请勿在该中间件组的配置数组下设置此项目的键值对,否则默认值将被覆盖。

自定义中间件组使用的路由前缀

要自定义中间件组使用的路由前缀,请在该中间件组的配置数组下设置 prefix 键值对。

  • prefix 的值必须是一个 字符串或 null

  • 如果 prefix 的值类型错误,将会抛出异常。

如果您不需要自定义中间件组的路由前缀,请勿在该中间件组的配置数组下设置此项目的键值对,否则默认值将被覆盖。

自定义中间件组使用的路由名称前缀

要自定义中间件组使用的路由名称前缀,请在该中间件组的配置数组下设置 name 键值对。

  • name 的值必须是一个 字符串或 null

  • 如果 name 的值类型错误,将会抛出异常。

如果您不需要自定义中间件组的路由名称前缀,请勿在该中间件组的配置数组下设置此项目的键值对,否则默认值将被覆盖。

自定义中间件组使用的路由参数的正则表达式约束

要自定义中间件组使用的路由参数正则表达式约束,请在该中间件组的配置数组下设置 where 键值对。

  • where 的值必须是一个 数组或 null

  • 如果 where 的值类型错误,将会抛出异常。

  • 如何正确设置路由参数的正则表达式约束,请参阅 Laravel 文档 - 路由 - 正则表达式约束。

如果您不需要自定义中间件组使用的路由参数正则表达式约束,请勿在该中间件组的配置数组下设置此项目的键值对,否则默认值将被覆盖。

自定义中间件组的异常消息响应格式是否为 Json

在使用此功能之前,请手动在App\Exceptions\Handler类的render方法中添加处理异常信息输出格式的函数,否则此功能无效。

如果您需要自定义中间件组的异常消息响应格式是否为 Json,请在中间件组的配置数组下设置 eJsonResponse 键值对。

  • eJsonResponse 的值必须是一个 布尔值(truefalse

  • 如果 eJsonResponse 的值类型错误,将会抛出异常。

  • eJsonResponse 配置项不存在或其值为 null 时,异常消息的响应格式将根据默认规则和全局默认设置 $defaultExceptionJsonResponse 确定。

  • eJsonResponse的值为true时,在访问该中间件组下的路由时,异常消息的响应将采用JSON格式。

  • eJsonResponse的值为false时,访问该中间件组下路由时异常消息的响应格式由请求头中的Accept参数决定。

如果您不需要自定义中间件组的异常消息响应格式,不要在中间件组的配置数组中设置该项的键值对,否则默认值将被覆盖。

中间件组的自定义路由文件匹配规则

如果您需要自定义中间件组使用的路由文件匹配规则,请在中间件组的配置数组中设置matchRule键值对。

注意:当在routes目录中重复加载同一路由文件超过3次时,扩展包将抛出异常。开发者应检查路由文件是否重复引用。如果自定义了路由匹配规则,也应检查匹配规则的正确性。

  • matchRule的值是一个闭包

  • 路由文件的路径将被传递到闭包中。此路径相对于routes目录。开发者需要将路由文件路径与中间件组的匹配规则编码。如果路由文件路径满足匹配条件,闭包需要返回true,否则返回false

    注意:传递给闭包的路径是区分大小写的。

    //e.g.
    //Custom matching rules for web middleware groups
    'web' => array(
        'matchRule' => function ($fileRelativePath) {
            $fileRelativePath = strtolower($fileRelativePath); //Turn lowercase
            if (Str::endsWith($fileRelativePath, '_web.php')) {
                  //If the routing file ends in `_web.php`, it is assigned to the web middleware group
                  return true;
            } else {
                  return false;
            }
        }
    )
  • 闭包的返回值必须是一个布尔值(truefalse)。

  • matchRule的值不是一个闭包或者闭包的返回值不是一个布尔值时,会抛出异常。

如果您不需要自定义中间件组的路由文件匹配规则,不要在中间件组的配置数组中设置该项的键值对,否则默认值将被覆盖。

生成路由缓存

当应用程序部署到生产环境时,别忘了在生产环境中生成路由缓存!

输入命令

php artisan route:cache

该命令在bootstrap/cache目录下生成路由缓存文件。

注意,路由缓存不适用于基于闭包的路由。要使用路由缓存,所有闭包路由都必须转换为控制器类。

如果使用了闭包路由,在生成缓存时会报告错误!

此外,如果您添加了任何新路由,必须生成新的路由缓存!

如果您想删除缓存路由文件,可以使用以下命令

php artisan route:clear

许可证

该扩展包是开源软件,许可协议为MIT许可证