登录  /  注册
首页 > php框架 > Laravel > 正文

聊聊laravel中的Service Container

藏色散人
发布: 2021-07-26 15:53:46
转载
2122人浏览过

什么是Service Container

the 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
<?php require __DIR__.&#39;/../bootstrap/autoload.php&#39;;

$app = require_once __DIR__.&#39;/../bootstrap/app.php&#39;;

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel-&gt;handle(
    $request = Illuminate\Http\Request::capture()
);

$response-&gt;send();

$kernel-&gt;terminate($request, $response);
登录后复制
// bootstrap/app.php
<?php $app = new Illuminate\Foundation\Application(
    realpath(__DIR__.&#39;/../&#39;)
);

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

$app-&gt;singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app-&gt;singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

return $app;
登录后复制

首先看bootstrap/app.php,其中$appIlluminate\Foundation\Application的一个实例,而Illuminate\Foundation\Application类继承自Container,所以$app实际上就是一个Service Container。
然后下面的三个singleton方法定义了当依赖Illuminate\Contracts\Http\KernelIlluminate\Contracts\Console\KernelIlluminate\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-&gt;app获取容器,除此之外,还可以使用app()来获取容器。
如果在Laravel外使用Service Container,直接new一个Illuminate\Container\Container就可以获得容器了。

以下都用$container代表获取到的容器。

绑定

  • 绑定返回接口的实例

//使用闭包
$container-&gt;bind('BarInterface', function(){
    return new Bar();
});
//或者使用字符串
$container-&gt;bind('FooInterface', 'Foo');
登录后复制
  • 绑定单例

singletion 方法绑定一个只会被解析一次的类或接口至容器中,且后面的调用都会从容器中返回相同的实例:

$container-&gt;singleton('BarInterface', function(){
    return new Bar();
});
登录后复制
  • 绑定实例

你也可以使用 instance 方法,绑定一个已经存在的对象实例至容器中。后面的调用都会从容器中返回指定的实例:

$bar = new Bar();
$bar-&gt;setSomething(new Something);

$container-&gt;instance('Bar', $bar);
登录后复制
  • 情境绑定

有时候,你可能有两个类使用到相同接口,但你希望每个类都能注入不同实现。

$container-&gt;when('Man')
          -&gt;needs('PartnerInterface')
          -&gt;give('Woman');
$container-&gt;when('Woman')
          -&gt;needs('PartnerInterface')
          -&gt;give('Man');
登录后复制
  • 标记

有些时候,可能需要解析某个「分类」下的所有绑定。

$container-&gt;bind('Father', function () {
    //
});
$container-&gt;bind('Mother', function () {
    //
});
$container-&gt;bind('Daughter', function () {
    //
});
$container-&gt;bind('Son', function () {
    //
});
$container-&gt;tag(['Father', 'Mother', 'Daughter', 'Son'], 'familyMembers');

$container-&gt;bind('Family', function ($container) {
    return new Family($container-&gt;tagged('familyMembers'));
});
登录后复制

解析

  • make方法

$foo = $container-&gt;make('Foo');
登录后复制
  • 数组方法

$bar = $container['Bar'];
登录后复制
  • 解析被标记绑定

$familyMembers = $container-&gt;tagged('familyMembers');

foreach ($familyMembers as $inpidual) {
    $inpidual-&gt;doSomething();
}
登录后复制

解析事件

每当服务容器解析一个对象时就会触发事件。你可以使用 resolving 方法监听这个事件。

$container-&gt;resolving(function ($object, $container) {
    // 当容器解析任何类型的对象时会被调用...
});

$container-&gt;resolving('Foo', function (Foo $foo, $container) {
    // 当容器解析「Foo」类型的对象时会被调用...
});
登录后复制

相关推荐:最新的五个Laravel视频教程

以上就是聊聊laravel中的Service Container的详细内容,更多请关注php中文网其它相关文章!

智能AI问答
PHP中文网智能助手能迅速回答你的编程问题,提供实时的代码和解决方案,帮助你解决各种难题。不仅如此,它还能提供编程资源和学习指导,帮助你快速提升编程技能。无论你是初学者还是专业人士,AI智能助手都能成为你的可靠助手,助力你在编程领域取得更大的成就。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
最新问题
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号