Контейнер DI (внедрение зависимости) — это объект, который знает, как создавать и настраивать объекты. Yii предоставляет контейнер DI через класс yii \ di \ Container .
Он поддерживает следующие виды DI —
- Сеттер и внедрение свойства
- 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);
Инъекции свойств и сеттеров поддерживаются через конфигурации —
<?php use yii\base\Object; class MyObject extends Object { public $var1; private $_var2; public function getVar2() { return $this->_var2; } public function setVar2(MyObject2 $var2) { $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 Connection $container->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 class $container->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 when $container->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 — Внутри папки компонентов создайте два файла.
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, вы должны увидеть следующее.
Этот подход удобен тем, что мы можем установить классы в одном месте, а другой код будет автоматически использовать новые классы.