Laravel Core Theories
官方文档项目 https://github.com/laravel/docs
providers.md https://laravel.com/docs/5.6/providers
container.md https://laravel.com/docs/5.6/container
Laravel 的核心就是一个 IoC 容器,该容器提供了整个框架中需要的一系列服务。在官方架构概念文档 Architecture Concepts 中提到五个重点:
✓ Request Lifecycle
✓ Service Container
✓ Service Providers
✓ Facades
✓ Contracts
核心的概念有 Service Container
、Service Provider
、Facades
以及 Contracts
,这几个核心的概念相互交织,协同工作,构成了 Laravel 开发框架的基石,让我们能够更高效的进行 Larave 开发。
✓ Facades
外观模式
相当代理模式,从偷懒的角度,别名而已,少敲几个字。另外一个好处是方便的自定义,直接修改 config/app.php
里的 aliases 部分即可。在 Laravel 里的作用其实就跟 PHP 的 class_alias
的作用类似,把框架里带命名空间 namespace 的类变得更好记,比如:
App => Illuminate\Support\Facades\App
在 Laravel 应用中,一个 facade 就是一个提供访问容器中对象的类,实现 Illuminate\Support\Facades\Facade
基础抽象类。Facade 基类使用 __callStatic()
魔术方法在你的 Facades 中延迟调用容器中对应对象的方法。
当然外观还有一些其它的好处,也有它的弊端,比如无法直接访问真正目标对象的类常量,因为 Facades 是通过 PHP 的 __callStatic()
这个魔术方法实现的。
✓ Contracts
锲约
是指框架提供的一系列定义核心服务的接口,比如缓存,队列,日志的接口,契约就是接口 interface。它用来实现松耦合,当系统升级,需要对一种实现进行修改时,如 Memcached 需要升级到 Redis,能够不对代码库进行修改,只需要对配置进行修改就能完成升级的时候就算是松耦合了!
✓ Service Container
IoC(Inversion Of Control)控制反转,是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。IoC 容器则是实现这种设计的一种模式,Factory 模式也能实现 IoC。
IoC 容器会根据类的依赖需求,自动在注册、绑定的一堆实例中搜寻符合的依赖需求,并自动注入到构造函数参数中去。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。这就是依赖注入(Dependency Injection, DI)。依赖注入实质上是指:类的依赖通过构造器或在某些情况下通过「setter」方法进行「注入」。这里结合 TypeScript 列子来解释:
class World {
dog = new Dog();
run(){
this.dog.barking();
}
}
class Dog {
barking(){
console.log("Wang...Wang...Wang...Wang...");
}
}
new World().run();
这段代码模拟了一个世界,世界运行时会有一条狗在吠。现在想改一下需求,增加一只猫,让它跳一跳。对于这个列子,需要修改核心世界的代码,这就时高耦合的体现。如果这个世界就是一个框架,那么开发者就不能再不修改核心的情况下进行扩展。这就是高耦合的致命缺点,现在引入 IoC 模式来改造它,依赖迁移到外部,核心部分负责指定接口规范:
class World {
dog = new Dog();
run( it:Animal ){
console.log(it.type);
it.act();
return this;
}
}
interface Animal {
readonly type:String;
act():boolean;
}
class Dog implements Animal {
type = "Dog";
act(){
console.log("Wang...Wang...");
return true;
}
}
class Cat implements Animal {
type = "Cat";
act(){
console.log("Jump...");
return true;
}
}
new World().run(new Dog()).run(new Cat());
通过改造,核心部分包括了 World
框架和 Animal
接口规范,而 Dog
、Cat
则需要按规范进行扩展,只要遵循这个接口规范即可。当然 Laravel 的 IoC 容器设计没有这么简单,它还使用了 PHP 的反射技术。
对于每一个 ServiceProvider
,框架运行时会调用 register()
方法完成该服务的注册,然后执行引导方法 boot()
。
在 ServiceProvider
内部通过 $this->app
来访问整个应用的服务容器实例,通过服务容器 bind()
方法绑定 ServiceProvider
或接口,其它绑定方式有 instance()
实例、singleton()
等。
$this->app->bind('post', function ($app) {
return new App\Models\Post;
});
以下两行等效代码实例化 ServiceProvider:
$app->make('App\Models\Post');
$app->make('post');
再实列化过程,resolve()
全局函数会负责定位到类定文件。通过 PHP 反射技术,Laravel 可以做自动依赖注入,如在控制器的构造函数中显式声明了参数的类型即具有 type-hit
类型提醒功能。容器通过 resolve()
解析到它时就知道需要实例化什么类型的对象并传入到构造器中:
public function __construct(UserRepository $users)
{
$this->users = $users;
}
可以自动依赖注入的不局限于控制器,还有 event listeners, queue jobs, middleware 等等。
✓ Service Provider
服务提供者 Provider 就是实现依赖的部分,实现 \Illuminate\Support\ServiceProvider
基础抽象类,
register()
方法注入容器就实现了完整功能
boot()
引导方法也就是依赖注入方法
Laravel 中,包括应用程序,以及所有的核心服务,都是通过 Provider 引导的。所谓的「引导」指的是注册事务,包括注册服务容器绑定,事件监听器,中间件,甚至路由。
所有服务提供者都在 config/app.php
配置文件中注册。可以选择推迟服务提供者的注册,直到真正需要注册绑定时,这样可以提供应用程序的性能。