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


依赖注入

构造函数参数类型注入

  1. namespace app\web\controller;
  2. use lib\markdown\Markdown;
  3. use lib\test\Audi;
  4. class Test extends Base
  5. {
  6. private $markdown;
  7. public function __construct(Markdown $markdown)
  8. {
  9. parent::__construct();
  10. $this->markdown = $markdown;
  11. }
  12. public function index()
  13. {
  14. $this->markdown->buildHtml();
  15. }
  16. }

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

举例说明

服务提供者

  1. namespace common\provider;
  2. use lib\markdown\Markdown;
  3. use lib\test\Saler;
  4. use lib\test\CarFactory;
  5. use Timo\Core\Container;
  6. use Timo\Support\ServiceProvider;
  7. class CommonProvider extends ServiceProvider
  8. {
  9. public function register()
  10. {
  11. $this->container->singleton([Markdown::class => 'markdown'], Markdown::class);
  12. $this->container->singleton([Saler::class => 'Saler'], function (Container $container) {
  13. /** @var CarFactory $carFactory */
  14. $carFactory = $container->get(CarFactory::class);
  15. return new Saler($carFactory, '刘慧', '成都');
  16. });
  17. }
  18. }

控制器

  1. namespace app\cli\controller;
  2. use lib\markdown\Markdown;
  3. use lib\test\Saler;
  4. class Test extends Cli
  5. {
  6. private $markdown;
  7. private $saler;
  8. public function __construct(Markdown $markdown, Saler $saler)
  9. {
  10. parent::__construct();
  11. $this->markdown = $markdown;
  12. $this->saler = $saler;
  13. }
  14. public function container()
  15. {
  16. $this->markdown->buildHtml();
  17. $this->saler->audi();
  18. }
  19. }

一般注入方式

  1. namespace app\web\controller;
  2. use lib\test\Audi;
  3. class Test extends Base
  4. {
  5. public function index()
  6. {
  7. $car = $this->container->get('car');
  8. $car->run();
  9. $audi = $this->container->get(Audi::class);
  10. $audi->run();
  11. }
  12. }
  1. 看见没,上面的car是我们给lib\test\Car取的别名,下面的Audi:class,也就是lib\test\Audi,我们同样也可以取别名
  1. $this->container->singleton([Audi::class => 'audi'], function() {
  2. $car = $this->container->get('car');
  3. $car->design('Audi A6');
  4. return new Audi($car);
  5. });

然后,就可以这么用了:

  1. $audi = $this->container->get('audi');
  1. 也可以这样取别名
  2. $this->container->alias(Audi::class, 'audi');
  3. $this->container->alias('lib\test\Audi', 'audi');
  4. 上面两个等价的

注册方式

bind

singleton

instance

将接口绑定到实现

首先我们定义一个接口

  1. namespace app\contract;
  2. interface Sms
  3. {
  4. public function send($mobile, $content, $template_id);
  5. }

定义具体的sms类

  1. namespace lib\alisms;
  2. use app\contract\Sms;
  3. class Client implements Sms
  4. {
  5. protected $type = 1;
  6. public function send($mobile, $content, $template_id)
  7. {
  8. echo 'aliYun send sms: Mobile->' . $mobile . ' Content->' . $content . '<br>';
  9. }
  10. }

在控制器中使用

在使用之前需要先绑定

  1. $this->container->singleton([Sms::class => 'sms'], 'lib\alisms\Client');
  1. namespace app\web\controller;
  2. use app\contract\Sms;
  3. use Timo\Core\Controller;
  4. class Test extends Controller
  5. {
  6. private $sms;
  7. public function __construct(Sms $sms)
  8. {
  9. parent::__construct();
  10. $this->sms = $sms;
  11. }
  12. public function run()
  13. {
  14. $this->sms->send('13800000008', 'Hello TimoPHP', 1009);
  15. }
  16. }