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.

About these ads

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...