Ok, donc hier nous avons eu une grosse discussion avec d’autres membres de la communauté Magento concernant l’ utilisation directe de ObjectManager
in classes / modèles .
Je connais déjà les raisons pour lesquelles nous ne devrions pas utiliser directement ObjectManager, citant Alan Kent :
Il y a plusieurs raisons. Le code fonctionnera, mais il est recommandé de ne pas référencer directement la classe ObjectManager.
- Parce que nous le disons! ;-) (mieux exprimé car un code cohérent est un bon code)
- Le code pourrait être utilisé avec un cadre d'injection de dépendance différent à l'avenir
- Le test est plus simple : vous passez des arguments fictifs pour la classe requise sans devoir fournir d'objet fictif.
- Les dépendances restent plus claires - il est évident que le code dépend de la liste de constructeurs, plutôt que d'avoir des dépendances cachées au milieu du code
- Cela encourage les programmeurs à mieux réfléchir aux concepts tels que l'encapsulation et la modularisation - si le constructeur grand, c'est peut-être un signe que le code doit être refactorisé.
D'après ce que j'ai vu dans StackExchange, beaucoup de gens ont tendance à opter pour la solution facile / courte / non recommandée, par exemple quelque chose comme ceci:
<?php
//Get Object Manager Instance
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
//Load product by product id
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($id);
Au lieu de passer par le processus douloureux mais recommandé de:
- créer un module
- déclarer ses préférences
- injecter des dépendances
- déclarer une méthode publique
Cependant, et voici le dilemme, les fichiers de base de Magento 2 appellent souvent directement ObjectManager . Vous trouverez un exemple rapide ici: https://github.com/magento/magento2/blob/develop/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php#L57
Donc, voici mes questions:
- Pourquoi Magento fait-il ce qu'ils nous recommandent de ne pas faire? Cela signifie-t-il qu'il y a des cas où nous devrions utiliser le
ObjectManager
logiciel directement ? Si oui, quels sont ces cas? - Quelles sont les conséquences de l'utilisation directe d'ObjectManager ?
la source
The intent of zend-servicemanager is for use as an Inversion of Control container. It was never intended as a general purpose service locator [...]
. Cela s'applique également à M2. Consultez également laThere are valid use cases
section, qui, là encore, s’applique ici.Réponses:
Vous ne devez pas utiliser directement ObjectManager!
Les exceptions à la règle sont:
__wakeup
,serialize
etc.la source
Réponse brutale: M2 est un portage de M1 - pas une réécriture complète. Donc, ne supposez pas que tout le code M2 est parfaitement porté (malheureusement). Ce n'est pas parce que vous trouvez quelque chose dans la base de code M2 que c'est "la meilleure façon de le faire". Parfois, c’est juste "nous n’avons pas encore pris le temps de le réparer".
Moins brutal: comme d’autres réponses, vous DEVEZ l’utiliser car il n’ya pas d’alternative. D'autres fois, cela pourrait être pour des raisons de compatibilité ascendante. Et le code-cadre a parfois du sens de l'utiliser directement, car c'est un code-cadre. Mais si je devais deviner sans regarder le code, beaucoup devraient vraiment être corrigés, mais la priorité n’a pas été suffisamment élevée pour le faire pour le moment.
Rappelez-vous simplement le bon conseil parental: "Enfants, faites ce que je dis, pas ce que je fais!"
la source
Vous ne devriez jamais utiliser
\Magento\Framework\App\ObjectManager::getInstance()
.Il va à l'encontre du but de l'injection de dépendance. Nous sommes de retour à
Mage::getModel()
.Le gestionnaire d'objets ne doit être utilisé que dans les usines, puis injecté dans un constructeur.
L'avantage d'utiliser ceci est moins de code à écrire. Mais cela ne le rend pas OK.
Le fait que cela soit toujours utilisé dans le noyau, c'est parce que ça n'a pas encore été refactorisé. J'espère que ça va être.
la source
di.xml
pour créer une carte clé => nom de classe, injecter cette carte dans le constructeur de la fabrique et utiliser la fabrique pour instancier la classe via objectmanagerSans connaître toute l'histoire, voici ce que je suppose:
Au cours du développement de l'équipe M2 Magento à un moment a couru un script automatisé qui a remplacé les occurrences de
Mage:getModel()
,Mage::getSingleton()
,$layout->createBlock()
, etc. utiliser le ObjectManager.Un refactoring ultérieur aurait dû résoudre ce problème pour utiliser à la place l'injection de dépendance appropriée, mais le temps et les ressources étaient insuffisants pour convertir toutes les occurrences.
De plus, l'équipe de Magento semble récemment utiliser cela comme un mécanisme d'évasion. Au lieu de casser une implémentation existante (en changeant le constructeur), ils cachent simplement la nouvelle dépendance via le gestionnaire d’objets. Je ne peux pas dire que je suis d'accord avec cette approche - écrire un code pire pour éviter une pause en Colombie-Britannique.
Je pense que votre question comprend déjà suffisamment de raisons. Généralement, cela crée une dépendance cachée. En d'autres termes, la dépendance se trouve dans les détails de l'implémentation et n'est pas visible uniquement par le constructeur.
la source
Ne doit pas utiliser directement le gestionnaire d'objets!
Par exemple:
De même, si vous travaillez avec des observateurs d'événements ou des plug-ins, vous ne devez jamais l'utiliser directement.
Vous pouvez l'utiliser dans les usines, sauf que vous devez d'abord injecter le gestionnaire d'objets dans le constructeur, puis utiliser son objet dans votre méthode.
Préférable d'utiliser:
1) déclarer un objet privé:
2) injecter dans le constructeur et initialiser:
3) utiliser dans une méthode:
la source
::getInstance()
La principale raison pour laquelle il est fortement déconseillé aux développeurs d'utiliser directement le gestionnaire d'objets est que l'utilisation directe de ce dernier empêche l'installation de l'extension en mode de publication compilée.
Cela rompt donc pour vos clients utilisant le mode de publication, y compris tous les clients de Magento Cloud.
Il semble qu'une proportion assez importante de développeurs (environ 75%) ne testent pas leurs extensions pour savoir si elles peuvent être installées en mode de publication. Par conséquent, ne rencontrez pas les problèmes posés par une utilisation incorrecte de ObjectManager.
À partir de 2017, le marché Magento exécute un test de compilation et d'installation sur toutes les extensions vendues par son intermédiaire. Si votre extension utilise directement le gestionnaire d'objets, elle échouera à ces tests et sera rejetée de la place de marché jusqu'à ce que vous résolviez ce problème et effectuez un nouveau chargement.
la source
Vous pouvez essayer en créant un objet de objectManager et ne pas utiliser directement objectManager .
Utilisez quelque chose comme
la source