设计思想
请求生命周期
Nginx/Apache
↓定向到
Index.php
↓handleRequest()发送到
HTTP / Console Kernels
↓加载
Service Providers
↓
Routing
↓
Finishing Uppublic/index.php
注册composer自动加载器
require __DIR__.'/../vendor/autoload.php'autoload.php 是composer提供的自动加载器,可以把类加载到任何地方需要使用的地方
小补充:自动加载器只负责把类加载至调用处,但不承担use关键字的功能,如需简化命名空间类的写法,需要使用请使用use关键字
通过引导文件创建Laravel应用/服务容器(Application/Service Container)的实例
/** @var Application $app */
$app = require_once __DIR__.'/../bootstrap/app.php'bootstrap/app.php是Laravel应用启动引导文件,它负责创建Application,通常把结果返回给$app对象,此对象即服务容器
捕获到当前请求交给handleRequest方法处理
$app->handleRequest(Request::capture())Kernel内核初始化Application运行环境
传入 handleRequest() 方法的请求会交由 Kernel内核(Kernel类的一个实例)处理。Kernel 可以理解为 HTTP 请求进入 Laravel 应用后的重要处理中心
Kernel 会通过bootstrappers数组指定的一系列引导程序初始化应用的运行环境。这些运行环境包括:
- 加载环境变量;
- 加载配置;
- 设置异常处理机制;
- 注册 Facade;
- 注册并启动 Service Provider;
完成这些引导工作后,应用的运行环境初始化完成,随后请求会继续进入中间件、路由、控制器等处理流程
Service Providers
同上述,注册并启动Service Providers是Kernel内核最重要的引导操作之一
Service Providers负责引导和配置框架的各种核心组件,包括:数据库、队列、验证、路由...
路由
当kernel完成应用初始化后,应用的运行环境准备完毕,万事俱备!接下来请求会通过路由分发到各个控制器来处理
IoC(控制反转)
IoC是面向对象编程中的一种设计思想:把对象的创建、依赖关系的管理、生命周期控制,全部交给一个外部容器(在Laravel中为Service Container)来负责,使用处只需要声明"我需要什么",容器会自动把依赖“注入”进来(DI,即依赖注入)
与自动加载区别:自动加载解决“类文件怎么加载”,IoC 解决“对象及其依赖怎么创建、管理和注入”
如下为使用IoC执行依赖注入的流程演示:
UserController
│
│ 需要(声明依赖) UserService
↓
Service Container
│
├── 找到/加载 UserService 类
├── 解析 UserService 的依赖
├── 创建 UserService 对象
↓
注入到 UserController声明依赖
即告诉服务容器,我需要谁,在Laravel中依赖声明主要有以下两种位置
class UserController{
// ① 构造函数声明依赖
public function __construct(UserService $service){
$this->service = $service;
}
// ② 普通方法声明依赖
public function show(UserRepository $repository){
return $repository->find(1);
}
}依赖解析
容器根据一个调用处的依赖声明,找到它需要的对象(如果该对象还依赖其他对象,就继续递归解析这些依赖,直到所有依赖都准备好)为后续注入做准备
服务提供者
上文中“创建 UserService 对象”的步骤中,这个对象应该如何创建?这需要引入服务提供者的概念,其向服务容器注册和配置服务
需要注意的是,不是任何服务都要用户手动使用服务提供者来注册和配置,容器可以通过反射解析来自动完成
不能反射解析的服务(接口/单例/原始参数/上下文 /框架扩展),就需要手动用服务提供商注册和配置服务
public function register(): void{
// ① 单例绑定
$this->app->singleton(Connection::class, function (Application $app) {
return new Connection($app['config']['riak']);
});
// ② 接口绑定
$this->app->bind(
PaymentGatewayInterface::class,
AlipayGateway::class
);
}职责优先的类文件划分
Laravel遵循面向对象的设计理念,通常一个文件就是一个类,这些类文件是按照一定的职责进行划分的,这使得各种类文件职责清晰、降低耦合、便于维护
| 类文件 | 主要职责 |
|---|---|
| Controller | 处理 HTTP 请求、协调业务、返回响应 |
| Request | 请求数据验证 |
| Model | 数据模型、数据库相关操作 |
| Service | 复杂业务逻辑 |
| Repository | 数据访问、持久化操作 |
| Middleware | 请求/响应的中间处理 |
| Job | 异步/队列任务 |
| Event | 表示某个事件已经发生 |
| Listener | 处理事件 |
| Policy | 权限/授权判断 |
| Notification | 通知逻辑 |
| Resource | API 响应数据转换 |
| Rule | 自定义验证规则 |
| Exception | 异常处理 |
服务(类)
真正干活的类
例:CardService服务类,用户给一个 card_id,该服务类负责查询卡片并返回卡片信息
class CardService
{
public function getCard(int $cardId): string
{
return "这是卡片 {$cardId}"
}
}服务提供者
用于向服务提供者注册服务(类)并告知如何使用
例:我要注册CardService服务类到服务容器,调用处需要该类时,返回该服务类的对象
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// 告诉容器:我要注册 CardService
$this->app->singleton(CardService::class, function () {
// 告诉容器:需要 CardService 时怎么创建它
return new CardService()
});
}
}用户在 app/Services 中定义的普通服务类,通常不需要通过 Service Provider 注册,因为 Laravel 服务容器能够自动解析和实例化普通具体类
服务类使用
class ReciteController extends Controller
{
public function __construct(
private CardService $cardService
) {}
public function show()
{
return $this->cardService->getCard(1)
}
}app/
│
├── Http/
│ ├── Controllers/ ← 接收 HTTP 请求
│ ├── Middleware/ ← 请求经过的“门”
│ └── Requests/ ← 验证请求数据
│
├── Models/ ← 数据模型 / 数据库
│
├── Providers/ ← 注册、配置服务
│
├── Actions/ ← 一个个具体业务操作
│
├── Services/ ← 复杂业务逻辑
│
├── Console/ ← Artisan 命令
│
└── Exceptions/ ← 异常相关Providers
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// 告诉 Container 怎么注册/创建某些服务
}
public function boot(): void
{
// 应用启动后执行一些初始化工作
}
}注意:自己在Services中创建的具体Service通常不需要再register中注册,因为Service Container会自动解析具体的类
Actions和Services
Actions(操作类)通常是一个类里只有一个方法,用于处理一个具体的业务,Services(服务类)里通常是一个类里一组方法,用于处理同类的业务
Thin Controller
thin controller是一种控制器设计方式:controller内不应该处理一大堆业务逻辑,而是把具体业务交给service完成,自己则负责完成如下逻辑
// 一个thin controller的内部逻辑如下
HTTP Request
↓
Controller
│
├─ ① 接收请求
├─ ② 验证输入
├─ ③ 准备数据(获取用户/参数/文件)
├─ ④ 调用 Service / Action
├─ ⑤ 接收处理结果
└─ ⑥ 返回 Response / Redirect
↓
HTTP Response用户使用某服务,完整流程为:Service→Service Providers→Service Container
Service(服务类):真正提供服务的类 Service Providers(服务提供商):用于注册服务到Service Container,告诉其如何使用该服务类 Service Container(服务容器):管理类依赖项和执行依赖注入
以系统的服务提供商说明: vender/laravel/framework/src/Illuminate/Cache/CacheServiceProvider.php,其提供了三个服务类(cache,cache.store,memcached.connect)
public function register()
{
$this->app->singleton('cache', function ($app) {
return new CacheManager($app);
});
$this->app->singleton('cache.store', function ($app) {
return $app['cache']->driver();
});
$this->app->singleton('memcached.connector', function () {
return new MemcachedConnector;
});
}当我们使用cache服务类时,服务容器会解析出CacheManager服务类的实例并返回