Dependency Injection
 Reinventing how you manage PHP classes
What is DI?




              DI?
The Really Short Version

 Dependency Injection means giving an object its
      instance variables. Really. That's it.

                                      - James Shore
Why This Kolaveri DI?
Why This Kolaveri DI?


 CHANGE
Why DI?
•   Maintainable

•   Extendible

•   Flexible

•   Configurable

•   Testable

•   Reusable

•   Interoperable
A Real Life Example
Don’t Panic!
“Dependency Injection” is a 25-dollar
    term for a 5-cent concept.
A PHP Example
class MySqlDB {

     private $_link;

     public function __construct($host, $username, $password, $database) {
         $this->_link = mysql_connect($host, $username, $password);
         mysql_select_db($database);
     }

     public function insert($data, $table) {
         array_map('mysql_real_escape_string', $data);

         $query = 'INSERT INTO `' . $table .
             '` (`' . implode('`,`', array_keys($data)) . '`)' .
             'VALUES ("' . implode('","', $data) . '" )';

         return mysql_query($query, $this->_link);
     }

    // ...

}
define('MYSQL_HOST', 'localhost');
define('MYSQL_USER', 'root');
define('MYSQL_PASS', '');
define('MYSQL_DB', 'test');

class User {

    private $_db;
    private $_info = array();

    public function __construct() {
        $this->_db = new MySqlDB(MYSQL_HOST, MYSQL_USER, MYSQL_PASS,
                                 MYSQL_DB);
    }

    public function register($name, $email, $age, $sex) {
        $this->_info = compact('name', 'email', 'age', 'sex');
        $this->_db->insert($this->_info, 'users');
    }

    // ...
}

$user = new User();
$user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
Options
// You can hardcode it
public function __construct() {
    $this->_db = new MySqlDB('localhost', 'root', '', 'test');
}



// You can configure it with an array
public function __construct($config) {
    $this->_db = new MySqlDB($config['host'], $config['user'],
                            $config['pass'], $config['db']);
}



// And, What we saw earlier
public function __construct() {
    $this->_db = new MySqlDB(MYSQL_HOST, MYSQL_USER, MYSQL_PASS,
                             MYSQL_DB);
}
What if I want to use a different
database like MongoDB or SQLite
Hey wait, I can improve it!
class User {

    protected $_db;
    protected $_info = array();

    public function __construct() {
        $registry = RegistrySingleton::getInstance();
        $this->_db = $registry->database;
    }

    public function register($name, $email, $age, $sex) {
        $this->_info = compact('name', 'email', 'age', 'sex');
        $this->_db->insert($this->info, 'users');
    }

    // ...

}

$user = new User();
$user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
Smart Huh???
So, now User depends
      on Registry
Let’s do it with DI
class User {

    protected $_db;
    protected $_info = array();

    public function __construct($database) {
        $this->_db = $database;
    }

    public function register($name, $email, $age, $sex) {
        $this->_info = compact('name', 'email', 'age', 'sex');
        $this->_db->insert($this->_info, 'users');
    }

    // ...

}

$mysql = new MySqlDB('localhost', 'root', '', 'test');
$user = new User($mysql);
$user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
th ere  are
 But
        ro oms  for
st ill
   im pro vem ent
Interface
Ever hear
          d of
Type Hint
          ing
Type Hinting
        Since PHP 5.1
public function test(OtherClass $otherClass) {

}

public function testInterface(Interface $interface) {

}

public function testArray(array $inputArray) {

}
interface Database {
    public function insert(array $data, $table);
}

class User {

    protected $_db;
    protected $_info = array();

    public function __construct(Database $database) {
        $this->_db = $database;
    }

    public function register($name, $email, $age, $sex) {
        $this->_info = compact('name', 'email', 'age', 'sex');
        $this->_db->insert($this->_info, 'users');
    }

    // ...

}

$mysql = new MySqlDB('localhost', 'root', '', 'test');
$user = new User($mysql);
$user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
MySQL
class MySqlDB implements Database {

     protected $_link;

     public function __construct($host, $username, $password, $database) {
         $this->_link = mysql_connect($host, $username, $password);
         mysql_select_db($database);
     }

     public function insert(array $data, $table) {
         array_map('mysql_real_escape_string', $data);

         $query = 'INSERT INTO `' . $table .
             '` (`' . implode('`,`', array_keys($data)) . '`)' .
             'VALUES ("' . implode('","', $data) . '" )';

         return mysql_query($query, $this->_link);
     }

    // ...
}
MongoDB
class MongoDB implements Database {

    // ...

     public function insert(array $data, $table) {
         // Save the passed array using MongoDB
     }

    // ...

}

$mongoDb = new MongoDB('localhost', 'root', '', 'test');
$user = new User($mongoDb);
$user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
SQLite
class SQLiteDB implements Database {

    // ...

     public function insert(array $data, $table) {
         // Save the passed array using SQLite
     }

    // ...

}

$sqlite = new SQLiteDB('app.db', 'test');
$user = new User($sqlite);
$user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
TestDB
class TestDB implements Database {

    protected $_data = array();

    public function insert(array $data, $table) {
        $this->_data[$table] = $data;
    }

    public function get($table) {
        return $this->_data[$table];
    }

}

$fakeDb = new TestDB();
$user = new User($fakeDb);
$user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
print_r($fakeDb->get('users'));
DI Contai
          ner
Twittee
   A DI Container in a Tweet

using the power of                           PHP 5.3
class Container {
    protected $s=array();
    function __set($k, $c) { $this->s[$k]=$c; }
    function __get($k) { return $this->s[$k]($this); }
}
Container
$c = new Container();

$c->mysql = function ($c) {
    return new MySqlDB('localhost', 'root', '', 'test');
}

$c->user = function ($c) {
    $db = $c->mysql;
    return new User($db);
}

// When you need a user
$user = $c->user;

// Instead of
$user = new User();
More...
http://components.symfony-project.org/dependency-injection/

                http://pimple.sensiolabs.org/

                     http://twittee.org/
Question?
Thank
 You


                @rifat
         rifat@facebook.com
          http://VistaArc.com/
        http://OmicronLab.com/

Dependency Injection

  • 1.
    Dependency Injection Reinventinghow you manage PHP classes
  • 2.
  • 3.
    The Really ShortVersion Dependency Injection means giving an object its instance variables. Really. That's it. - James Shore
  • 4.
  • 5.
  • 6.
    Why DI? • Maintainable • Extendible • Flexible • Configurable • Testable • Reusable • Interoperable
  • 7.
    A Real LifeExample
  • 8.
    Don’t Panic! “Dependency Injection”is a 25-dollar term for a 5-cent concept.
  • 9.
  • 10.
    class MySqlDB { private $_link; public function __construct($host, $username, $password, $database) { $this->_link = mysql_connect($host, $username, $password); mysql_select_db($database); } public function insert($data, $table) { array_map('mysql_real_escape_string', $data); $query = 'INSERT INTO `' . $table . '` (`' . implode('`,`', array_keys($data)) . '`)' . 'VALUES ("' . implode('","', $data) . '" )'; return mysql_query($query, $this->_link); } // ... }
  • 11.
    define('MYSQL_HOST', 'localhost'); define('MYSQL_USER', 'root'); define('MYSQL_PASS',''); define('MYSQL_DB', 'test'); class User { private $_db; private $_info = array(); public function __construct() { $this->_db = new MySqlDB(MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB); } public function register($name, $email, $age, $sex) { $this->_info = compact('name', 'email', 'age', 'sex'); $this->_db->insert($this->_info, 'users'); } // ... } $user = new User(); $user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
  • 12.
    Options // You canhardcode it public function __construct() { $this->_db = new MySqlDB('localhost', 'root', '', 'test'); } // You can configure it with an array public function __construct($config) { $this->_db = new MySqlDB($config['host'], $config['user'], $config['pass'], $config['db']); } // And, What we saw earlier public function __construct() { $this->_db = new MySqlDB(MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB); }
  • 13.
    What if Iwant to use a different database like MongoDB or SQLite
  • 14.
    Hey wait, Ican improve it!
  • 15.
    class User { protected $_db; protected $_info = array(); public function __construct() { $registry = RegistrySingleton::getInstance(); $this->_db = $registry->database; } public function register($name, $email, $age, $sex) { $this->_info = compact('name', 'email', 'age', 'sex'); $this->_db->insert($this->info, 'users'); } // ... } $user = new User(); $user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
  • 16.
  • 17.
    So, now Userdepends on Registry
  • 18.
  • 19.
    class User { protected $_db; protected $_info = array(); public function __construct($database) { $this->_db = $database; } public function register($name, $email, $age, $sex) { $this->_info = compact('name', 'email', 'age', 'sex'); $this->_db->insert($this->_info, 'users'); } // ... } $mysql = new MySqlDB('localhost', 'root', '', 'test'); $user = new User($mysql); $user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
  • 20.
    th ere are But ro oms for st ill im pro vem ent
  • 21.
  • 22.
    Ever hear d of Type Hint ing
  • 23.
    Type Hinting Since PHP 5.1 public function test(OtherClass $otherClass) { } public function testInterface(Interface $interface) { } public function testArray(array $inputArray) { }
  • 24.
    interface Database { public function insert(array $data, $table); } class User { protected $_db; protected $_info = array(); public function __construct(Database $database) { $this->_db = $database; } public function register($name, $email, $age, $sex) { $this->_info = compact('name', 'email', 'age', 'sex'); $this->_db->insert($this->_info, 'users'); } // ... } $mysql = new MySqlDB('localhost', 'root', '', 'test'); $user = new User($mysql); $user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
  • 25.
    MySQL class MySqlDB implementsDatabase { protected $_link; public function __construct($host, $username, $password, $database) { $this->_link = mysql_connect($host, $username, $password); mysql_select_db($database); } public function insert(array $data, $table) { array_map('mysql_real_escape_string', $data); $query = 'INSERT INTO `' . $table . '` (`' . implode('`,`', array_keys($data)) . '`)' . 'VALUES ("' . implode('","', $data) . '" )'; return mysql_query($query, $this->_link); } // ... }
  • 26.
    MongoDB class MongoDB implementsDatabase { // ... public function insert(array $data, $table) { // Save the passed array using MongoDB } // ... } $mongoDb = new MongoDB('localhost', 'root', '', 'test'); $user = new User($mongoDb); $user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
  • 27.
    SQLite class SQLiteDB implementsDatabase { // ... public function insert(array $data, $table) { // Save the passed array using SQLite } // ... } $sqlite = new SQLiteDB('app.db', 'test'); $user = new User($sqlite); $user->register('Tasneem', 'tasmee@fb.me', 18, 'female');
  • 28.
    TestDB class TestDB implementsDatabase { protected $_data = array(); public function insert(array $data, $table) { $this->_data[$table] = $data; } public function get($table) { return $this->_data[$table]; } } $fakeDb = new TestDB(); $user = new User($fakeDb); $user->register('Tasneem', 'tasmee@fb.me', 18, 'female'); print_r($fakeDb->get('users'));
  • 29.
  • 30.
    Twittee A DI Container in a Tweet using the power of PHP 5.3 class Container { protected $s=array(); function __set($k, $c) { $this->s[$k]=$c; } function __get($k) { return $this->s[$k]($this); } }
  • 31.
    Container $c = newContainer(); $c->mysql = function ($c) { return new MySqlDB('localhost', 'root', '', 'test'); } $c->user = function ($c) { $db = $c->mysql; return new User($db); } // When you need a user $user = $c->user; // Instead of $user = new User();
  • 32.
    More... http://components.symfony-project.org/dependency-injection/ http://pimple.sensiolabs.org/ http://twittee.org/
  • 33.
  • 34.
    Thank You @rifat rifat@facebook.com http://VistaArc.com/ http://OmicronLab.com/