Dependency Injection in PHP parte 2: Container

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.

Lascia un Commento

Fill in your details below or click an icon to log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Log Out / Modifica )

Foto Twitter

You are commenting using your Twitter account. Log Out / Modifica )

Foto di Facebook

You are commenting using your Facebook account. Log Out / Modifica )

Connecting to %s