Pcms container in opbouw - 2
Nu zal ik het mogelijk maken om de container te laten uitbreiden met de definities uit andere containers. Dit is niet nodig voor eenvoudig gebruik, maar wel voor een modulaire applicatie. Deze pagina is dus niet noodzakelijk, misschien wel een leuke bonus.
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
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
<?php
class Container
{
// ...
public function extend(Container $c)
{
$c->applyValuesTo($this);
}
public function applyValuesTo(Container $c)
{
foreach($this->values as $key => $value) {
$c->set($key, $value, $this->shared[$key]);
}
}
}
$hoofdContainer = new Container();
$subContainer = new Container();
$subContainer->set('mailer', function() {
return new Zend_Mailer();
}, true);
$hoofdContainer->extend($subContainer);
$mailer = $hoofdContainer->get('mailer');
?>
class Container
{
// ...
public function extend(Container $c)
{
$c->applyValuesTo($this);
}
public function applyValuesTo(Container $c)
{
foreach($this->values as $key => $value) {
$c->set($key, $value, $this->shared[$key]);
}
}
}
$hoofdContainer = new Container();
$subContainer = new Container();
$subContainer->set('mailer', function() {
return new Zend_Mailer();
}, true);
$hoofdContainer->extend($subContainer);
$mailer = $hoofdContainer->get('mailer');
?>
Ik denk dat de code wel voor zich spreekt. Met de functie extend() kan een container zijn waarden uitbreiden met de waarden van een andere container. De functie applyValuesTo() is een hulp functie die de eigen waarden bij de andere container registreert. Deze constructie voorkomt een getAll() methode die mijns inziens de interne data te veel blootstelt.
Maar wat als een subcontainer een factory wil verfijnen om bijvoorbeeld een extra afhankelijkheid te injecteren in de service.
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$c->set('service', function($c) {
$service = $c->get('service');
$service->setExtraDependency(new Dependency());
return $service;
});
?>
$c->set('service', function($c) {
$service = $c->get('service');
$service->setExtraDependency(new Dependency());
return $service;
});
?>
Dit creƫert een cirkel-referentie omdat $c->get('service') de nieuwe factory zal teruggeven. De nieuwe factory word namelijk pas later aangeroepen als de oude factory al is overschreven.
Ik gebruik daarom (de door mij bedachte) 'configurators', callables die worden aangeroepen nadat de service door de oude factory is gemaakt en die de service nog kunnen aanpassen.
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
31
32
33
34
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
31
32
33
34
<?php
class Container
{
// ...
protected $configurators = array();
public function configure($key, $configurator)
{
if(!is_callable($configurator))
throw new \InvalidArgumentException('The configurator should be a callable');
$this->configurators[$key][] = $configurator;
}
public function get($key)
{
$value = $this->values[$key];
// Als het om een service gaat
if(is_callable($value)) {
$instance = $value($this);
if(isset($this->configurators[$key]))
foreach($this->configurators[$key] as $configurator) {
$instance = $configurator($instance, $this);
}
return $instance;
// Als het om een parameter gaat
else
return $value;
}
}
?>
class Container
{
// ...
protected $configurators = array();
public function configure($key, $configurator)
{
if(!is_callable($configurator))
throw new \InvalidArgumentException('The configurator should be a callable');
$this->configurators[$key][] = $configurator;
}
public function get($key)
{
$value = $this->values[$key];
// Als het om een service gaat
if(is_callable($value)) {
$instance = $value($this);
if(isset($this->configurators[$key]))
foreach($this->configurators[$key] as $configurator) {
$instance = $configurator($instance, $this);
}
return $instance;
// Als het om een parameter gaat
else
return $value;
}
}
?>
Het bovenstaande niet werkende voorbeeld kan nu herschreven worden als:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$c->configure('service', function($service, $c) {
$service->setExtraDependency(new Dependency());
return $service;
});
?>
$c->configure('service', function($service, $c) {
$service->setExtraDependency(new Dependency());
return $service;
});
?>
Zo is het mogelijk om een container uit te breiden met nieuwe parameters en factories evenals bestaande factories te verfijnen.
« 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