Dependency Injection Container

Het instantieëren van een object kan uiteindelijk vrij veel code vereisen. Een instantie van Zend_Mail kan je bijvoorbeeld als volgt maken:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
<?php
$transport
= new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
  'auth'     => 'login',
  'username' => 'foo',
  'password' => 'bar',
  'ssl'      => 'ssl',
  'port'     => 465,
));

 
$mailer = new Zend_Mail();
$mailer->setDefaultTransport($transport);
?>

Dat is vrij veel code om elke keer als je de mailer nodig hebt te gebruiken. Een Dependency Injection Container beheert dergelijke objecten, vanaf nu ook wel services geheten. Services zijn dus kant-en-klare objecten die de container voor je kan maken. Een Dependency Injection Container wordt daarom ook wel een Service container genoemd. De taak van de container is dus om services op te bouwen en te retourneren.

Een hardcoded container voor bovenstaand voorbeeld kan er als volgt uitzien:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class Container
{
  public function getMailTransport()
  {

    return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
      'auth'     => 'login',
      'username' => 'foo',
      'password' => 'bar',
      'ssl'      => 'ssl',
      'port'     => 465,
    ));
  }

 
  public function getMailer()
  {

    $mailer = new Zend_Mail();
    $mailer->setDefaultTransport($this->getMailTransport());
 
    return $mailer;
  }

?>

Merk op hoe de verschillende afhankelijkheden ook verschillende methoden hebben.
Het gebruik is makkelijk:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$container
= new Container();
$mailer = $container->getMailer();
?>

We kunnen nu aan de container vragen om voor ons een mailer te creëren, zonder iets te weten over de configuratie. De verantwoordelijkheden zijn zo mooi gescheiden.

De container is nu echter nog weinig flexibel. Dit kan opgelost worden door de container parameters mee te geven:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
class Container
{
  protected $parameters = array();
 
  public function __construct(array $parameters = array())
  {

    $this->parameters = $parameters;
  }

 
  public function getMailTransport()
  {

    return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
      'auth'     => 'login',
      'username' => $this->parameters['mailer.username'],
      'password' => $this->parameters['mailer.password'],
      'ssl'      => 'ssl',
      'port'     => 465,
    ));
  }

 
  public function getMailer()
  {

    $mailer = new Zend_Mail();
    $mailer->setDefaultTransport($this->getMailTransport());
 
    return $mailer;
  }
}

?>

Nu kunnen gemakkelijk de gebruikersnaam en het wachtwoord worden aangepast:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$container
= new Container(array(
  'mailer.username' => 'foo',
  'mailer.password' => 'bar',
));

$mailer = $container->getMailer();
?>

En stel dat we de klasse van de mailer willen kunnen aanpassen, kunnen we ook voor de klassenaam een parameter gebruiken:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class Container
{
  // ...
 
  public function getMailer()
  {

    $class = $this->parameters['mailer.class'];
 
    $mailer = new $class();
    $mailer->setDefaultTransport($this->getMailTransport());
 
    return $mailer;
  }
}

 
$container = new Container(array(
  'mailer.username' => 'foo',
  'mailer.password' => 'bar',
  'mailer.class'    => 'Zend_Mail',
));

$mailer = $container->getMailer();
?>


En bovendien kan je de mailer service hergebruiken:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class Container
{
  protected $shared = array();
 
  // ...
 
  public function getMailer()
  {

    if (isset($this->shared['mailer']))
    {

      return $this->shared['mailer'];
    }

 
    $class = $this->parameters['mailer.class'];
 
    $mailer = new $class();
    $mailer->setDefaultTransport($this->getMailTransport());
 
    return $this->shared['mailer'] = $mailer;
  }
}

?>

De eerste keer dat er een mailer wordt aangemaakt, wordt het object opgeslagen in de $shared property van de container. De tweede keer wordt dan dit object teruggegeven, in plaats van dat er een nieuwe wordt aangemaakt.

De Dependency Injection Container neemt dus de instantiatie en configuratie van services voor zijn rekening. Deze objecten zelf hoeven zich niet van de container bewust te zijn. Zo kan elk PHP object een service worden.

« Lees de omschrijving en reacties

Inhoudsopgave

  1. Inleiding
  2. Dependency Injection
  3. Dependency Injection Container
  4. Pcms container in opbouw - 1
  5. Pcms container in opbouw - 2
  6. De Pcms container
  7. Conclusie

PHP tutorial opties

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.