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)
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
<?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');
?>

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)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$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)
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
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;
    }
}

?>


Het bovenstaande niet werkende voorbeeld kan nu herschreven worden als:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$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.

« 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.