Maison >développement back-end >tutoriel php >PHP Master | Injection de dépendance avec bouton

PHP Master | Injection de dépendance avec bouton

Christopher Nolan
Christopher Nolanoriginal
2025-02-24 08:57:10514parcourir

PHP Master | Dependency Injection with Pimple

Points de base

  • L'injection de dépendance est un concept clé dans le développement d'applications, et en injectant les dépendances dans les modules plutôt que de les coder dur, vous pouvez écrire un code plus efficace et plus maintenable.
  • Pimple est un simple conteneur d'injection de dépendance qui utilise la fermeture de PHP pour définir les dépendances de manière gérable, aidant à maintenir votre code maintenable.
  • Les deux principales techniques d'injection de dépendances sont l'injection de dépendance basée sur le constructeur et l'injection basée sur le secteur, chacune avec ses propres avantages et inconvénients.
  • Pimple prend en charge le principe sec du développement de logiciels en agissant comme un conteneur qui définit les dépendances, en évitant la duplication, en facilitant la gestion et la centralisation des services dans les applications.
  • Pimple fournit également des fonctionnalités avancées telles que la possibilité de renvoyer la même instance à l'aide d'objets partagés, et la possibilité de modifier dynamiquement les fermetures existantes sans affecter l'implémentation d'origine.

Dans le développement d'applications, nous essayons de créer des modules autonomes pour réutiliser le code dans les projets futurs. Cependant, la création de modules complètement indépendants qui fournissent des fonctionnalités utiles sont difficiles; C'est là que l'injection de dépendance est utile, car elle nous permet d'injecter les dépendances nécessaires pour que le code fonctionne correctement sans les coder dur dans le module. Pimple est un simple conteneur d'injection de dépendance qui utilise la fermeture de PHP pour définir les dépendances de manière gérable. Dans cet article, nous explorerons le problème des dépendances à code dur, comment l'injection de dépendance résout ces problèmes et comment utiliser Pimple pour faciliter l'injection de dépendance à la dépendance.

Problème de dépendances spécifiques

Lors de la rédaction d'applications, nous utilisons de nombreuses classes PHP. Une classe peut avoir besoin d'appeler des méthodes d'une ou plusieurs autres classes pour fournir les fonctionnalités attendues, nous disons donc que la première classe dépend d'autres classes. Par exemple:

<code class="language-php"><?php
class A
{
    public function a1() {
        $b = new B();
        $b->b1();
    }
}</code>

La classe A dépend de la classe B. Si la classe B n'est pas disponible, le code ci-dessus ne fonctionnera pas. De plus, chaque fois que nous cocodions en dur la création d'un objet dans la classe, nous aurons des dépendances spécifiques à la classe. Les dépendances spécifiques sont un obstacle à la rédaction de code testable. Une meilleure approche consiste à fournir un objet de classe B à la classe A. Ces objets peuvent être fournis par le constructeur de A ou la méthode du secteur. Avant de discuter plus approfondie, regardons un scénario plus réaliste.

Partager du contenu sur les sites de réseaux sociaux est très courant de nos jours, et la plupart des sites Web affichent directement leurs flux de profil social sur leurs sites Web. Supposons que nous ayons une classe appelée SocialFeeds qui génère des flux à partir de sites sociaux tels que Twitter, Facebook, Google, etc. Créez des classes distinctes pour gérer chacun de ces services. Ici, nous examinerons la classe Twitterservice qui interagit avec Twitter. La classe SocialFeeds utilise Twitterservice pour demander des flux Twitter. Twiterservice interagit avec la base de données pour récupérer des jetons utilisateur spécifiques qui accèdent à l'API. Le jeton est transmis à la classe OAuth, qui récupère le flux à l'aide du jeton fourni et le renvoie à la classe SocialFeeds.

<code class="language-php"><?php
class A
{
    public function a1() {
        $b = new B();
        $b->b1();
    }
}</code>
<code class="language-php"><?php
class SocialFeeds
{
    public function getSocialFeeds() {
        $twService = new TwitterService();
        echo $twService->getTweets();
    }
}</code>
<code class="language-php"><?php
class TwitterService
{
    public function getTweets() {
        $db = new DB();
        $query = "Query to get user token from database";
        $token = $db->getQueryResults($query);

        $oauth = new OAuth();
        return $oauth->requestTwitterFeed($token);
    }
}</code>
<code class="language-php"><?php
class OAuth
{
    public function requestTwitterFeed($token) {
        // Retrieve and return twitter feed using the token         
    }
}</code>

Il est évident que SocialFeeds repose sur Twitterservice. Mais Twitterservice dépend de la DB et de l'OAuth, de sorte que SocialFeeds dépendent indirectement DB et OAuth. Alors, quel est le problème? Socialfeeds s'appuie sur la mise en œuvre concrète de trois classes, il est donc impossible de tester les sociaux-sociétés séparément sans la véritable mise en œuvre d'autres classes. Ou supposons que nous voulons utiliser une base de données différente ou un autre fournisseur OAuth. Dans ce cas, nous devons remplacer la classe existante par la nouvelle classe tout au long du code.

Correction des dépendances spécifiques

La solution à ces dépendances est simple, c'est-à-dire fournir dynamiquement des objets si nécessaire sans utiliser d'implémentations concrètes. Il existe deux types de techniques qui peuvent injecter des dépendances: l'injection de dépendance basée sur le constructeur et l'injection basée sur le secteur.

Injection basée sur le constructeur

En utilisant l'injection de dépendance basée sur le constructeur, l'objet de dépendance est créé à l'extérieur et passé comme paramètre au constructeur de la classe. Nous pouvons attribuer ces objets aux variables de classe et les utiliser n'importe où dans la classe. L'injection basée sur le constructeur de la classe SocialFeeds est la suivante:

<code class="language-php"><?php
class DB
{
    public function getQueryResults($query) {
        // Get results from database and return token
    }
}</code>

Une instance de Twitterservice est passé comme un objet au constructeur. SocialFeeds repose toujours sur Twitterservice, mais maintenant nous sommes libres de fournir différentes versions des fournisseurs de services Twitter, et même des objets simulés à des fins de test. En ce qui concerne Twitterservice, les classes DB et OAuth sont également définies de la même manière.

<code class="language-php"><?php
class SocialFeeds
{
    public $twService;

    public function __construct($twService) {
        $this->twService = $twService;
    }

    public function getSocialFeeds() {
        echo $this->twService->getTweets();
    }
}</code>

injection basée sur le secteur

En utilisant l'injection basée sur le secteur, les objets sont fournis par des méthodes de setter au lieu des constructeurs. Ce qui suit est la mise en œuvre de l'injection de dépendance basée sur le setter de la classe SocialFeeds:

<code class="language-php"><?php
$db = new DB();
$oauth = new OAuth();
$twService = new TwitterService($db, $oauth);
$socialFeeds = new SocialFeeds($twService);
$socialFeeds->getSocialFeeds();</code>

Le code d'initialisation comprend désormais DB et OAuth ressemble à ceci:

<code class="language-php"><?php
class SocialFeeds
{
    public $twService;

    public function getSocialFeeds() {
        echo $this->twService->getTweets();
    }

    public function setTwitterService($twService) {
        $this->twService = $twService;
    }
}</code>

Constructeur et injection de setter

Sélectionner l'injection basée sur le constructeur ou l'injection basée sur le secteur dépend de vous. L'injection basée sur le constructeur convient lorsque toutes les dépendances sont nécessaires pour instancier une classe. L'injection basée sur le secteur convient lorsque les dépendances ne sont pas nécessaires à chaque fois.

pros

  • Constructeur - Il suffit de regarder le constructeur de la classe pour identifier toutes les dépendances de la classe
  • Setor - L'ajout de nouvelles dépendances est aussi simple que d'ajouter une nouvelle méthode de setter et ne casser pas le code existant

Inconvénients

  • Constructeur - L'ajout de nouvelles dépendances ajoutera des paramètres au constructeur;
  • Setor - Nous devons rechercher les dépendances nécessaires manuellement car elles ne sont spécifiées nulle part
Après avoir compris l'injection de dépendance et diverses techniques d'injection, il est temps de voir le bouton et comment il s'y trouve.

Le rôle de Pimple dans Di

Lorsque nous pouvons déjà injecter des dépendances en utilisant les techniques susmentionnées, vous vous demandez peut-être pourquoi vous avez besoin de bouton. Pour répondre à cette question, nous devons regarder le principe sec.

Ne vous répétez pas (sec) est un principe du développement logiciel qui vise à réduire la duplication de diverses informations, ce qui est particulièrement utile dans les architectures multicouches. L'énoncé du principe sec est que "chaque fragment de connaissance doit avoir une représentation unique, claire et faisant autorité dans un système" - Wikipedia

Considérez l'exemple d'injection basé sur le constructeur. Chaque fois que nous voulons un objet de la classe SocialFeed, nous devons répéter l'intégralité du processus de configuration d'instanciation et de transmission de ses dépendances. Selon Dry, ce code doit être évité pour éviter les problèmes de maintenance. Pimple agit comme un conteneur qui définit ces dépendances pour éviter la duplication. Regardons un exemple simple pour voir comment fonctionne Pimple.

<code class="language-php"><?php
class A
{
    public function a1() {
        $b = new B();
        $b->b1();
    }
}</code>
Créez une instance de Pimple comme conteneur pour stocker les dépendances. Il implémente l'interface SPL ArrayAccess, donc l'utiliser est très similaire à l'utilisation des tableaux. Tout d'abord, nous définissons une clé qui contient le nom de toute classe que nous voulons. Nous définissons ensuite une fermeture pour renvoyer une instance de la classe spécifiée qui agit comme un service. Notez qu'une instance du conteneur sera transmise à $ C, nous pouvons donc nous référer à d'autres clés définies selon les besoins; chaque paramètre ou objet défini peut être utilisé dans la fermeture via la variable $ C. Maintenant, chaque fois que nous voulons une instance d'une classe, nous pouvons référencer la clé pour récupérer l'objet. Convertissons l'exemple SocialFeeds en pimple. Les exemples sur le site Web officiel du pimple montrent une injection basée sur le constructeur, nous allons donc ici illustrer l'injection basée sur le setter. N'oubliez pas que pour utiliser Pimple, nous n'avons pas besoin de modifier des méthodes de setter ou du code défini précédemment - nous encapsulons simplement la logique.

<code class="language-php"><?php
class SocialFeeds
{
    public function getSocialFeeds() {
        $twService = new TwitterService();
        echo $twService->getTweets();
    }
}</code>
Les classes DB et OAuth sont toutes deux des modules indépendants, nous retournons donc leurs nouvelles instances directement dans la fermeture. Nous utilisons ensuite l'injection basée sur le secteur pour ajouter des dépendances à la classe Twitterservice. Nous avons ajouté les classes DB et OAuth au conteneur, afin que nous puissions y accéder directement à l'intérieur de la fonction en utilisant $ c ['db'] et $ c ['oAuth']. Maintenant, les dépendances sont encapsulées dans le conteneur en tant que service. Chaque fois que nous voulons utiliser une classe DB différente ou un autre service OAuth, nous remplaçons simplement la classe dans l'instruction Container et tout fonctionnera parfaitement. Avec Pimple, il vous suffit d'ajouter de nouvelles dépendances en un seul endroit.

Utilisation avancée du pimp

Dans le scénario ci-dessus, Pimple renvoie une nouvelle instance de chaque classe de la fermeture à chaque fois qu'il est demandé. Dans certains cas, nous devons utiliser le même objet sans initialiser une nouvelle instance à chaque fois, comme la connexion à une base de données en est un exemple parfait. Pimple offre la possibilité de renvoyer la même instance à l'aide d'un objet partagé.

<code class="language-php"><?php
class A
{
    public function a1() {
        $b = new B();
        $b->b1();
    }
}</code>
Aussi, jusqu'à présent, nous avons défini toutes les dépendances dans un seul emplacement dans le conteneur Pimple. Cependant, considérons un cas où nous avons besoin d'un service qui a ses dépendances mais est configuré légèrement différemment du service d'origine. Par exemple, supposons que nous devons accéder à l'ORM pour implémenter certaines fonctionnalités de la classe Twitterservice. Nous ne pouvons pas modifier la fermeture existante car elle oblige toutes les fonctions existantes à utiliser ORM. PIMPLE fournit la méthode Extend () pour modifier dynamiquement les fermetures existantes sans affecter l'implémentation d'origine. Considérez le code suivant:

<code class="language-php"><?php
class SocialFeeds
{
    public function getSocialFeeds() {
        $twService = new TwitterService();
        echo $twService->getTweets();
    }
}</code>
Maintenant, nous pouvons utiliser différentes versions d'extension de Tweet_Service dans des cas spéciaux. Le premier paramètre est le nom du service, et le deuxième paramètre est une fonction qui peut accéder aux instances et aux conteneurs d'objets. En fait, Extend () est un moyen puissant d'ajouter dynamiquement les dépendances en fonction des différentes situations, mais assurez-vous de limiter la version étendue du service au minimum, car elle augmente la quantité de code en double.

Résumé

La gestion des dépendances est l'une des tâches les plus importantes et les plus difficiles du développement d'applications Web. Nous pouvons utiliser l'injection de dépendance des constructeurs et des méthodes de setter pour les gérer efficacement. Cependant, l'injection de dépendance elle-même a également quelques problèmes, et Pimple résout ces problèmes en fournissant un conteneur léger pour créer et stocker les dépendances d'objets de manière sèche. N'hésitez pas à partager votre expérience en gestion de dépendances dans votre projet et à vos réflexions sur Pimple en tant que conteneur d'injection de dépendance dans les commentaires ci-dessous.

FAQ sur l'injection de dépendance avec Pimple (FAQ)

Qu'est-ce que Pimple et pourquoi est-il utilisé en PHP?

Pimple est un simple conteneur d'injection de dépendance PHP qui vous permet de gérer et de centraliser les services dans votre application. Il est utilisé dans PHP, ce qui rend le code plus flexible, réutilisable et plus facile à tester. En utilisant Pimple, vous pouvez instancier des objets en un seul endroit et les injecter dans différentes parties de votre application, réduisant le besoin de l'état global et facilitant votre code à maintenir et à tester.

Comment fonctionne Pimple?

Pimple fonctionne en stockant les définitions de service dans les conteneurs. Ces définitions sont appelables (fonction ou méthode) et elles renvoient les instances du service. Lorsque vous accédez à un service à partir d'un conteneur, Pimple exécute la définition de service pour créer un objet de service. Cela vous permet de gérer les services de manière centralisée et de partager des services tout au long de l'application.

Comment installer Pimple?

Pimple peut être installé à l'aide de Composer (outil de gestion de la dépendance de PHP). Vous pouvez installer Composer à l'échelle mondiale sur votre système, puis introduire Pimple dans votre projet en exécutant la commande

. composer require pimple/pimple

Comment définir un service dans Pimple?

Dans Pimple, vous pouvez définir un service en attribuant un objet appelant à une clé dans un conteneur. L'objet appelable doit renvoyer une instance du service. Par exemple, vous pouvez définir un service pour la classe d'expéditeur de messagerie comme ceci:

$container['mailer'] = function ($c) { return new Mailer($c['smtp']); };

Dans cet exemple, le service d'expéditeur de courrier est défini comme une nouvelle instance de la classe Mailer, où le service SMTP est injecté comme une dépendance.

Comment accéder aux services à Pimple?

Vous pouvez accéder aux services dans Pimple à l'aide de la notation du tableau avec des clés de service. Par exemple, vous pouvez accéder au service d'expéditeur de messagerie comme ceci: $mailer = $container['mailer'];. Lorsque vous accédez à un service, Pimple exécute la définition de service et renvoie l'objet de service.

Comment partager des services dans Pimple?

Par défaut, Pimple renvoie une nouvelle instance du service chaque fois qu'il accède au service. Si vous souhaitez partager le service et renvoyer la même instance à chaque fois, vous pouvez utiliser la méthode share(). Par exemple, vous pouvez partager le service d'expéditeur de messagerie comme ceci: $container['mailer'] = $container->share(function ($c) { return new Mailer($c['smtp']); });.

Puis-je étendre le service en bouton?

Oui, vous pouvez utiliser la méthode extend() pour étendre les services dans Pimple. Cela vous permet de modifier le service après l'avoir défini. Par exemple, vous pouvez étendre le service d'expéditeur de messagerie comme celui-ci pour ajouter une configuration supplémentaire:

$container['mailer'] = $container->extend('mailer', function ($mailer, $c) { $mailer->setFrom($c['email.from']); return $mailer; });

Dans cet exemple, la méthode setFrom() est appelée sur le service d'expéditeur de courrier à l'aide du service email.from comme paramètre.

Comment protéger les paramètres dans Pimple?

Dans Pimple, vous pouvez utiliser la méthode protect() pour protéger les paramètres (qui ne doivent pas être considérés comme des paramètres des services). Cela vous permet de stocker des valeurs dans un conteneur sans les traiter comme des définitions de service. Par exemple, vous pouvez protéger la valeur de configuration comme ceci: $container['config.value'] = $container->protect(function () { return 'value'; });.

Comment utiliser Pimple dans un projet?

Vous pouvez utiliser Pimple dans un projet en créant une nouvelle instance de la classe Pimplicontainer et en définissant un service là-bas. Vous pouvez ensuite accéder au service à partir du conteneur où vous en avez besoin dans l'application. Cela vous permet de gérer les services de manière centralisée et de les injecter dans différentes parties de votre application.

Quels sont les avantages de l'utilisation de bouton?

Pimple offre de nombreux avantages pour le développement de PHP. Il rend votre code plus flexible car il vous permet de gérer les services de manière centralisée. Il rend votre code plus facile à réutiliser car il vous permet de partager des services tout au long de votre application. Il rend votre code plus facile à tester car il vous permet d'injecter des services simulés pour les tests. En utilisant Pimple, vous pouvez améliorer la qualité de votre code et faciliter le maintien et le test.

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