依赖注入服务容器(实现控制反转)

 


 

依赖注入

构造函数参数类型注入

 

namespace app\web\controller;


use lib\markdown\Markdown;
use lib\test\Audi;

class Test extends Base
{
    private $markdown;

    public function __construct(Markdown $markdown)
    {
        parent::__construct();
        $this->markdown = $markdown;
    }

    public function index()
    {
        $this->markdown->buildHtml();
    }
}

 

说明:在控制器构造函数里面直接声明了Markdown这个类参数,框架会自动实例化Markdown这个类,并传给构造函数
注意,这里我们没有注册Markdown这个服务

 

举例说明

 

服务提供者

namespace common\provider;


use lib\markdown\Markdown;
use lib\test\Saler;
use lib\test\CarFactory;
use Timo\Core\Container;
use Timo\Support\ServiceProvider;

class CommonProvider extends ServiceProvider
{
    public function register()
    {
        $this->di->singleton([Markdown::class => 'markdown'], Markdown::class);

        $this->di->singleton([Saler::class => 'Saler'], function (Container $di) {
            /** @var CarFactory $carFactory */
            $carFactory = $di->get(CarFactory::class);
            return new Saler($carFactory, '刘慧', '成都');
        });
    }
}

 

控制器

namespace app\cli\controller;


use lib\markdown\Markdown;
use lib\test\Saler;

class Test extends Cli
{
    private $markdown;
    private $saler;

    public function __construct(Markdown $markdown, Saler $saler)
    {
        parent::__construct();
        $this->markdown = $markdown;
        $this->saler = $saler;
    }

    public function container()
    {
        $this->markdown->buildHtml();
        $this->saler->audi();
    }
}

 

一般注入方式

 

namespace app\web\controller;

use lib\test\Audi;

class Test extends Base
{
    public function index()
    {
        $car = $this->di->get('car');
        $car->run();
        
        $audi = $this->di->get(Audi::class);
        $audi->run();
    }
}

 

看见没,上面的car是我们给lib\test\Car取的别名,下面的Audi:class,也就是lib\test\Audi,我们同样也可以取别名

 

$this->di->singleton([Audi::class => 'audi'], function() {
    $car = $this->di->get('car');
    $car->design('Audi A6');
    return new Audi($car);
});

 

然后,就可以这么用了:

 

 

 

$audi = $this->di->get('audi');

 

也可以这样取别名
$this->di->alias(Audi::class, 'audi');
$this->di->alias('lib\test\Audi', 'audi');
上面两个等价的

 

注册方式

 

bind

 

singleton

 

instance

 

将接口绑定到实现

 

首先我们定义一个接口

 

namespace app\contract;


interface Sms
{
    public function send($mobile, $content, $template_id);
}

 

定义具体的sms类

 

namespace lib\alisms;


use app\contract\Sms;

class Client implements Sms
{
    protected $type = 1;

    public function send($mobile, $content, $template_id)
    {
        echo 'aliYun send sms: Mobile->' . $mobile . ' Content->' . $content . '<br>';
    }
}

在控制器中使用

 

在使用之前需要先绑定

 

$this->di->singleton([Sms::class => 'sms'], 'lib\alisms\Client');

 

namespace app\web\controller;


use app\contract\Sms;
use Timo\Core\Controller;

class Test extends Controller
{
    private $sms;

    public function __construct(Sms $sms)
    {
        parent::__construct();
        
        $this->sms = $sms;
    }
 
    public function run()
    {
        $this->sms->send('13800000008', 'Hello TimoPHP', 1009);
    }
}