依赖注入服务容器(实现控制反转)
依赖注入
构造函数参数类型注入
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->container->singleton([Markdown::class => 'markdown'], Markdown::class);
$this->container->singleton([Saler::class => 'Saler'], function (Container $container) {
/** @var CarFactory $carFactory */
$carFactory = $container->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->container->get('car');
$car->run();
$audi = $this->container->get(Audi::class);
$audi->run();
}
}
看见没,上面的car是我们给lib\test\Car取的别名,下面的Audi:class,也就是lib\test\Audi,我们同样也可以取别名
$this->container->singleton([Audi::class => 'audi'], function() {
$car = $this->container->get('car');
$car->design('Audi A6');
return new Audi($car);
});
然后,就可以这么用了:
$audi = $this->container->get('audi');
也可以这样取别名
$this->container->alias(Audi::class, 'audi');
$this->container->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->container->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);
}
}