Dependency Injection

34
Dependency Injection Reinventing how you manage PHP classes

description

Dependency Injection, Reinventing how you manage PHP classes

Transcript of Dependency Injection

Page 1: Dependency Injection

Dependency InjectionReinventing how you manage PHP classes

Page 2: Dependency Injection

DI?

What is DI?

Page 3: Dependency Injection

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

- James Shore

The Really Short Version

Page 4: Dependency Injection

Why This Kolaveri DI?

Page 5: Dependency Injection

Why This Kolaveri DI?

CHANGE

Page 6: Dependency Injection

Why DI?

• Maintainable

• Extendible

• Flexible

• Configurable

• Testable

• Reusable

• Interoperable

Page 7: Dependency Injection

A Real Life Example

Page 8: Dependency Injection

“Dependency Injection” is a 25-dollar term for a 5-cent concept.

Don’t Panic!

Page 9: Dependency Injection

A PHP Example

Page 10: Dependency Injection

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); }

// ...

}

Page 11: Dependency Injection

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');

Page 12: Dependency Injection

// 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

Page 13: Dependency Injection

What if I want to use a different database like MongoDB or SQLite

Page 14: Dependency Injection

Hey wait, I can improve it!

Page 15: Dependency Injection

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');

Page 16: Dependency Injection

Smart Huh???

Page 17: Dependency Injection

So, now User depends on Registry

Page 18: Dependency Injection

Let’s do it with DI

Page 19: Dependency Injection

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');

Page 20: Dependency Injection

But there are

still rooms for

improvement

Page 21: Dependency Injection

Interface

Page 22: Dependency Injection

Ever heard ofType Hinting

Page 23: Dependency Injection

public function test(OtherClass $otherClass) {

}

public function testInterface(Interface $interface) {

}

public function testArray(array $inputArray) {

}

Type HintingSince PHP 5.1

Page 24: Dependency Injection

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');

Page 25: Dependency Injection

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

Page 26: Dependency Injection

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

Page 27: Dependency Injection

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

Page 28: Dependency Injection

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

Page 29: Dependency Injection

DI Container

Page 30: Dependency Injection

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

Page 31: Dependency Injection

$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

Page 33: Dependency Injection

Question?