Dependency Injection

Ik zal het begrip 'Dependency Injection' introduceren met behulp van een voorbeeld, dat van een object geörienteerd session opslagsysteem.

Stel we de taal van de website willen opslaan in een sessievariabele, doen we dat als volgt:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$_SESSION
['language'] = 'nl';
?>

Opvragen gaat dan zo:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$language
= $_SESSION['language'];
?>


Wanneer we dit opslagmechanisme dan herschrijven in een object geörienteerde wijze krijg je iets als:
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
<?php
class SessionStorage
{
  public function __construct($cookieName = 'PHP_SESS_ID')
  {

    session_name($cookieName);
    session_start();
  }

 
  public function set($key, $value)
  {

    $_SESSION[$key] = $value;
  }

 
  public function get($key)
  {

    return $_SESSION[$key];
  }
}

?>


Een User klasse kan dit dan gebruiken om de taal op te slaan:
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 User
{
  protected $storage;
 
  public function __construct()
  {

    $this->storage = new SessionStorage();
  }

 
  public function setLanguage($language)
  {

    $this->storage->set('language', $language);
  }

 
  public function getLanguage()
  {

    return $this->storage->get('language');
  }

 
  // ...
}
?>

Het gebruik gaat dan als volgt:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
$user
= new User();
$user->setLanguage('nl');
$userLanguage = $user->getLanguage();
?>

Maar wat nu als we meer flexibiliteit willen en de naam van de cookie naam willen kunnen veranderen? Je kan dan bijvoorbeeld:
- De cookie naam hardcoden in de User klasse:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php
class User
{
    public function __construct()
    {

        $this->storage = new SessionStorage('DIT_IS_EEN_NAAM');
    }

    // ...
}
?>

- Een constante 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
<?php
define('STORAGE_SESSION_NAME', 'SESSION_ID');

class User
{
  public function __construct()
  {

    $this->storage = new SessionStorage(STORAGE_SESSION_NAME);
  }

 
  // ...
}
?>

- De cookie naam met de constructor meegeven:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class User
{
  public function __construct($sessionName)
  {

    $this->storage = new SessionStorage($sessionName);
  }

 
  // ...
}
 
$user = new User('SESSION_ID');
?>

- Een array met opties aan de constructor meegeven:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class User
{
  public function __construct($storageOptions)
  {

    $this->storage = new SessionStorage($storageOptions['session_name']);
  }

 
  // ...
}
 
$user = new User(array('session_name' => 'SESSION_ID'));
?>

Maar al deze methoden zijn verre van ideaal. Hardcoden in de User klasse maakt het geheel niet flexibeler en een constante voegt een afhankelijkheid toe. De naam megeven (al dan niet in een array) aan de constructor is dan nog het beste, maar als de applicatie dan complexer wordt, wordt het een chaos van meegegeven parameters. En wat als we de naam van de SessionStorage klasse willen aanpassen en een subklasse of een mock (een nep-object dat bij testen wordt gebruik) willen gebruiken? Dat is nu onmogelijk.

De oplossing is: Dependency Injection, het injecteren van de afhankelijkheid. In plaats van dat we SessionStorage (de afhankelijkheid) creëren in het User object, injecteren we het in de User klasse, bijvoorbeeld in de constructor.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php
class User
{
  public function __construct($storage)
  {

    $this->storage = $storage;
  }

 
  // ...
}
?>

En dat is dus Dependency Injection. Simpel.

De User klasse instantiëren is nu iets ingewikkelder:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$storage
= new SessionStorage('SESSION_ID');
$user = new User($storage);
?>

Configuratie is nu makkelijk, evenals het vervangen van de SessionStorage klasse. De User klasse hoeft hier niet voor te worden aangepast en de verantwoordelijkheden zijn nu beter gescheiden.

De afhankelijkheden kunnen ook anders dan via de constructor worden meegegeven:
- Setter injectie:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php
class User
{
  public function setSessionStorage($storage)
  {

    $this->storage = $storage;
  }

 
  // ...
}
?>

- Property injectie:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php
class User
{
  public $sessionStorage;
}

 
$user->sessionStorage = $storage;
?>

Meestal wordt constructor injectie gebruikt voor noodzakelijke afhankelijkeheden en setter injectie voor optionele afhankelijkheden. Property injectie gebruikt public properties en wordt daarom vaak als slordig gezien.

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