您好,欢迎访问一九零五行业门户网

聊聊laravel中的Service Container

[laravel]唠唠service container什么是service containerthe laravel service container is a powerful tool for managing class dependencies and performing dependency injection.
从laravel官方文档对于service container的解释可以看出,它的作用就是帮助我们管理和进行依赖注入的。
为什么要用service container在《依赖注入》中,我们看到使用依赖注入可以极大的降低代码的耦合度,但是也带来了一个缺点,就是需要自己管理注入的对象。
如果一个组件有很多依赖,我们需要创建多个参数的setter方法来传递依赖关系,或者建立一个多个参数的构造函数来传递它们,另外在使用组件前还要每次都创建依赖,这让我们的代码像这样不易维护。
所以为依赖实例提供一个容器(service container),就是一个实用而且优雅的方法。
比如下面是laravel的入口文件(已去掉注释):
// public/index.php<?phprequire __dir__.'/../bootstrap/autoload.php';$app = require_once __dir__.'/../bootstrap/app.php';$kernel = $app->make(illuminate\contracts\http\kernel::class);$response = $kernel->handle(    $request = illuminate\http\request::capture());$response->send();$kernel->terminate($request, $response);
// bootstrap/app.php<?php$app = new illuminate\foundation\application( realpath(__dir__.'/../'));$app->singleton(    illuminate\contracts\http\kernel::class,    app\http\kernel::class);$app->singleton(    illuminate\contracts\console\kernel::class,    app\console\kernel::class);$app->singleton(    illuminate\contracts\debug\exceptionhandler::class,    app\exceptions\handler::class);return $app;
首先看bootstrap/app.php,其中$app是illuminate\foundation\application的一个实例,而illuminate\foundation\application类继承自container,所以$app实际上就是一个service container。
然后下面的三个singleton方法定义了当依赖illuminate\contracts\http\kernel、illuminate\contracts\console\kernel、illuminate\contracts\debug\exceptionhandler这三个接口时,注入哪个类的单例。
然后看public/index.php,其中的make方法实际上就是用service container来new一个illuminate\contracts\http\kernel实例,跟普通new的区别就是会把他的依赖自动注入进去。
是不是很简洁?
其实不单是laravel,像yii2、phalcon等框架都通过实现容器来管理依赖注入。
如何使用service container既然是一个容器,无非就是两个事,往里放东西和往外取东西,对应到service container就是绑定(binding)和解析(resolving)。
获得容器在laravel的service provider中,可以通过$this->app获取容器,除此之外,还可以使用app()来获取容器。
如果在laravel外使用service container,直接new一个illuminate\container\container就可以获得容器了。
以下都用$container代表获取到的容器。
绑定绑定返回接口的实例
//使用闭包$container->bind('barinterface', function(){    return new bar();});//或者使用字符串$container->bind('foointerface', 'foo');
绑定单例
singletion 方法绑定一个只会被解析一次的类或接口至容器中,且后面的调用都会从容器中返回相同的实例:
$container->singleton('barinterface', function(){    return new bar();});
绑定实例
你也可以使用 instance 方法,绑定一个已经存在的对象实例至容器中。后面的调用都会从容器中返回指定的实例:
$bar = new bar();$bar->setsomething(new something);$container->instance('bar', $bar);
情境绑定
有时候,你可能有两个类使用到相同接口,但你希望每个类都能注入不同实现。
$container->when('man')          ->needs('partnerinterface')          ->give('woman');$container->when('woman')          ->needs('partnerinterface')          ->give('man');
标记
有些时候,可能需要解析某个「分类」下的所有绑定。
$container->bind('father', function () {    //});$container->bind('mother', function () {    //});$container->bind('daughter', function () {    //});$container->bind('son', function () {    //});$container->tag(['father', 'mother', 'daughter', 'son'], 'familymembers');$container->bind('family', function ($container) {    return new family($container->tagged('familymembers'));});
解析make方法
$foo = $container->make('foo');
数组方法
$bar = $container['bar'];
解析被标记绑定
$familymembers = $container->tagged('familymembers');foreach ($familymembers as $inpidual) {    $inpidual->dosomething();}
解析事件每当服务容器解析一个对象时就会触发事件。你可以使用 resolving 方法监听这个事件。
$container->resolving(function ($object, $container) {    // 当容器解析任何类型的对象时会被调用...});$container->resolving('foo', function (foo $foo, $container) {    // 当容器解析「foo」类型的对象时会被调用...});
相关推荐:最新的五个laravel视频教程
以上就是聊聊laravel中的service container的详细内容。
其它类似信息

推荐信息