# 简介
服务提供者是 Laravel 应用启动的中心,你自己的应用以及所有 Laravel 的核心服务都是通过服务提供者启动。
但是,我们所谓的“启动”指的是什么?通常,这意味着注册服务,包括注册服务容器绑定、事件监听器、中间件甚至路由。服务提供者是应用配置的中心。
如果你打开 Laravel 自带的 `config/app.php` 文件,将会看到一个 `providers` 数组,这里就是应用所要加载的所有服务提供者类,当然,其中很多是延迟加载的,也就是说不是每次请求都会被加载,只有真的用到它们的时候才会加载。
通过本文档,你将会学习如何编写自己的服务提供者并在 Laravel 应用中注册它们。
# 编写服务提供者
所有的服务提供者都继承自 `Illuminate\Support\ServiceProvider` 类。大部分服务提供者都包含两个方法: `register` 和 `boot` 。在 `register` 方法中,你唯一要做的事情就是绑定服务到`服务容器`,不要尝试在该方法中注册事件监听器,路由或者任何其它功能。
通过 Artisan 命令 `make:provider` 即可生成一个新的提供者:
~~~
php artisan make:provider RiakServiceProvider
~~~
## register 方法
正如前面所提到的,在 `register` 方法中只绑定服务到`服务容器`,而不要做其他事情,否则,一不小心就可能用到一个尚未被加载的服务提供者提供的服务。
现在让我们来看看一个基本的服务提供者长什么样:
~~~
<?php
namespace App\Providers;
use Riak\Connection;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider{
/**
* 在容器中注册绑定.
*
* @return void
*/
public function register()
{
$this->app->singleton(Connection::class, function ($app) {
return new Connection(config('riak'));
});
}
}
~~~
该服务提供者只定义了一个 `register` 方法,并使用该方法在服务容器中定义了一个 `Riak\Connection` 的实现。如果你不知道服务容器是如何工作的,请参考`其文档`。
**`bindings` 和 `singletons` 属性**
如果你的服务提供者注册了很多简单的绑定,你可能希望使用 `bindings` 和 `singletons` 属性来替代手动注册每个容器绑定以简化代码。当服务提供者被框架加载后,会自动检查这些属性并注册相应绑定:
~~~
<?php
namespace App\Providers;
use App\Contracts\ServerProvider;
use App\Contracts\DowntimeNotifier;
use Illuminate\Support\ServiceProvider;
use App\Services\PingdomDowntimeNotifier;
use App\Services\DigitalOceanServerProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* All of the container bindings that should be registered.
*
* @var array
*/
public $bindings = [
ServerProvider::class => DigitalOceanServerProvider::class,
];
/**
* All of the container singletons that should be registered.
*
* @var array
*/
public $singletons = [
DowntimeNotifier::class => PingdomDowntimeNotifier::class,
];
}
~~~
boot 方法
如果我们想要在服务提供者中注册视图 composer 该怎么做?这就要用到 `boot` 方法了。该方法在所有服务提供者被注册以后才会被调用,这就是说我们可以在其中访问框架已注册的所有其它服务:
~~~
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
view()->composer('view', function () {
//
});
}
}
~~~
boot 方法的依赖注入
我们可以在 `boot` 方法中对依赖进行类型提示,`服务容器`会自动注入你所需要的依赖:
~~~
use Illuminate\Contracts\Routing\ResponseFactory;
public function boot(ResponseFactory $response){
$response->macro('caps', function ($value) {
//
});
}
~~~
# 注册服务提供者
所有服务提供者都是通过配置文件 `config/app.php` 中进行注册,该文件包含了一个列出所有服务提供者名字的 `providers` 数组,默认情况下,其中列出了所有核心服务提供者,这些服务提供者启动 Laravel核心组件,比如邮件、队列、缓存等等。
要注册你自己的服务提供者,只需要将其追加到该数组中即可:
~~~
'providers' => [
// 其它服务提供者
App\Providers\ComposerServiceProvider::class,
],
~~~
# 延迟加载服务提供者
如果你的提供者仅仅只是在`服务容器`中注册绑定,你可以选择延迟加载该绑定直到注册绑定的服务真的需要时再加载,延迟加载这样的一个提供者将会提升应用的性能,因为它不会在每次请求时都从文件系统加载。
Laravel 编译并保存所有延迟服务提供者提供的服务及服务提供者的类名。然后,只有当你尝试解析其中某个服务时 Laravel 才会加载其服务提供者。
想要延迟加载一个提供者,设置 `defer` 属性为 `true` 并定义一个 `provides` 方法,该方法返回该提供者注册的服务容器绑定:
~~~
<?php
namespace App\Providers;
use Riak\Connection;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider{
/**
* 服务提供者加是否延迟加载.
*
* @var bool
*/
protected $defer = true;
/**
* 注册服务提供者
*
* @return void
*/
public function register()
{
$this->app->singleton(Connection::class, function ($app) {
return new Connection($app['config']['riak']);
});
}
/**
* 获取由提供者提供的服务.
*
* @return array
*/
public function provides()
{
return [Connection::class];
}
}
~~~
> 注:强烈推荐阅读[深入理解控制反转(IoC)和依赖注入(DI)](https://www.wandhi.com/post-865.html)深入理解服务容器和服务提供者的实现原理。
- 序言
- 新版特性
- 快速入门
- 升级指南
- 贡献指南
- API文档
- 安装配置
- 目录结构
- Homestead
- Valet
- 部署
- 核心概念
- 请求生命周期
- 服务容器
- 服务提供者
- 门面(Facades)
- 契约(Contracts)
- 框架基础
- 路由
- 中间件
- CSRF 保护
- 控制器
- 请求
- 响应
- 视图
- 生成 URL
- Session
- 验证
- 错误处理
- 日志
- 前端开发
- Blade 模板
- 本地化
- 前端脚手架
- 编译前端资源(Laravel Mix)
- 安全系列
- 登录认证
- API 认证
- 授权
- 加密
- 哈希
- 重置密码
- 进阶系列
- Artisan 控制台
- 集合
- 广播
- 缓存
- 事件
- 文件存储
- 辅助函数
- 邮件
- 通知
- 扩展包开发
- 队列
- 任务调度
- 数据库操作
- 快速入门
- 查询构建器
- 分页
- 迁移
- 数据填充
- Redis
- Eloquent ORM
- 快速入门
- 关联关系
- 集合
- 访问器 & 修改器
- API 资源类
- 序列化
- 应用测试
- 快速入门
- HTTP 测试
- 浏览器测试
- 数据库测试
- 模拟
- 官方扩展包
- Cashier(订阅支付解决方案)
- Envoy(远程操作解决方案)
- Horizon(队列系统解决方案)
- Passport(API 认证解决方案)
- Scout(全文搜索解决方案)
- Socialite(第三方登录解决方案)
- 相关下载
- Laravel 5.6 中文文档离线版
- Laravel 5.6 一键安装包