Donc, je sais théoriquement ce qu'est une classe proxy dans Magento 2. J'ai lu le génial article d'Alan Storm à ce sujet et je comprends parfaitement comment ces classes sont générées.
Cependant, et je ne sais pas si c'est parce que je ne parle pas anglais ou si les explications d'Alan utilisent des classes non fondamentales qui sont très abstraites, mais j'ai du mal à comprendre comment cela fonctionne et surtout quand utiliser pendant le développement.
Prenons donc cet exemple du noyau dans app/code/Magento/GoogleAdwords/etc/di.xml
:
<?xml version="1.0"?>
<!--
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\GoogleAdwords\Observer\SetConversionValueObserver">
<arguments>
<argument name="collection" xsi:type="object">Magento\Sales\Model\ResourceModel\Order\Collection\Proxy</argument>
</arguments>
</type>
</config>
J'aimerais savoir:
- pourquoi une classe proxy est utilisée dans ce cas particulier?
- quand, en général, faut-il utiliser une classe proxy?
la source
Une classe proxy vous permet d'injecter en dépendance une classe dont vous n'avez pas nécessairement besoin, et qui a un coût élevé associé à le faire.
Si vous regardez un proxy que Magento a généré,
\Magento\Framework\View\Layout\Proxy
vous verrez qu'il a toutes les mêmes méthodes que la classe d'origine. La différence est que chaque fois que l'un de ceux-ci est appelé, il vérifie si la classe dont il est un proxy a réellement été instancié et crée l'objet sinon. (Cela se produit dans une méthode_getSubject()
ou_getCache()
.)C'est un chargement paresseux pour l'injection de dépendances.
Vous devez utiliser un proxy si une dépendance de classe n'est pas toujours utilisée par votre classe et:
Un bon exemple de ceci est les sessions. Obtenir des sessions via l'ObjectManager est une mauvaise pratique, mais injecter une classe de session comme
\Magento\Customer\Model\Session
pourrait casser des choses si votre classe s'exécute jamais en dehors de la portée de cette session (par exemple, vous injectez la session client frontale sur une page d'administration). Vous pouvez contourner cela en injectant le proxy de la session à la\Magento\Customer\Model\Session\Proxy
place et en le référençant uniquement lorsque vous savez qu'il est valide. Sauf si vous y faites référence, la session n'est jamais instanciée et rien ne se casse.Dans votre exemple spécifique de
di.xml
, il semble qu'ils aient utilisé le proxy pour justifier l'injection d'un contrôleur plutôt que la fabrique de ce contrôleur. Quoi qu'il en soit, ce n'est pas à cela que les procurations sont destinées et le bénéfice de celui-ci dans cette situation est probablement minime.la source
Les proxys autogénérés de type Magento 2 peuvent être utilisés pour "corriger" les erreurs de conception. Cela peut être très pratique. Il existe 2 cas d'utilisation:
Enveloppez un graphique d'objet coûteux qui pourrait ne pas être nécessaire à chaque fois par la personne à charge.
Briser une dépendance cyclique où la classe
A
dépendB
et la classeB
dépend d'unA
.L'injection
B\Proxy
dansA
vous permet d'instancierA
, qui à son tour peut être utilisé pour instancierB
quand il est réellement utilisé avec l'A
objet réel .Dans le cas de 1. la dépendance qui n'est pas toujours utilisée est un signe que la classe dépendante fait trop, ou peut-être beaucoup par une méthode. La commande de console @ivan mentionnée en est un bon exemple.
Dans le cas de 2. Je ne connais pas de moyen générique de briser cette dépendance. J'ai tendance à réécrire s'il reste du temps, mais ce n'est peut-être pas une option.
Juste comme note latérale, je voudrais ajouter qu'il existe beaucoup plus de types de proxy dans la POO que l'instanciation paresseuse générée automatiquement que Magento 2 utilise (par exemple, un proxy distant).
la source
Voici les réponses
pourquoi une classe proxy est utilisée dans ce cas particulier?
Si vous regardez attentivement le code ci-dessous qui est écrit pour la classe "SetConversionValueObserver", si Google Adwards n'est pas actif "retour" et s'il n'y a pas d'ordre "retour". Moyens, l'objet de collecte de commandes ne sera créé que lorsque les identifiants de commande existent et que les adwords Google sont actifs. si nous injectons la classe de collection Order réelle, le gestionnaire d'objets crée un objet de collection avec ses objets de classe parent sans savoir que Google AdWords n'est pas actif et ralentit la page de réussite de la commande. ainsi, mieux créer un objet à la demande qui est l'utilisation d'un proxy. /vendor/magento/module-google-adwords/Observer/SetConversionValueObserver.php
quand, en général, faut-il utiliser une classe proxy? - Injectez la classe Proxy lorsque vous pensez que la création d'objets sera coûteuse et que le constructeur de la classe est particulièrement gourmand en ressources. - lorsque vous ne voulez pas d'impact inutile sur les performances en raison de la création d'objets. - lorsque vous sentez que la création d'objet doit se produire lorsque vous appelez une méthode particulière dans une condition particulière, pas toujours. Par exemple, le constructeur de mise en page est gourmand en ressources.
Constructeur de mise en page réel vs mise en page / proxy
Constructeur proxy, jetez un oeil, aucun constructeur parent appelé ainsi que le nom de classe de disposition juste passé afin que la création d'objet réelle se produise lors de l'appel de la méthode.
La classe proxy a une méthode pour créer un objet à la demande, _subject est l'objet de la classe passée.
Et la méthode appelée using _subject.
la source