Laravel路由中间件?中间件如何分配路由?

Laravel由中间件是请求到达控制器前的过滤机制,可用于认证、授权、日志等操作。可通过全局、路由组、单个路由或控制器方式分配,执行顺序遵循“从外到内”原则:全局中间件 → 路由组中间件 → 单个/控制器中间件,响应时则逆序执行后续逻辑。

laravel路由中间件?中间件如何分配路由?

Laravel的路由中间件,在我看来,就像是HTTP请求抵达你应用核心逻辑(比如控制器方法)前的一道道关卡或守卫。它的核心作用,就是让你能在请求真正被处理之前或之后,执行一些预设的操作。至于如何分配路由,其实Laravel给了我们很多灵活的方式,无论是全局、针对一组路由,还是某个特定的路由,甚至是在控制器内部,都能精准地挂载中间件。

解决方案

要说如何在Laravel里分配中间件给路由,其实方法挺多的,每种都有它适用的场景。我个人觉得,理解这些不同的分配方式,是掌握Laravel请求生命周期的关键一步。

全局中间件 (Global Middleware)这是最粗放也最直接的方式,任何进入你应用的HTTP请求都会经过这些中间件。你可以在

app/Http/Kernel.php

文件的

$middleware

属性中定义它们。

// app/Http/Kernel.phpprotected $middleware = [    AppHttpMiddlewareTrustProxies::class,    AppHttpMiddlewarePreventRequestsDuringMaintenance::class,    IlluminateFoundationHttpMiddlewareValidatePostSize::class,    AppHttpMiddlewareTrimStrings::class,    IlluminateFoundationHttpMiddlewareConvertEmptyStringsToNull::class,    // AppHttpMiddlewareEncryptCookies::class, // 假设我不想所有请求都加密cookie    // ... 其他全局中间件];

坦白讲,全局中间件我用得不多,通常是那些对所有请求都生效的基础性操作,比如处理CORS、维护模式检查或者一些基础的请求数据处理。

路由组中间件 (Route Group Middleware)这是我个人最常用的一种方式,尤其是在构建API或者需要对一组相关路由应用相同策略时。通过

Route::middleware()

方法,你可以将一个或多个中间件应用到一个路由组上。

// routes/web.php 或 routes/api.phpRoute::middleware(['auth', 'verified'])->group(function () {    Route::get('/dashboard', function () {        // 需要认证且邮箱已验证才能访问    });    Route::get('/profile', 'UserProfileController@show');});// 也可以是多个中间件链式调用Route::middleware('auth')->middleware('throttle:60,1')->group(function () {    Route::post('/order', 'OrderController@store');});

这种方式的好处在于,它能让你的路由文件看起来更整洁,逻辑也更清晰。想象一下,如果每个路由都单独写

->middleware('auth')

,那代码得多冗余啊。

单个路由中间件 (Individual Route Middleware)如果你只想给某个特定的路由应用中间件,直接在路由定义后面链式调用

middleware()

方法就行。

// routes/web.phpRoute::get('/admin/settings', 'AdminController@showSettings')->middleware('admin');Route::post('/logout', 'AuthLoginController@logout')->middleware('auth');

这个方法很直观,适合那些有特殊需求的单个路由。但如果多个路由有相同需求,我肯定会考虑用路由组。

控制器中间件 (Controller Middleware)有时候,你可能希望一个控制器里的所有方法,或者部分方法,都经过某个中间件处理。这时候,可以在控制器的构造函数里定义。

// app/Http/Controllers/PostController.phpclass PostController extends Controller{    public function __construct()    {        $this->middleware('auth'); // 所有方法都需要认证        $this->middleware('can:update,post')->only('edit', 'update'); // 只有edit和update方法需要授权        $this->middleware('log.access')->except('show'); // 除了show方法,其他方法都要记录访问日志    }    public function index() { /* ... */ }    public function create() { /* ... */ }    public function store() { /* ... */ }    public function show(Post $post) { /* ... */ }    public function edit(Post $post) { /* ... */ }    public function update(Request $request, Post $post) { /* ... */ }    public function destroy(Post $post) { /* ... */ }}

我个人觉得控制器中间件非常方便,尤其是在处理资源控制器(Resource Controllers)时,它能让你在控制器层面进行更细粒度的控制,避免了路由文件过于臃肿。

only()

except()

方法的组合拳,更是让这种控制变得异常强大。

Laravel中间件的执行顺序是怎样的?

说实话,中间件的执行顺序是个常常让人感到困惑,但又极其重要的问题。理解它,能帮你更好地调试请求流程,避免一些意想不到的行为。在我看来,Laravel中间件的执行顺序,可以大致概括为“从外到内,再从内到外”的原则。

具体来说,当一个HTTP请求进入Laravel应用时,它会首先经过

app/Http/Kernel.php

$middleware

属性里定义的全局中间件。这些中间件是所有请求的“必经之路”,它们按照你在数组中定义的顺序依次执行。

紧接着,如果请求命中了某个路由组,那么这个路由组上挂载的中间件会开始执行。这些中间件的执行顺序,就是你在

Route::middleware([...])

数组中定义的顺序。

再往里走,如果路由组内的某个具体路由还单独挂载了中间件,或者你是在控制器构造函数里为特定方法定义了中间件,那么这些中间件会在路由组中间件之后执行。同样,它们的顺序也取决于定义时的顺序。

总结一下,一个请求的中间件执行顺序大概是:

全局中间件 (Kernel.php

$middleware

)路由中间件组 (Kernel.php

$middlewareGroups

,如果路由使用了组别,如

web

api

)路由组中间件 (

Route::middleware([...])->group()

)单个路由中间件 (

->middleware()

) 或 控制器中间件 (

$this->middleware()

)

值得一提的是,中间件的

handle

方法在请求到达控制器之前执行,而中间件中的

terminate

方法(如果你定义了的话)则是在HTTP响应发送给浏览器之后才执行。这意味着

terminate

方法非常适合做一些清理、日志记录等不影响响应速度的操作。

// app/Http/Kernel.phpprotected $middleware = [    // 1. 全局中间件 A    AppHttpMiddlewareTrustProxies::class,    // 2. 全局中间件 B    AppHttpMiddlewarePreventRequestsDuringMaintenance::class,];protected $middlewareGroups = [    'web' => [        // 3. Web组中间件 A        AppHttpMiddlewareEncryptCookies::class,        // 4. Web组中间件 B        IlluminateSessionMiddlewareStartSession::class,    ],    'api' => [        // 5. API组中间件 A        LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful::class,        // 6. API组中间件 B        'throttle:api',    ],];// routes/web.phpRoute::middleware(['auth', 'check.role:admin'])->group(function () {    // 7. 路由组中间件 auth    // 8. 路由组中间件 check.role:admin    Route::get('/admin', 'AdminController@index')->middleware('log.activity');    // 9. 单个路由中间件 log.activity});

所以,请求的实际路径是:全局A -> 全局B -> Web组A -> Web组B -> auth -> check.role:admin -> log.activity -> 控制器方法。然后响应回来的时候,这个顺序会反过来执行中间件的后续逻辑(如果

handle

方法中有

$next($request)

之后的代码)和

terminate

方法。这种层层嵌套的机制,是Laravel中间件强大灵活的基础。

如何在Laravel中创建和注册自定义中间件?

创建和注册自定义中间件,是Laravel开发中非常常见且实用的操作。它允许你根据自己的业务需求,定制请求处理流程中的任何环节。

首先,创建中间件非常简单,Laravel提供了一个Artisan命令:

php artisan make:middleware MyCustomLogger

执行这个命令后,Laravel会在

app/Http/Middleware

目录下生成一个名为

MyCustomLogger.php

的文件。文件内容大致如下:

method() . ' ' . $request->fullUrl());        $response = $next($request); // 将请求传递给下一个中间件或控制器        // 在请求离开控制器之后执行的逻辑        // 比如,记录响应状态码        Log::info('Outgoing response status: ' . $response->getStatusCode());        return $response;    }}

handle

方法是中间件的核心。它接收两个参数:

$request

(当前的HTTP请求)和

$next

(一个闭包,代表请求流中的下一个处理者,可能是另一个中间件,也可能是控制器)。

$next($request)

之前的代码,会在请求到达控制器之前执行。

$next($request)

之后的代码,会在控制器处理完请求并生成响应之后,但在响应返回给客户端之前执行。

接下来是注册。自定义中间件创建好之后,你需要让Laravel知道它的存在。这通常在

app/Http/Kernel.php

文件中完成。

如果你想将它注册为路由中间件(即可以通过别名在路由或控制器中使用),你需要把它添加到

$routeMiddleware

属性中:

// app/Http/Kernel.phpprotected $routeMiddleware = [    'auth' => AppHttpMiddlewareAuthenticate::class,    'verified' => AppHttpMiddlewareEnsureEmailIsVerified::class,    'my.logger' => AppHttpMiddlewareMyCustomLogger::class, // 注册你的自定义中间件    // ... 其他路由中间件];

注册后,你就可以像使用内置中间件一样,在路由或控制器中通过

my.logger

这个别名来应用它了:

Route::get('/some-path', 'SomeController@index')->middleware('my.logger');

或者,如果你想让它成为全局中间件,那么就把它添加到

$middleware

属性中:

// app/Http/Kernel.phpprotected $middleware = [    // ...    AppHttpMiddlewareMyCustomLogger::class, // 作为全局中间件注册];

一旦注册为全局中间件,所有进入应用的请求都会经过

MyCustomLogger

处理。选择哪种注册方式,完全取决于你的业务需求。大多数情况下,我更倾向于注册为路由中间件,这样可以更灵活地控制哪些请求需要经过我的自定义逻辑。

Laravel中间件在实际项目中常见的应用场景有哪些?

在实际的Laravel项目开发中,中间件几乎无处不在,它的设计哲学就是为了让你能优雅地解耦请求处理前的各种“横切关注点”。在我看来,中间件是构建健壮、可维护的Laravel应用不可或缺的一部分。

这里我列举一些我个人在项目中经常用到,或者觉得非常典型的应用场景:

用户认证 (Authentication):这是最常见也是最重要的应用。Laravel内置的

auth

中间件就是为此而生。它会检查用户是否已登录。如果未登录,通常会重定向到登录页面或返回未认证的响应。

Route::middleware('auth')->group(function () {    Route::get('/dashboard', 'DashboardController@index');    // ... 其他需要登录才能访问的路由});

对于API,

auth:api

auth:sanctum

则是验证API令牌或会话的利器。

用户授权 (Authorization):在用户认证之后,你可能还需要检查用户是否有权限执行某个操作。Laravel的

can

中间件结合了策略(Policies)或门面(Gates)来实现授权。

Route::get('/posts/{post}/edit', 'PostController@edit')->middleware('can:update,post');

这里

can:update,post

会检查当前用户是否有权限更新传入的

post

模型。

CSRF 保护 (CSRF Protection):Laravel的

VerifyCsrfToken

中间件是默认开启的全局中间件,它能有效防止跨站请求伪造攻击,确保所有非GET请求都带有有效的CSRF令牌。这个真的非常省心,我们几乎不用操心。

请求限流 (Rate Limiting):对于API接口,为了防止恶意攻击或资源滥用,限流是必不可少的。Laravel的

throttle

中间件可以轻松实现。

Route::middleware('throttle:60,1')->group(function () { // 每分钟最多60次请求    Route::post('/api/submit-form', 'ApiController@submit');});

这能很好地保护你的后端服务。

维护模式 (Maintenance Mode):当你的应用需要进行升级或维护时,

PreventRequestsDuringMaintenance

中间件能让所有请求都重定向到一个维护页面,直到你关闭维护模式。这也是一个默认的全局中间件,非常实用。

日志记录与审计 (Logging & Auditing):我上面自定义的

MyCustomLogger

就是一个很好的例子。你可以在中间件中记录请求的详细信息(如IP、User-Agent、请求路径、请求参数),或者记录响应状态、执行时间等,用于监控和审计。

API 密钥验证 (API Key Validation):如果你在构建一个公共API,可能需要验证请求头中是否包含有效的API Key。

// app/Http/Middleware/VerifyApiKey.phppublic function handle(Request $request, Closure $next): Response{    if (!$request->header('X-API-Key') || !$this->isValidApiKey($request->header('X-API-Key'))) {        return response()->json(['message' => 'Unauthorized: Invalid API Key'], 401);    }    return $next($request);}// routes/api.phpRoute::middleware('verify.api.key')->group(function () {    Route::get('/api/data', 'ApiController@getData');});

数据预处理与清理 (Data Preprocessing & Sanitization):例如,将所有字符串输入自动去除首尾空格 (

TrimStrings

中间件),或者将空字符串转换为

null

(

ConvertEmptyStringsToNull

中间件)。这些都是Laravel默认提供的,极大提高了开发效率和数据一致性。

语言本地化 (Localization):根据用户的请求头(如

Accept-Language

)或者URL参数,动态设置应用的语言环境。

// app/Http/Middleware/SetLocale.phppublic function handle(Request $request, Closure $next): Response{    if ($request->hasHeader('Accept-Language')) {        App::setLocale($request->header('Accept-Language'));    }    return $next($request);}// ... 注册并应用

这些场景只是冰山一角。中间件的强大之处在于它提供了一个统一且可扩展的机制,来处理请求生命周期中的各种通用逻辑,让你的控制器能更专注于业务逻辑本身,从而实现代码的清晰、解耦和高内聚。

以上就是Laravel路由中间件?中间件如何分配路由?的详细内容,更多请关注php中文网其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/146792.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
漫蛙manwa官网入口 _ 漫蛙漫画最新备用入口
上一篇 2025年12月2日 12:14:13
微软悄然行动:Office 2019涨价
下一篇 2025年12月2日 12:14:14

相关推荐

  • composer require-dev和require有什么不同_Composer Require与Require-Dev区别解析

    require用于声明项目运行必需的依赖,如框架、数据库组件和第三方SDK,这些包会随项目部署到生产环境;2. require-dev用于声明仅在开发和测试阶段需要的工具,如PHPUnit、PHPStan、Faker等,不会默认部署到生产环境;3. 安装时composer install根据环境决定…

    2026年5月10日
    1000
  • 修复Django电商项目中AJAX过滤产品列表图片不显示问题

    在Django电商项目中,当使用AJAX动态加载过滤后的产品列表时,常遇到图片无法正常显示的问题。这通常是由于前端模板中图片加载方式(如data-setbg属性结合JavaScript库)与AJAX动态内容更新机制不兼容所致。解决方案是直接在AJAX返回的HTML中使用标准的标签来渲染图片,确保浏览…

    2026年5月10日
    000
  • 开源免费PHP工具 PHP开发效率提升利器

    推荐开源免费PHP开发工具以提升效率:VS Code、Sublime Text轻量高效,PhpStorm专业强大;调试用Xdebug、Kint、Ray;依赖管理选Composer;代码质量工具包括PHPStan、Psalm、PHP_CodeSniffer;数据库管理可用%ignore_a_1%MyA…

    2026年5月10日
    000
  • Matplotlib 地图中多类型图例的创建与优化

    Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化

    本教程旨在解决matplotlib地图可视化中,如何在一个图例中同时展示颜色块(如区域分类)和自定义标记(如特定兴趣点)的问题。文章详细介绍了当传统`patch`对象无法正确显示标记时,如何利用`matplotlib.lines.line2d`创建标记图例句柄,并将其与颜色块图例句柄合并,从而生成一…

    2026年5月10日 用户投稿
    100
  • Golang JSON序列化:控制敏感字段暴露的最佳实践

    本教程探讨golang中如何高效控制结构体字段在json序列化时的可见性。当需要将包含敏感信息的结构体数组转换为json响应时,通过利用`encoding/json`包提供的结构体标签,特别是`json:”-“`,可以轻松实现对特定字段的忽略,从而避免敏感数据泄露,确保api…

    2026年5月10日
    000
  • 怎么在PHP代码中实现图片上传功能_PHP图片上传功能实现与安全处理教程

    首先创建含enctype的HTML表单,再用PHP接收文件,检查目录、移动临时文件,验证类型与大小,生成唯一文件名,并调整php.ini限制以确保上传成功。 如果您尝试在PHP项目中添加图片上传功能,但服务器无法正确接收或保存文件,则可能是由于表单配置、文件处理逻辑或安全限制的问题。以下是实现该功能…

    2026年5月10日
    100
  • 获取日期中的周数:CodeIgniter 教程

    本教程旨在帮助开发者在 CodeIgniter 框架中,从日期字符串中准确提取周数。我们将使用 PHP 内置的 DateTime 类,并提供详细的代码示例和注意事项,确保您能够轻松地在项目中实现此功能。 使用 DateTime 类获取周数 PHP 的 DateTime 类提供了一种便捷的方式来处理日…

    2026年5月10日
    100
  • 比特币新手教程 比特币交易平台有哪些

    比特币是一种去中心化的数字货币,基于区块链技术实现点对点交易,具有匿名性、有限发行和不可篡改等特点;新手可通过交易所购买,P2P交易获得比特币,常用平台包括Binance、OKX和Huobi;交易流程包括注册账户、实名认证、绑定支付方式、充值法币并下单购买,可选择市价单或限价单;比特币存储方式有交易…

    2026年5月10日
    000
  • c++中的SFINAE技术是什么_c++模板编程中的SFINAE原理与应用

    SFINAE 是“替换失败不是错误”的原则,指模板实例化时若参数替换导致错误,只要存在其他合法候选,编译器不报错而是继续重载决议。它用于条件启用模板、类型检测等场景,如通过 decltype 或 enable_if 控制函数重载,实现类型特征判断。尽管 C++20 引入 Concepts 简化了部分…

    2026年5月10日
    000
  • Golang gRPC流式请求异常处理

    在Golang的gRPC流式通信中,必须通过context.Context处理异常。应监听上下文取消或超时,及时释放资源,设置合理超时,避免连接长时间挂起,并在goroutine中通过context控制生命周期。 在使用 Golang 和 gRPC 实现流式通信时,异常处理是确保服务健壮性的关键部分…

    2026年5月10日
    000
  • Go语言mgo查询构建:深入理解bson.M与日期范围查询的正确实践

    本文旨在解决go语言mgo库中构建复杂查询时,特别是涉及嵌套`bson.m`和日期范围筛选的常见错误。我们将深入剖析`bson.m`的类型特性,解释为何直接索引`interface{}`会导致“invalid operation”错误,并提供一种推荐的、结构清晰的代码重构方案,以确保查询条件能够正确…

    2026年5月10日
    100
  • vscode上怎么运行html_vscode上运行html步骤【指南】

    首先保存文件为.html格式,再通过浏览器或Live Server插件打开预览;推荐安装Live Server实现本地服务器运行与实时刷新,提升开发体验。 在 VS Code 上运行 HTML 文件并不需要复杂的配置,只需几个简单步骤即可预览页面效果。VS Code 本身是一个代码编辑器,不直接运行…

    2026年5月10日
    100
  • 修复点击时按钮抖动:CSS垂直对齐实践

    本文探讨了在Web开发中,交互式按钮(如播放/暂停按钮)在点击时发生意外垂直位移的问题。通过分析CSS样式变化对元素布局的影响,我们发现这是由于按钮不同状态下的边框样式和内边距改变,以及默认的垂直对齐行为共同作用所致。核心解决方案是利用CSS的vertical-align属性,将其设置为middle…

    2026年5月10日
    100
  • Golang goroutine与channel调试技巧

    使用go run -race检测数据竞争,结合runtime.NumGoroutine监控协程数量,通过pprof分析阻塞调用栈,利用select超时避免永久阻塞,有效排查goroutine泄漏、死锁和数据竞争问题。 Go语言的goroutine和channel是并发编程的核心,但它们也带来了调试上…

    2026年5月10日
    000
  • 使用 Jupyter Notebook 进行探索性数据分析

    Jupyter Notebook通过单元格实现代码与Markdown结合,支持数据导入(pandas)、清洗(fillna)、探索(matplotlib/seaborn可视化)、统计分析(describe/corr)和特征工程,便于记录与分享分析过程。 Jupyter Notebook 是进行探索性…

    2026年5月10日
    000
  • 《魔兽世界》将于6月11日开启国服回归技术测试

    《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试

    《%ign%ignore_a_1%re_a_1%》官方宣布,将于6月11日开启国服回归技术测试,时间为7天,并称可以在6月内正式开服,玩家们可以访问官网下载战网客户端并预下载“巫妖王之怒”客户端,技术测试详情见下图。 WordAi WordAI是一个AI驱动的内容重写平台 53 查看详情 以上就是《…

    2026年5月10日 用户投稿
    200
  • php常量怎么用_PHP常量(define/const)定义与使用方法

    PHP中可通过define函数和const关键字定义常量,用于存储不可变值。define适用于全局作用域,支持动态名称和条件定义,如define(‘SITE_NAME’, ‘MyWebsite’);const在编译时生效,语法简洁但限制多,只能在类或全…

    2026年5月10日
    000
  • 如何在HTML中插入表单元素_HTML表单控件与输入类型使用指南

    HTML表单通过标签构建,包含action和method属性定义数据提交目标与方式,常用input类型如text、password、email等适配不同输入需求,配合label、required、placeholder提升可用性,结合textarea、select、button等控件实现完整交互,是…

    2026年5月10日
    100
  • 前端缓存策略与JavaScript存储管理

    根据数据特性选择合适的存储方式并制定清晰的读写与清理逻辑,能显著提升前端性能;合理运用Cookie、localStorage、sessionStorage、IndexedDB及Cache API,结合缓存策略与定期清理机制,可在保证用户体验的同时避免安全与性能隐患。 前端缓存和JavaScript存…

    2026年5月10日
    200
  • HTML5网页如何实现手势操作 HTML5网页移动端交互的处理技巧

    首先利用原生touch事件实现滑动判断,再通过preventDefault解决滚动冲突,接着引入Hammer.js处理复杂手势,最后通过优化点击区域、避免事件冲突和增加视觉反馈提升体验。 在移动端浏览器中,HTML5网页可以通过触摸事件实现手势操作,提升用户体验。虽然原生JavaScript提供了基…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信