https://laravel.com/docs/5.8 翻译成中文
契约contracts(定义接口)
facades(门面模式) 可静态代用的封装
服务提供者(注册服务 服务组件) 解析服务
服务容器($app)
加载流程(请求周期)https://learnku.com/docs/laravel/5.6/lifecycle/1358
模仿。参考框架复杂逻辑的实现方案。
Laravel 中的许多类型的类都是通过 服务容器 解析出来的,包括控制器、事件监听器、中间件、任务队列,甚至路由闭包。所以说,要获得一个契约的实现,你只需要被解析的类的构造函数中添加「类型提示」即可。
Facades Vs. 依赖注入
Facades Vs. 函数
服务提供器是所有 Laravel 应用程序引导中心。你的应用程序以及 Laravel 的所有核心服务都是通过服务提供器进行引导。
服务提供器 我们说的「引导」其实是指注册,比如注册服务容器绑定、事件监听器、中间件,甚至是路由的注册。服务提供器是配置你的应用程序的中心。
注册服务提供器。 用register方法 。或者如果你的服务提供商注册许多简单的绑定,你可能想使用 bindings 和 singletons 属性而不是手动注册每个容器绑定。当服务提供者被框架加载时,它将自动检查这些属性并注册它们的绑定:。 在你的任何服务提供器方法中,你可以通过 $app 属性来访问服务容器。
服务提供器都在 config/app.php 配置文件中注册。该文件中有一个 providers 数组,用于存放服务提供器的类名 。要注册提供器,只需要将其添加到数组:
注册组件。(组件各种服务的集合)
在 boot 方法中完成。 此方法在所有其他服务提供器都注册之后才能调用,这意味着你可以访问已经被框架注册的所有服务:
(引导方法依赖注入)你可以为服务提供器的 boot 方法设置类型提示。服务容器 会自动注入你需要的任何依赖项:
延迟提供器
要延迟提供器的加载,请将 defer 属性设置为 true ,并定义 provides 方法。provides 方法应该返回由提供器注册的服务容器绑定:
在真正工程师的生活中,coding 应该基本上只占 20% —— 因为最终代码是用来表达思想的,用来解决问题的;
是用于管理类的依赖和执行依赖注入的工具。依赖注入这个花俏名词实质上是指:类的依赖项通过构造函数,或者某些情况下通过「setter」方法「注入」到类中。
绑定:几乎所有服务容器绑定操作都是在 服务提供器 中注册的
如果类没有依赖任何接口,就没有必要将类绑定到容器中。容器不需要指定如何构建这些对象,因为它可以使用反射自动解析这些对象。
在服务提供器中,你可以通过 $this->app 属性访问容器。我们可以通过 bind 方法注册绑定
传递我们想要注册的类或接口名称 和 返回类的实例的 Closure :
$this->app->bind('HelpSpot\API', function ($app) {
return new HelpSpot\API($app->make('HttpClient'));
});
绑定一个单例
singleton 方法将类或接口绑定到只能解析一次的容器中。绑定的单例被解析后,相同的对象实例会在随后的调用中返回到容器中:
$this->app->singleton('HelpSpot\API', function ($app) {
return new HelpSpot\API($app->make('HttpClient'));
});
绑定实例
你也可以使用 instance 方法将现有对象实例绑定到容器中。给定的实例会始终在随后的调用中返回到容器中:
$api = new HelpSpot\API(new HttpClient);
$this->app->instance('HelpSpot\API', $api);
绑定接口到实现
服务容器有一个强大的功能,就是将接口绑定到给定实现。例如,如果我们有一个 EventPusher 接口和一个 RedisEventPusher 实现。编写完接口的 RedisEventPusher 实现后,我们就可以在服务容器中注册它,像这样:
$this->app->bind(
'App\Contracts\EventPusher',
'App\Services\RedisEventPusher'
);
上下文绑定
有时候,你可能有两个类使用了相同的接口,但你希望每个类都能注入不同的实现。例如,两个控制器可能需要依赖不同的 Illuminate\Contracts\Filesystem\Filesystem 契约 实现。 Laravel 提供了一个简单、优雅的接口来定义这个行为:
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\PhotoController;
use App\Http\Controllers\VideoController;
use Illuminate\Contracts\Filesystem\Filesystem;
$this->app->when(PhotoController::class)
->needs(Filesystem::class)
->give(function () {
return Storage::disk('local');
});
$this->app->when(VideoController::class)
->needs(Filesystem::class)
->give(function () {
return Storage::disk('s3');
});
你可以使用 make 方法将容器中的类实例解析出来。make 方法接受要解析的类或接口的名称:
$api = $this->app->make('HelpSpot\API');
如果你的代码处于不能访问 $app 变量的位置,你可以使用全局的辅助函数 resolve:
$api = resolve('HelpSpot\API');
如果你的某些类的依赖项不能通过容器去解析,那你可以通过将它们作为关联数组传递到 makeWith 方法来注入它们。
$api = $this->app->makeWith('HelpSpot\API', ['id' => 1]);
自动注入
你可以简单地使用「类型提示」的方式在由容器解析的类的构造函数中添加依赖项,包括 控制器、监听事件、队列任务、中间件 等。 事实上,这是你的大多数对象也应该由容器解析。
例如,你可以在控制器的构造函数中对应用程序定义的 Repository 使用类型提示。Repository 会被自动解析并注入到类中:
容器事件
每当服务容器解析一个对象时触发一个事件。你可以使用 resolving 方法监听这个事件:
$this->app->resolving(function ($object, $app) {
// Called when container resolves object of any type...
});
$this->app->resolving(HelpSpot\API::class, function ($api, $app) {
// Called when container resolves objects of type "HelpSpot\API"...
});
Application.php
/**
* Register all of the configured providers.
*
* @return void
*/
public function registerConfiguredProviders()
{
$providers = Collection::make($this->config['app.providers'])
->partition(function ($provider) {
return Str::startsWith($provider, 'Illuminate\\');
});
$providers->splice(1, 0, [$this->make(PackageManifest::class)->providers()]);
(new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
->load($providers->collapse()->toArray());
}
最重要的内核引导操作之一是加载应用程序的 服务提供器 。应用程序的所有服务提供器都在 config/app.php 配置文件的 providers 数组中配置。首先,所有提供器都会调用 register 方法,接着,由 boot 方法负责调用所有被注册提供器。
服务提供器负责引导所有框架的各种组件,如数据库、队列、验证和路由组件。也就是说,框架提供的每个功能都由它们来引导并配置。因此也可以说,服务提供器是整个 Laravel 引导过程中最重要的方面。
HTTP 内核的 handle 方法的方法签名非常简单:接收 Request 并返回 Response 。可以把内核当作是代表整个应用程序的大黑盒,给它 HTTP 请求,它就返回 HTTP 响应。