En tant que développeurs, nous essayons toujours de trouver de nouvelles façons d'écrire du code bien conçu et nettoyant en adoptant de nouveaux styles, en utilisant des modèles de conception et en essayant de nouveaux frameworks robustes. Dans cet article, nous explorerons le modèle de conception d'injection de dépendance via le composant IOC de Laravel et verrons comment il peut améliorer notre conception.
L'injection de dépendance est un terme inventé par Martin Fowler, et c'est l'acte d'injecter des composants dans votre application. Comme Ward Cunningham l'a dit:
L'injection de dépendance est un élément clé de l'architecture agile.
Voyons un exemple:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>$this->connection = new Connection; </span> <span>} </span> <span>public function retrieveByCredentials( array $credentials ){ </span> <span>$user = $this->connection </span> <span>->where( 'email', $credentials['email']) </span> <span>->where( 'password', $credentials['password']) </span> <span>->first(); </span> <span>return $user; </span> <span>} </span><span>}</span>
Si vous souhaitez tester ou entretenir cette classe, vous devrez accéder à une base de données réelle et faire des requêtes. Pour éviter d'avoir à faire cela et à découpler la classe du reste, vous avez l'une des trois options pour injecter la classe de connexion sans l'utiliser directement.
Lors de l'injection de composants dans votre classe, vous pouvez utiliser l'une des trois options:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
De même, nous pouvons injecter notre dépendance à l'aide d'une méthode de setter:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function setConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
<span>interface ConnectionInjector{ </span> <span>public function injectConnection( Connection $con ); </span><span>} </span> <span>class UserProvider implements ConnectionInjector{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function injectConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span><span>}</span>
Lorsqu'une classe implémente notre interface, nous définissons la méthode InjectConnection pour résoudre la dépendance.
Maintenant, lors du test de notre classe, nous pouvons se moquer de la classe de dépendance et la passer en tant que paramètre. Chaque classe doit être axée sur une tâche particulière et ne doit pas être soucieuse de résoudre leurs dépendances. De cette façon, vous aurez une application mieux concentrée et maintenable.
Si vous souhaitez en savoir plus sur DI, Alejandro Gervassio l'a couvert largement et professionnellement dans cette série, alors assurez-vous de lire ces articles. Maintenant, qu'en est-il du CIO? Le CIO (inversion du contrôle) n'est pas nécessaire pour utiliser l'injection de dépendance, mais cela peut vous aider à gérer efficacement vos dépendances.
IOC est un composant simple qui rend la résolution des dépendances plus pratique. Vous décrivez vos objets au conteneur, et chaque fois que vous résolvez une classe, les dépendances sont injectées automatiquement.
Laravel IOC est en quelque sorte spécial avec sa façon de résoudre les dépendances, lorsque vous demandez un objet:
Nous utiliserons un exemple simple que nous améliorerons au cours de cet article.
La classe SimpleAuth a une dépendance de FileSessionStorage, donc notre code peut ressembler à ceci:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>$this->connection = new Connection; </span> <span>} </span> <span>public function retrieveByCredentials( array $credentials ){ </span> <span>$user = $this->connection </span> <span>->where( 'email', $credentials['email']) </span> <span>->where( 'password', $credentials['password']) </span> <span>->first(); </span> <span>return $user; </span> <span>} </span><span>}</span>
C'est la façon classique de le faire, commençons par utiliser l'injection de constructeur.
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
Maintenant, nous créons notre objet:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function setConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
Maintenant, je veux utiliser Laravel IOC pour gérer tout cela.
Étant donné que la classe d'application étend la classe de conteneurs, vous pouvez toujours accéder au conteneur via la façade de l'application.
<span>interface ConnectionInjector{ </span> <span>public function injectConnection( Connection $con ); </span><span>} </span> <span>class UserProvider implements ConnectionInjector{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function injectConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span><span>}</span>
Le premier paramètre pour la méthode Bind est un ID unique pour se lier au conteneur, le second est une fonction de rappel à exécuter chaque fois que nous résolvons la classe FilesSessionStorage, nous pouvons également passer une chaîne représentant le nom de classe comme nous le verrons Suivant.
Remarque: Si vous inspectez les packages Laravel, vous le ferez, les liaisons sont parfois groupées comme (vue, vue.finder ..).
Disons que nous voulons peut-être changer notre stockage de session à MySQL, notre classe devrait être similaire à:
<span>class FileSessionStorage{ </span> <span>public function __construct(){ </span> <span>session_start(); </span> <span>} </span> <span>public function get( $key ){ </span> <span>return $_SESSION[$key]; </span> <span>} </span> <span>public function set( $key, $value ){ </span> <span>$_SESSION[$key] = $value; </span> <span>} </span><span>} </span> <span>class SimpleAuth{ </span> <span>protected $session; </span> <span>public function __construct(){ </span> <span>$this->session = new FileSessionStorage; </span> <span>} </span><span>} </span> <span>//creating a SimpleAuth </span><span>$auth = new SimpleAuth();</span>
Maintenant que nous avons changé la dépendance, nous devons modifier le constructeur SimpleAuth et lier un nouvel objet au conteneur!
Les modules de haut niveau ne devraient pas dépendre de modules de faible niveau. Les deux
devrait dépendre des abstractions.
Les abstractions ne devraient pas dépendre des détails. Les détails devraient dépendre
sur les abstractions.Robert C. Martin
Notre classe SimpleAuth ne devrait pas être préoccupée par la façon dont notre stockage est effectué, mais il devrait plutôt se concentrer davantage sur la simple consommation du service.
afin que nous puissions résumer notre implémentation de stockage:
<span>class SimpleAuth{ </span> <span>protected $session; </span> <span>public function __construct( FileSessionStorage $session ){ </span> <span>$this->session = $session; </span> <span>} </span><span>}</span>
De cette façon, nous pouvons simplement implémenter et demander une instance de l'interface SessionStorage:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>$this->connection = new Connection; </span> <span>} </span> <span>public function retrieveByCredentials( array $credentials ){ </span> <span>$user = $this->connection </span> <span>->where( 'email', $credentials['email']) </span> <span>->where( 'password', $credentials['password']) </span> <span>->first(); </span> <span>return $user; </span> <span>} </span><span>}</span>
Si nous essayons de résoudre la classe SimpleAuth via le conteneur à l'aide de App :: Make ('SimPleAuth'), le conteneur lancera une liaison de liaison toutes les dépendances.
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
Le conteneur essaie d'instancier l'interface. Nous pouvons résoudre ce problème en créant une liaison spécifique pour notre interface.
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function setConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
Maintenant, chaque fois que nous essayons de résoudre l'interface via le conteneur, nous obtiendrons une instance MySQLSessionStorage. Si nous voulons changer notre service de stockage, nous pouvons simplement mettre à jour les liaisons.
Remarque: si vous souhaitez voir si une classe est liée au conteneur, vous pouvez utiliser l'application :: Bound ('className') ou utiliser l'application :: bindif ('className') pour enregistrer une liaison si elle n'a pas eu T a déjà été enregistré.
Laravel IOC propose également l'application :: singleton ('classname', 'résolver') pour les liaisons partagées.
Vous pouvez également utiliser App :: instance ('className', 'instance') pour créer une instance partagée.
Si le conteneur ne peut pas résoudre la dépendance, il lancera une conception de réflexion, mais nous pouvons utiliser l'application :: ResolvvingAny (fermeture) pour résoudre un type donné ou comme une forme de secours.
Remarque: Si vous enregistrez un résolveur pour un type donné, la méthode ResolvvingAny sera également appelée, mais la valeur de la méthode de liaison est renvoyée.
Comme toujours, la meilleure façon de savoir quelque chose est d'inspecter le code source. Laravel IOC n'est qu'un fichier et ne devrait pas vous emmener longtemps pour passer par toutes les fonctions. Souhaitez-vous en savoir plus sur Laravel IOC ou IOC en général? Faites-nous savoir!
La dépendance dans le CIO de Laravel (inversion du contrôle) est un modèle de conception qui permet le découplage des dépendances codées durs. Cela signifie qu'au lieu d'avoir vos objets à créer une dépendance ou à demander à un objet d'usine d'en faire un, vous passez les dépendances nécessaires dans l'objet à l'extérieur. Cela rend votre code plus flexible, réutilisable et plus facile à tester car vous pouvez contrôler les dépendances à partir de l'extérieur de la classe.
Le conteneur IOC de Laravel est un outil puissant pour gérer les dépendances des cours. Il contrôle comment les différents objets sont résolus et créés. Lorsqu'une classe a des dépendances, le conteneur les injecte automatiquement lorsque la classe est instanciée. Cela se fait via un processus appelé «câblage automatique», où le conteneur inspecte la classe pour déterminer automatiquement les dépendances.
à lier un service au conteneur IOC de Laravel, vous pouvez utiliser la méthode de liaison. Cette méthode accepte deux arguments: le nom de classe ou d'interface qui sera utilisé lors de la résolution du service et une fermeture qui renvoie une instance de la classe. La fermeture recevra l'instance de conteneur, vous permettant de résoudre toutes les autres dépendances nécessaires pour instancier la classe.
La différence entre Bind Et Singleton dans le conteneur IOC de Laravel réside dans la façon dont les instances sont gérées. Lorsque vous liez un service, une nouvelle instance du service sera créée chaque fois que vous la résolvez. D'un autre côté, lorsque vous utilisez Singleton, la même instance sera retournée à chaque fois que le service est résolu.
Pour résoudre un service Dans le conteneur IOC de Laravel, vous pouvez utiliser la méthode de fabrication. Cette méthode accepte le nom du service à résoudre comme son argument. Si le service a été lié au conteneur, il renverra une instance du service, avec toutes ses dépendances automatiquement injectées.
L'injection de dépendance s'améliore-t-elle Tester à Laravel en rendant votre code plus flexible et découplé. Cela signifie que vous pouvez facilement échanger des dépendances avec des objets simulés lors des tests. Cela facilite l'isolat du code du test et de contrôler l'environnement de test.
Oui, vous pouvez utiliser la liaison d'interface dans le conteneur IOC de Laravel . Cela vous permet de lier une interface à une implémentation donnée. Ensuite, chaque fois que l'interface est demandée, le conteneur injectera l'implémentation liée.
Le conteneur IOC de Laravel gère la résolution automatique en utilisant la réflexion pour inspecter les dépendances d'une classe. Lorsque vous essayez de résoudre une classe, le conteneur construira automatiquement et injectera toutes les dépendances dont la classe a besoin.
Un fournisseur de services dans le CIO de Laravel Le conteneur est un moyen de grouper les inscriptions du CIO liées à un seul endroit. Ils sont l'endroit central pour configurer votre application. Chaque application Laravel comprend un certain nombre de fournisseurs de services hors de la boîte pour les services de base.
Pour enregistrer un fournisseur de services dans le conteneur IOC de Laravel, vous pouvez l'ajouter au tableau des fournisseurs dans le fichier de configuration config / app.php. Une fois le fournisseur de services enregistré, il sera enraciné par Laravel lorsque l'application sera amorti.
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!