Skip to main content
为包添加 HTTP 功能时,要把“让中间件可用”与“将其应用到使用方应用的请求上”区分开来。如果设计成仅安装包并不会改变所有路由的行为,就更容易管理引入时的影响和未来的兼容性。 本页以包开发基础为前提,参考 Laravel 官方文档 13.x 以及 Framework v13.36.0 的实现。常规中间件的写法请参阅中间件。

区分注册、应用与执行

Router::aliasMiddleware() 以别名为键、类名为值,将其注册到 Router 的数组中。它不会创建中间件实例,也不会将其应用到路由上。 别名是公开 API。请避免使用 auth、throttle 等内置名称,以及容易与其他包冲突的通用名称,并加上包专属的前缀。如果对同一个键重新注册,aliasMiddleware() 会覆盖之前的映射。

在服务提供者中公开别名

下面的示例创建一个为响应添加固定标识头的中间件。这不是认证、授权或访问控制的示例。前提是通过 Composer 的 PSR-4 将 Acme\Courier\ 映射到 src/,并通过自动发现或手动方式注册服务提供者。
src/Http/Middleware/AddCourierHeader.php
Router 的使用放在 boot() 中进行。boot() 的参数由服务容器注入,因此无需为了注册中间件而自动编辑使用方的 bootstrap/app.php。
src/CourierServiceProvider.php
请将此服务提供者作为常规服务提供者启动。如果把别名注册移到仅在解析其他服务时才执行的延迟服务提供者中,就无法保证在路由需要时已完成注册。

由使用方按路由应用

在使用方应用的 routes/web.php 中,只分配给需要的路由。
routes/web.php
也可以不提供别名,而是像 ->middleware(AddCourierHeader::class) 这样直接指定类名。可根据是否需要为使用方提供简短名称来选择。 当包自身提供路由时,也要在路由文件中显式指定所需的中间件。loadRoutesFrom() 不会自动添加 web 或 api。注册方式与路由缓存的处理请参阅包的路由注册与缓存。

是否应用到整个应用由使用方选择

如果希望应用到使用方应用的所有 web 路由,由使用方在现有的 withMiddleware() 回调中添加以下配置。这并不是替换现有配置的示例。
此配置直接使用类名,因此不依赖别名的注册顺序。适用范围是 web 分组,而不是全局栈。它不会自动应用到 api 路由,或未附加任何分组的路由。
在安装包时就应用到整个 web 的设计,与由使用方显式应用的设计并不兼容。请不要通过自动更新,将影响认证、会话、响应头、外部通信等的处理扩展到所有路由。

Router 的分组操作存在差异

当包提供自己的分组时,请使用专属名称。以下是放在服务提供者的 boot(Router $router) 中的示例。
使用方可以通过 ->middleware('acme-courier') 应用。不过,该分组只包含所指定的类,并不会继承 web 的会话或 CSRF 保护。 也有向现有分组添加的 API,但在 v13.36.0 的 Router 实现中存在以下差异。 如果用 middlewareGroup('web', [...]) 只设置包的类,就会替换掉现有 web 的内容。请不要与用于追加的方法混淆。此外,即使对不存在的 web 执行 pushMiddlewareToGroup(),也不会恢复标准的 web 分组。 追加方法的重复判定针对的是所注册的值。指向同一个类的别名与类名是不同的字符串,因此在注册表阶段会被视为不同的项。请统一写法,不要假设不同写法的同一个类会在注册时被去重。

不要仅靠注册顺序保证执行顺序

Router 会展开分配给路由的中间件别名与分组,处理排除后再按优先级排序。仅靠添加到开头或末尾,并不能保证与认证或路由模型绑定之间严格的先后关系。 此外,HTTP Kernel 的 syncMiddlewareToRouter() 会通过 middlewareGroup() 将 Kernel 持有的分组同步到 Router。如果 Kernel 一侧的配置之后被重新同步,直接添加到 Router 的分组内容可能会被替换。基本方针是:不要依靠包之间的启动顺序去争抢修改现有分组,而是在使用方应用一侧的 withMiddleware() 中集中配置。 对于需要“会话开始后”“认证后”等顺序的功能,请在安装步骤中写明该前提,并结合使用方应用的优先级设置进行确认。请避免由包整体替换应用的优先级列表。

缓存与验证的边界

请不要把别名注册放在 routesAreCached() 的条件内或路由文件中。存在缓存时,loadRoutesFrom() 不会加载路由文件,但为了在运行时解析缓存路由中保留的别名,仍需要进行注册。请在服务提供者的 boot() 中每次都进行注册。 如果更改了对路由的分配,请在使用方应用中重新生成路由缓存。
-vv 用于展开并确认分组的内容。不过,列表显示成功并不能保证中间件内的处理以及会话的使用。还需要进行 HTTP 请求测试。 下面是添加到定义了上述 /courier-status 的 Laravel 应用 Feature 测试中的方法。
检查分组是否存在或别名数组的单元测试,与实际的 HTTP 执行是不同的验证。尤其是缓存验证,不能只查看同一进程中的 Router,而要在生成缓存后的新启动中进行。如果使用长驻 worker,请按照常规部署流程重新加载。

相关页面

中间件

了解创建、应用到路由、参数以及优先级的基础知识。

包的路由注册与缓存

了解路由加载与生成缓存时配置之间的关系。

参考的一手资料

最后修改于 2026年10月15日