La settimana scorsa avevo pubblicato un articolo introduttivo alla dependency injection; questa volta faremo un passo avanti definendo un Container, ovvero una classe il cui scopo è quello di contenere i nostri oggetti e di permettere di recuperarli in modo pratico.
Un primo container primitivo è un oggetto dotato di due metodi set() e get() i quali permettano l’accesso alle istanze rilevanti per la nostra applicazione:
class Container { protected $_Data = array(); public function get($item_name) { if (isset($this->_Data[$item_name]) ) return $this->_Data[$item_name]; return null; } public function set($item_name,$item) { $this->_Data[$item_name] = $item; } }
Questo può sembrare triviale ma in realtà è tutto ciò di cui abbiamo bisogno! : Grazie al container possiamo dedicare una parte dell’applicazione, che chiameremo bootstrapping, alla creazione delle istanze di oggetti che utilizzeremo in altri punti dell’esecuzione.
$connection = new MysqlConnection($host,$user,$password,$db); $db = new Database($connection); $logger = new TxtLogger('myfile.txt'); $view = new View('master'); $container = new Container(); $container->set('database',$db); $container->set('logger',$logger); $container->set('master_view',$view);
A questo punto non ci resta che passare l’istanza di container ai business objects che necessitano delle istanze di database, logger e view per poi poterle riutilizzare:
//... public function businessMethod() { $this->doAction(); $this->container->get('logger')->log(' Action done :) '); $userDao = new UserDao( $this->container->get('database') ); }
Per rendere il codice più leggibile potremmo sovrascrivere il magic method __get() in modo da cercare l’attributo richiesto direttamente nel container:
public function __get($name) { if (null !== $this->container->get($name) ) return $this->container->get($name); throw new BusinessObjectException('Unkown property '.$name); } public function anAction() { $this->database->query('INSER INTO table VALUES (bla bla bla)'); }
Per approfondire il design di un container, vi consiglio di leggere queste slides scritte da Fabien Potencier, il creatore di Symfony.