Maison >développement back-end >tutoriel php >Exemple de didacticiel d'injection de dépendances PHP (DI) et d'inversion de contrôle (IoC)

Exemple de didacticiel d'injection de dépendances PHP (DI) et d'inversion de contrôle (IoC)

零下一度
零下一度original
2017-06-23 14:25:242473parcourir

Pour comprendre les deux concepts de PHP Injection de dépendances et Inversion de contrôle, vous devez comprendre les deux problématiques suivantes :

  • DI - Injection de dépendances

  • IoC - Inversion de contrôle

Qu'est-ce que l'injection de dépendances

Je ne peux pas vivre sans toi, donc tu es ma dépendance. Pour le dire franchement :

n'est pas le mien, mais c'est ce dont j'ai besoin et sur lequel je compte. Tout ce qui doit être fourni en externe nécessite une injection de dépendances.

Exemple d'injection de dépendances

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Boy {
  protected $girl;
 
  public function __construct(Girl $girl) {
    $this->girl = $girl;
  }
}
 
class Girl {
  ...
}
 
$boy new Boy();  // Error; Boy must have girlfriend!
 
// 所以,必须要给他一个女朋友才行
$girl new Girl();
 
$boy new Boy($girl); // Right! So Happy!

D'après le code ci-dessus, nous pouvons voir que la Boyforte dépendanceGirl doit être injectée dans une instance de Girl pendant la construction.

Alors pourquoi y a-t-il un concept de 依赖注入 ? Quel problème 依赖注入 résout-il ?

Modifions le code ci-dessus par le code que nous avons tous écrit lorsque nous étions débutants :

1
1
2
3
4
5
6
7
class Boy {
  protected $girl;
 
  public function __construct() {
    $this->girl = new Girl();
  }
}
2
3
4

5
6

7Boy
class Garçon {Boy
protected $girl;Boy
public fonction __construct()

$this->girl = nouveau code> <code class="php plain">Fille();Boy
}LoliGirl
}GirlLoliGirl
tr>
Quelle est la différence entre cette méthode et la méthode précédente ?
1
2
3
4
5
6
7
8
9
10
11
12
class LoliGirl {
 
}
 
class Boy {
  protected $girl;
 
  public function __construct() {
      //  $this->girl = new Girl();  // sorry...
      $this->girl = new LoliGirl();
  }
}
Nous découvrirons que la petite amie de a été codée en dur dans le corps de . . . Chaque fois que je veux avoir un type de petite amie différent, je dois me déshabiller. Un jour en aime vraiment une et veut vraiment qu'elle soit sa petite amie. . . ce qu'il faut faire? Renaissance vous-même. . . Découvrez-vous. . . Jetez . . . Rentrez à l'intérieur. . .
1
2
3
4
5
6
7
8
9
10
11
12
class LoliGirl {
}
class Garçon {
code><code class="php password">protected $girl;
public fonction __construct()
// $this->girl = new Girl(); // désolé...
$this->girl = nouveau LoliGirl();
}
}

Un jour Boy je suis tombé amoureux de sœur Yu....Boy C'est tellement ennuyeux. . .

Vous vous sentez mal ? Chaque fois que je rencontre quelqu'un qui me traite sincèrement, je dois me torturer ainsi. . .

Boy a dit : je veux devenir plus fort. Je ne veux pas être changé encore et encore !

D'accord, rendons Boy un peu plus fort :

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
interface Girl {
  // Boy need knows that I have some abilities.
}
classLoliGril implement Girl {
  // I will implement Girl's abilities.
}
classVixen implement Girl {
   // Vixen definitely is a girl, do not doubt it.
}
class Boy {
  protected$girl;
  publicfunction__construct(Girl $girl) {
    $this ->girl =  $girl;
  }
}
$loliGirl new LoliGirl();
$vixen
$boy new Boy($vixen);

Boy Je suis très heureuse de pouvoir enfin vivre une vie différente sans avoir à m'ouvrir. . . Tellement heureux !

Méthode d'injection de dépendances

1. Injection de constructeur

1
1
2
3
4
5
6
7
8
<?php
class Book {
private $db_conn;
public function __construct($db_conn) {
$this->db_conn = $db_conn;
  }
}
2
3
4
5
6
7
8
<?php<🎜>
class Livre {<🎜>
</code > code><code class="php password">privé $db_conn;<🎜>< div class="numéro de ligne4 index3 alt1"> <🎜>
< code class="php mot-clé">public fonction __construct($db_conn) {<🎜>
< code class="php variable">$this->db_conn = $db_conn;
}<div class="numéro de ligne8 index7 alt1"><code class="php plain">}

2. Injection de Setter

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
<?php
class Book {
private $db;
private $file;
function setdb($db) {
$this->db = $db;
    }
    function setfile($file) {
        $this->file = $file;
    }
}
class file {
}
class db {
}
// ...
class test {
    $book new Book();
    $book->setdb(new db());
    $book->setfile(new file());
}

Résumé :

Parce que la plupart des applications sont composées de deux classes ou plus qui coopèrent les unes avec les autres pour implémenter la logique métier. obtenir une référence à l'objet avec lequel il coopère (c'est-à-dire l'objet dont il dépend). Si ce processus d’acquisition est implémenté seul, le code sera fortement couplé et difficile à maintenir et à déboguer.

C'est pourquoi nous avons le concept d'injection de dépendances. L'injection de dépendances résout les problèmes suivants :

  • Découplage entre dépendances

  • Tests unitaires, pratiques pour Mock

Les codes des deux méthodes ci-dessus sont très clairs, mais lorsque nous devons injecter de nombreuses dépendances, cela signifie ajouter beaucoup de lignes, ce qui sera comparé Ingérable.

Une meilleure solution consiste à créer une classe comme conteneur pour toutes les dépendances. Dans cette classe, vous pouvez stocker, créer, obtenir et trouver les dépendances requises. Comprenons d'abord le concept d'IOC

Inversion de contrôle (IOC)

Inversion de contrôle est un concept de programmation orientée objet. Une conception principe qui peut être utilisé pour réduire le couplage entre codes informatiques. La méthode la plus courante est appelée Dependency Injection (Dependency Injection, DI), et l'autre s'appelle "Dependency Lookup". Par inversion de contrôle, lorsqu'un objet est créé, une entité externe qui contrôle tous les objets du système lui transmet la référence de l'objet dont elle dépend. On peut aussi dire que des dépendances sont injectées dans l'objet.

1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class Ioc {
protected $db_conn;
public static function make_book() {
$new_book = new Book();
$new_book->set_db(self::$db_conn);
        //...
        //...
        //其他的依赖注入
        return $new_book;
    }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php<🎜> <🎜>
classe Ioc {</code ><🎜><div class="numéro de ligne4 index3 alt1"><code class="espaces php"> protégé $db_conn;<🎜>
<🎜>
< code class="php space"> public static fonction make_book() {<🎜>
$new_book = nouveau Livre();<🎜>
$new_book ->set_db(self::$db_conn);
//... //...
//Autre injection de dépendances
return $new_book;
}
}

À l'heure actuelle, si vous souhaitez obtenir une instance de livre, il vous suffit d'exécuter $newone = Ioc::makebook();

Ce qui précède est une instance spécifique de conteneur. Il est préférable de ne pas écrire une méthode d'injection de dépendance spécifique, utilisez l'enregistrement dans le registre. Il est préférable de l'obtenir via get

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
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
/**
* 控制反转类
*/
classIoc {
/**
* @var array 注册的依赖数组
*/
protected static $registry= array ();
/**
* 添加一个 resolve (匿名函数)到 registry 数组中
*
* @param string $name 依赖标识
* @param Closure $resolve 一个匿名函数,用来创建实例
* @return void
*/
public static function register($name, Closure $resolve) {
static::$registry[$name] = $resolve;
}
 
/**
* 返回一个实例
*
* @param string $name 依赖的标识
* @return mixed
* @throws Exception
*/
public static function resolve($name) {
if (static::registered($name)) {
$name = static::$registry[$name];
return $name();
}
 
throw new Exception("Nothing registered with that name");
}
 
/**
* 查询某个依赖实例是否存在
*
* @param string $name
* @return bool
*/
public static function registered($name) {
return array_key_exists($name, static::$registry);
}
}

Vous pouvez maintenant vous inscrire et injecter un

< div class="numéro de ligne1 index0 alt2">1
1
2
3
4
5
6
7
8
9
10
11
<?php
Ioc::register("book", function () {
$book = new Book();
$book->setdb('db');
    $book->setfile('file');
 
    return $book;
});
 
// 注入依赖
$book = Ioc::resolve('book');
2
3
4
5
6
7
8
9
10 11
<?php<🎜>
Ioc::register("livre"<🎜><🎜> () {<🎜>
< 🎜>$book = nouveau Livre();<🎜>
<🎜>$book- >setdb('db'
$book->setfile('file'
$book;
});
//Injecter des dépendances
$book = Ioc::resolve('book' code>

Résumé des questions

1. Qui sont les participants ?

Réponse : Généralement, il y a trois parties, l'une est un objet ; l'une est le conteneur IoC/DI ; l'autre est une ressource externe d'un objet. Permettez-moi d'expliquer à nouveau les noms. Un objet fait référence à n'importe quel objet Java ordinaire ; le conteneur IoC/DI fait simplement référence à un programme-cadre utilisé pour implémenter les fonctions IoC/DI ; les ressources externes de l'objet font référence à l'objet. de l'extérieur de l'objet, sont collectivement appelés ressources, telles que : d'autres objets nécessaires à l'objet, ou des ressources de fichiers nécessaires à l'objet, etc.

2. Dépendance : Qui dépend de qui ? Pourquoi y a-t-il des dépendances ?

Réponse : Un objet dépend du conteneur IoC/DI. Les dépendances sont inévitables. Dans un projet, il existe diverses relations entre les différentes classes, et il est impossible qu'elles soient toutes complètement indépendantes, ce qui forme des dépendances. Le développement traditionnel consiste à appeler directement lors de l'utilisation d'autres classes, ce qui formera un couplage fort, ce qui doit être évité. L'injection de dépendances emprunte des conteneurs pour transférer les objets dépendants afin de réaliser le découplage.

3. Injection : Qui injecte à qui ? Qu'est-ce qui est injecté exactement ?

Réponse : Injecter les ressources externes nécessaires dans l'objet via le conteneur

Inversion de contrôle : Qui contrôle qui ? Contrôler quoi ? Pourquoi parle-t-on de renversement ?

Réponse : L'objet de contrôle de conteneur d'IoC/DI contrôle principalement la création d'instances d'objet. L’inversion est relative à la direction positive, alors qu’est-ce qui compte comme direction positive ? Pensez à l'application dans des circonstances normales. Si vous souhaitez utiliser C dans A, que feriez-vous ? Bien entendu, l'objet de C est créé directement, c'est-à-dire que la ressource externe requise C est activement obtenue dans la classe A. Cette situation est appelée en avant. Alors, qu’est-ce que l’inverse ? Autrement dit, la classe A n'obtient plus activement C, mais attend passivement que le conteneur IoC/DI obtienne une instance de C, puis l'injecte dans la classe A à l'envers.

5. L'injection de dépendances et l'inversion de contrôle sont-elles le même concept ?

Réponse : Comme le montre ce qui précède : l'injection de dépendances est décrite du point de vue de l'application. L'injection de dépendances peut être décrite plus en détail : l'application dépend du conteneur pour créer et. injecter ce dont il a besoin Ressources externes;et l'inversion du contrôle est décrite du point de vue du conteneur.La description complète est la suivante: le conteneur contrôle l'application et le conteneur injecte à l'envers les ressources externes requises par l'application dans l'application.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn