Yii 依赖注入
DI(依赖注入)容器是一个知道如何实例化和配置对象的对象。Yii通过 yii\di\Container类 提供了DI容器。
它支持以下类型的DI−
- setter和属性注入
- PHP可调用注入
- 构造函数注入
- 控制器动作注入
DI容器通过类型提示支持构造函数注入−
class Object1 {
public function __construct(Object2 object2) {
}
}object1 = container->get('Object1');
// which is equivalent to the following:object2 = new Object2;
object1 = new Object1(object2);
通过配置支持属性注入和setter注入
<?php
use yii\base\Object;
class MyObject extends Object {
public var1;
private_var2;
public function getVar2() {
return this->_var2;
}
public function setVar2(MyObject2var2) {
this->_var2 =var2;
}
}
container->get('MyObject', [], [
'var1' =>container->get('MyOtherObject'),
'var2' => $container->get('MyObject2'),
]);
?>
在PHP可调用注入的情况下,容器将使用已注册的PHP回调函数来构建一个类的新实例−
$container->set('Object1', function () {
$object1 = new Object1(new Object2);
return $object1;
});
$object1 = $container->get('Object1');
控制器动作注入是一种依赖注入(DI)的类型,其依赖关系使用类型提示来声明。这对于使MVC控制器保持精简、轻量级和瘦身非常有用。
public function actionSendToAdmin(EmailValidator validator,email) {
if (validator->validate(email)) {
// sending email
}
}
你可以使用 yii\db\Container::set() 方法注册依赖关系。
<?php
container = new \yii\di\Container;
// register a class name as is. This can be skipped.container->set('yii\db\Connection');
// register an alias name. You can use container->get('MyObject')
// to create an instance of Connectioncontainer->set('MyObject', 'yii\db\Connection');
// register an interface
// When a class depends on the interface, the corresponding class
// will be instantiated as the dependent object
container->set('yii\mail\MailInterface', 'yii\swiftmailer\Mailer');
// register an alias name with class configuration
// In this case, a "class" element is required to specify the classcontainer->set('db', [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=127.0.0.1;dbname = helloworld',
'username' => 'vladimir',
'password' => '12345',
'charset' => 'utf8',
]);
// register a class with configuration. The configuration
// will be applied when the class is instantiated by get()
container->set('yii\db\Connection', [
'dsn' => 'mysql:host=127.0.0.1;dbname = helloworld',
'username' => 'vladimir',
'password' => '12345',
'charset' => 'utf8',
]);
// register a PHP callable
// The callable will be executed each time whencontainer->get('db') is called
container->set('db', function (container, params,config) {
return new \yii\db\Connection(config);
});
// register a component instance
//container->get('pageCache') will return the same instance each time when it
//is called
$container->set('pageCache', new FileCache);
?>
使用DI
步骤1 - 在 组件 文件夹中创建一个名为 MyInterface.php 的文件,其代码如下:
<?php
namespace app\components;
interface MyInterface {
public function test();
}
?>
步骤2 - 在components文件夹中,创建两个文件。
First.php -
<?php
namespace app\components;
use app\components\MyInterface;
class First implements MyInterface {
public function test() {
echo "First class <br>";
}
}
?>
Second.php −
<?php
app\components;
use app\components\MyInterface;
class Second implements MyInterface {
public function test() {
echo "Second class <br>";
}
}
?>
步骤3 − 现在,将一个 actionTestInterface 添加到 SiteController 中。
public function actionTestInterface() {
container = new \yii\di\Container();container->set
("\app\components\MyInterface","\app\components\First");
obj =container->get("\app\components\MyInterface");
obj->test(); // print "First class"container->set
("\app\components\MyInterface","\app\components\Second");
obj =container->get("\app\components\MyInterface");
$obj->test(); // print "Second class"
}
步骤4 - 前往 http://localhost:8080/index.php?r=site/test-interface ,您应该看到以下内容。
这种方法很方便,因为我们可以在一个地方设置类别,其他代码将自动使用新的类别。