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)
1
2
3
4
5
6
7
8
9
10
11
12
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);
?>
$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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;
}
?>
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:
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)
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
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;
}
}
?>
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)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$container = new Container(array(
'mailer.username' => 'foo',
'mailer.password' => 'bar',
));
$mailer = $container->getMailer();
?>
$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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
?>
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
}
}
?>
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.
« vorige pagina | volgende pagina »
Inhoudsopgave
- Inleiding
- Dependency Injection
- Dependency Injection Container
- Pcms container in opbouw - 1
- Pcms container in opbouw - 2
- De Pcms container
- Conclusie