laravel中的 service container
laravel 中的service container 是管理类依赖注入和执行类依赖注入的工具
依赖注入这个名词实际上是指: 类的依赖通过构造函数,或者某些情况下通过setter方法来注入到类中,如下所示.
<?php
namespace App\Http\Controllers;
use App\User;
use App\Repositories\UserRepository;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
protected $users;
//这个地方依赖注入构造函数中,并把实例化的对象挂在类已经声明好的属性上.
public function __construct(UserRepository $users)
{
$this->users = $users;
}
//num2 第二种写法 当我们需要实例化整个controller对象时 此时不传值可能会导致报错 我们可以不依赖注入 选择在构造函数中实例化对象,只不过这样显得麻烦些.
public function __construct()
{
$this->users =new UserRepository();
}
public function show($id)
{
$user = $this->users->find($id);
return view('user.profile', ['user' => $user]);
}
}
在这个例子中,控制器 Usercontroller 需要从数据源获取users 因此,我们要注入可以获取users的服务. 在这种情况下, UserRepository 可能是使用 Eloquent 从数据库中获取user信息 因为Repository是通过UserRepository 注入的, 所以我们可以轻易的将其切换为另一个实现.
想要构建强大的大型应用, 至关重要的一件事是:要深刻理解laravel service container 的原理.
2.绑定
如何绑定一个服务到 service container? 请看以下代码.
//在服务提供器中 通过$this->app 属性访问容器. 传递我们想要注册的类 或接口名称再返回类的实例直接到container中
$this->app->bind('HelpSpot\API',function($app){
return new HelpSpot\API($app->make('HttpClient'));
});
laravel 接受容器本身作为解析器的参数. 然后,我们可以使用容器来解析正在构建的对象的子依赖.
绑定一个单例子
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);
解析实例:
make 方法
你可以使用make 方法将容器中的类实例解析出来. make 方法接受要解析的类或接口的名称:
$api =$this->app->make('HelpSpot\API');
如果你的代码处于不能访问$app 变量的位置 你可以使用全局的辅助函数resolve
$api =resolve('HelpSpot\API');
自动注入:
你可以简单的使用类型提示的方式在由容器解析的类的构造函数中添加依赖项,包括控制器,监听时间,队列任务,中间件等.事实上,这是你的大多数对象也应该由容器解析.
例如,你可以在控制器的构造函数中对应用程序定义的Repository使用类型提示,Repository会被自动解析并注入到类中:
<?php
namespace App\Http\Controllers;
use App\Users\Repository as UserRepository;
class UserController extends Controller
{
/**
* UserRepository 的实例对象
*/
protected $users;
/**
* 控制器的构造函数
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
/**
* 显示 ID 对应的用户
*
* @param int $id
* @return Response
*/
public function show($id)
{
$user =$this->users->findOrFail($id);
}
}
以上其实很多是文档的内容,文档有很多坑爹的地方首先看以下代码:
$this->app->bind('HelpSpot\API', function ($app) {
return new HelpSpot\API($app['HttpClient']);
});
//是不是看不大懂?再看以下代码:
//文档里的只是告诉你 我解析一个类的时候可以再注入一个其他类的实例,不得不说这个例子实在太不靠谱
//给一个接口起个别名
$this->app->bind('event_pusher', function ($app) {
return new App\Contracts\EventPusher;
});
//指定这个接口应该解析的实例
$this->app->bind('App\Contracts\EventPusher', 'App\Services\RedisEventPusher');
//这样是不是很清晰 明了?
//这时我要解析EventPusher可以这么做
$this->app->make(event_pusher);
我对service container 的理解还不是特别的深刻 通过详细阅读相关文档资料有了一个大概的概念.
我想通过具体的项目实现可以加深我的理解.
这个人暂时没有 freestyle