Yii – Dependency Injection


Yii – Dependency Injection


”;


A DI(dependency injection) container is an object that knows how to instantiate and configure objects. Yii provides the DI container via the yiidiContainer class.

It supports the following kinds of DI −

  • Setter and property injection
  • PHP callable injection
  • Constructor injection
  • Controller action injection

The DI container supports constructor injection with the help of type hints −

class Object1 {
   public function __construct(Object2 $object2) {

   }
}
$object1 = $container->get(''Object1'');
// which is equivalent to the following:
$object2 = new Object2;
$object1 = new Object1($object2);

Property and setter injections are supported through configurations −

<?php
   use yiibaseObject;
   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''),
   ]);
?>

In case of the PHP callable injection, the container will use a registered PHP callback to build new instances of a class −

$container->set(''Object1'', function () {
   $object1 = new Object1(new Object2);
   return $object1;
});
$object1 = $container->get(''Object1'');

Controller action injection is a type of DI where dependencies are declared using the type hints. It is useful for keeping the MVC controllers slim light-weighted and slim −

public function actionSendToAdmin(EmailValidator $validator, $email) {
   if ($validator->validate($email)) {
      // sending email
   }
}

You can use the yiidbContainer::set() method to register dependencies −

<?php
   $container = new yiidiContainer;
   // register a class name as is. This can be skipped.
   $container->set(''yiidbConnection'');
   // register an alias name. You can use $container->get(''MyObject'')
   // to create an instance of Connection
   $container->set(''MyObject'', ''yiidbConnection'');
   // register an interface
   // When a class depends on the interface, the corresponding class
   // will be instantiated as the dependent object
   $container->set(''yiimailMailInterface'', ''yiiswiftmailerMailer'');
   // register an alias name with class configuration
   // In this case, a "class" element is required to specify the class
   $container->set(''db'', [
      ''class'' => ''yiidbConnection'',
      ''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(''yiidbConnection'', [
      ''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 yiidbConnection($config);
   });
   // register a component instance
   // $container->get(''pageCache'') will return the same instance each time when it 
      //is called
   $container->set(''pageCache'', new FileCache);
?>

Using the DI

Step 1 − Inside the components folder create a file called MyInterface.php with the following code.

<?php
   namespace appcomponents;
   interface MyInterface {
      public function test();
   }
?>

Step 2 − Inside the components folder, create two files.

First.php

<?php
   namespace appcomponents;
   use appcomponentsMyInterface;
   class First implements MyInterface {
      public function test() {
         echo "First class <br>";
      }
   }
?>

Second.php

<?php
   appcomponents;
   use appcomponentsMyInterface;
      class Second implements MyInterface {
      public function test() {
         echo "Second class <br>";
      }
   }
?>

Step 3 − Now, add an actionTestInterface to the SiteController.

public function actionTestInterface() {
   $container = new yiidiContainer();
   $container->set
      ("appcomponentsMyInterface","appcomponentsFirst");
   $obj = $container->get("appcomponentsMyInterface");
   $obj->test(); // print "First class"
   $container->set
      ("appcomponentsMyInterface","appcomponentsSecond");
   $obj = $container->get("appcomponentsMyInterface");
   $obj->test(); // print "Second class"
}

Step 4 − Go to http://localhost:8080/index.php?r=site/test-interface you should see the following.

Using DI

This approach is convenient as we can set classes in one place and other code will use new classes automatically.

Advertisements

”;

Leave a Reply

Your email address will not be published. Required fields are marked *