请求生命周期
简介
在“现实世界”中使用任何工具时,如果你理解了它的工作原理,就会更有信心。应用开发也是如此。当你了解开发工具的运作方式后,使用它们时会感到更加从容和自信。
本文档的目标是为你提供一个关于 Laravel 框架工作原理的高层概述。通过更好地了解整个框架,一切都会变得不再那么“神奇”,你在构建应用时也会更有底气。如果你不能立即理解所有术语,也不要气馁!只需试着对正在发生的事情有一个基本的把握,随着你深入阅读文档的其他章节,你的知识体系自然会不断成长。
生命周期概述
入门指南
Laravel 应用所有请求的入口点是 public/index.php 文件。所有的请求都会由 Web 服务器(Apache / Nginx)配置定向到该文件。index.php 文件本身包含的代码并不多。它主要是作为一个加载框架其余部分的起点。
index.php 文件会加载 Composer 生成的自动加载器定义,然后从 bootstrap/app.php 获取 Laravel 应用实例。Laravel 自身执行的第一个动作是创建应用实例 / 服务容器。
HTTP / Console 内核
接下来,传入的请求会根据进入应用的请求类型,使用应用实例的 handleRequest 或 handleCommand 方法被发送到 HTTP 内核或控制台内核。这两个内核是所有请求流经的中心枢纽。现在,我们先重点关注 HTTP 内核,它是 Illuminate\Foundation\Http\Kernel 的一个实例。
HTTP 内核定义了一个 bootstrappers(引导程序)数组,这些引导程序会在请求执行前运行。它们负责配置错误处理、配置日志、检测应用环境,并执行其他在处理请求前必须完成的任务。通常,这些类处理的是你无需担心的 Laravel 内部配置。
HTTP 内核还负责将请求传递给应用的中间件堆栈。这些中间件负责读取和写入 HTTP 会话、确定应用是否处于维护模式、验证 CSRF 令牌等。我们很快会深入探讨这些内容。
HTTP 内核的 handle 方法签名非常简单:它接收一个 Request 对象并返回一个 Response 对象。你可以把内核想象成一个代表你整个应用的巨大“黑盒”。向它输入 HTTP 请求,它就会返回 HTTP 响应。
服务提供者
内核最重要的引导操作之一是为你的应用加载 服务提供者。服务提供者负责引导框架的各个组件,例如数据库、队列、验证和路由组件。
Laravel 会遍历这个提供者列表并实例化它们。在实例化提供者之后,将对所有提供者调用 register 方法。接着,一旦所有提供者都注册完毕,就会调用每个提供者的 boot 方法。这样做的目的是确保服务提供者在执行其 boot 方法时,所有容器绑定都已注册并可用。
本质上,Laravel 提供的每一个主要功能都是由服务提供者引导和配置的。由于它们引导和配置了框架提供的大量功能,因此服务提供者是整个 Laravel 引导过程中最重要的部分。
虽然框架内部使用了数十个服务提供者,但你也可以创建自己的提供者。你可以在 bootstrap/providers.php 文件中找到你的应用正在使用的用户自定义或第三方服务提供者的列表。
路由
一旦应用完成了引导且所有服务提供者都已注册,Request 就会被交给路由器进行分发。路由器会将请求分发给相应的路由或控制器,并运行所有路由特定的中间件。
中间件提供了一种方便的机制来过滤或检查进入你应用的 HTTP 请求。例如,Laravel 包含一个验证用户是否已通过身份验证的中间件。如果用户未通过认证,中间件会将用户重定向到登录页面。反之,如果用户已通过认证,中间件则允许请求继续进入应用。有些中间件会分配给应用内的所有路由,例如 PreventRequestsDuringMaintenance,而有些则仅分配给特定的路由或路由组。你可以通过阅读完整的 中间件文档 来深入了解。
如果请求通过了匹配路由所分配的所有中间件,则会执行路由或控制器方法,并且该方法返回的响应将通过路由的中间件链反向传回。
收尾工作
当路由或控制器方法返回响应后,响应会向外穿过路由的中间件,从而使应用有机会修改或检查即将发出的响应。
最后,当响应穿过中间件返回时,HTTP 内核的 handle 方法会将响应对象返回给应用实例的 handleRequest 方法,该方法会调用所返回响应的 send 方法。send 方法将响应内容发送到用户的 Web 浏览器。至此,我们已经完成了整个 Laravel 请求生命周期的旅程!
聚焦服务提供者
服务提供者确实是引导 Laravel 应用的关键。应用实例被创建,服务提供者被注册,请求被交给已引导的应用。这一切就是这么简单!
牢牢掌握 Laravel 应用如何构建以及如何通过服务提供者进行引导非常有价值。你应用中用户自定义的服务提供者存储在 app/Providers 目录中。
默认情况下,AppServiceProvider 是相当空的。这个提供者非常适合添加你应用自己的引导逻辑和服务容器绑定。对于大型应用,你可能希望创建多个服务提供者,每个提供者为应用使用的特定服务提供更细粒度的引导。