Dependency Injection
-
Upload
rifat-nabi -
Category
Technology
-
view
1.841 -
download
1
description
Transcript of Dependency Injection
Dependency InjectionReinventing how you manage PHP classes
DI?
What is DI?
Dependency Injection means giving an object its instance variables. Really. That's it.
- James Shore
The Really Short Version
Why This Kolaveri DI?
Why This Kolaveri DI?
CHANGE
Why DI?
• Maintainable
• Extendible
• Flexible
• Configurable
• Testable
• Reusable
• Interoperable
A Real Life Example
“Dependency Injection” is a 25-dollar term for a 5-cent concept.
Don’t Panic!
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', '[email protected]', 18, 'female');
// You can hardcode itpublic function __construct() { $this->_db = new MySqlDB('localhost', 'root', '', 'test');}
// You can configure it with an arraypublic function __construct($config) { $this->_db = new MySqlDB($config['host'], $config['user'], $config['pass'], $config['db']);}
// And, What we saw earlierpublic function __construct() { $this->_db = new MySqlDB(MYSQL_HOST, MYSQL_USER, MYSQL_PASS,
MYSQL_DB);}
Options
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', '[email protected]', 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', '[email protected]', 18, 'female');
But there are
still rooms for
improvement
Interface
Ever heard ofType Hinting
public function test(OtherClass $otherClass) {
}
public function testInterface(Interface $interface) {
}
public function testArray(array $inputArray) {
}
Type HintingSince PHP 5.1
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', '[email protected]', 18, 'female');
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); }
// ...}
MySQL
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', '[email protected]', 18, 'female');
MongoDB
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', '[email protected]', 18, 'female');
SQLite
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', '[email protected]', 18, 'female');print_r($fakeDb->get('users'));
TestDB
DI Container
class Container { protected $s=array(); function __set($k, $c) { $this->s[$k]=$c; } function __get($k) { return $this->s[$k]($this); }}
TwitteeA DI Container in a Tweet
using the power of PHP 5.3
$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();
Container
http://components.symfony-project.org/dependency-injection/
http://pimple.sensiolabs.org/
http://twittee.org/
More...
Question?
http://VistaArc.com/ http://OmicronLab.com/
Thank You