Ok, ayer tuvimos una gran conversación con otras personas de la comunidad de Magento sobre el uso directo de las ObjectManager
clases / plantillas .
Ya estoy al tanto de las razones por las que no deberíamos usar ObjectManager directamente, citando a Alan Kent :
Hay varias razones. El código funcionará, pero es una buena práctica no hacer referencia a la clase ObjectManager directamente.
- ¡Porque nosotros lo decimos! ;-) (mejor expresado como código consistente es un buen código)
- El código podría usarse con un marco de inyección de dependencia diferente en el futuro
- La prueba es más fácil : pasa argumentos simulados para la clase requerida, sin tener que proporcionar un ObjectManager simulado
- Mantiene las dependencias más claras : es obvio de qué depende el código a través de la lista de constructores, en lugar de tener dependencias ocultas en el medio del código
- Alienta a los programadores a pensar mejor en conceptos como la encapsulación y la modularización : si el constructor crece, tal vez sea una señal de que el código necesita refactorización
Por lo que he visto en StackExchange, muchas personas tienden a buscar la solución fácil / corta / no recomendada, por ejemplo algo como esto:
<?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);
En lugar de pasar por el doloroso pero recomendado proceso de:
- creando un módulo
- declarando preferencias
- inyectar dependencias
- declarar un método público
Sin embargo, y aquí viene el dilema, los archivos principales de Magento 2 a menudo llaman directamente al ObjectManager . Puede encontrar un ejemplo rápido aquí: https://github.com/magento/magento2/blob/develop/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php#L57
Asi que aqui están mis preguntas:
- ¿Por qué Magento hace lo que nos recomiendan que no hagamos? ¿Eso significa que hay algunos casos en los que deberíamos usar el
ObjectManager
directamente ? Si es así, ¿cuáles son esos casos? - ¿Cuáles son las consecuencias de usar ObjectManager directamente ?
fuente
The intent of zend-servicemanager is for use as an Inversion of Control container. It was never intended as a general purpose service locator [...]
. Lo cual se aplica también a M2. También revise laThere are valid use cases
sección, que, nuevamente, se aplica aquí también.Respuestas:
¡No deberías usar el ObjectManager directamente!
Las excepciones a la regla son:
__wakeup
,serialize
, etc.fuente
Respuesta brutal: M2 es un puerto de M1, no una reescritura completa. Por lo tanto, no asuma que todo el código M2 está perfectamente portado todavía (desafortunadamente). Solo porque encuentre algo en la base del código M2, eso no significa "es la mejor manera de hacerlo". A veces es simplemente "todavía no hemos podido arreglarlo".
Menos brutal: según otras respuestas, a veces DEBE usarlo ya que no hay alternativa. Otras veces puede ser por razones de compatibilidad con versiones anteriores. Y el código marco a veces tiene sentido usarlo directamente, porque es un código marco. Pero si tuviera que adivinar sin mirar el código, muchos realmente deberían repararse, pero aún no ha sido una prioridad lo suficientemente alta como para hacerlo.
Solo recuerde el buen consejo para padres: "¡Niños, hagan lo que digo, no lo que hago!"
fuente
Nunca deberías usar
\Magento\Framework\App\ObjectManager::getInstance()
.Derrota el propósito de la inyección de dependencia. Estamos de vuelta en
Mage::getModel()
.El administrador de objetos debe usarse solo en fábricas y luego como se inyecta en un constructor.
La ventaja de usar esto es menos código para escribir. Pero esto no lo hace correcto.
El hecho de que esto todavía se use en el núcleo es porque aún no se refactorizó. Yo espero que sea.
fuente
di.xml
para crear un mapa de nombre de clase => e inyectar ese mapa en el constructor de la fábrica y usar la fábrica para crear una instancia de la clase a través del administrador de objetosSin saber la historia completa aquí es mi suposición:
Durante el desarrollo del M2 del equipo de Magento en algún momento corrió un script automatizado que sustituyó ocurrencias de
Mage:getModel()
,Mage::getSingleton()
,$layout->createBlock()
, etc, para utilizar el ObjectManager.La refactorización posterior debería haber solucionado esto para usar la inyección de dependencia adecuada, pero no había suficiente tiempo / recursos para convertir todas las ocurrencias.
También el equipo de Magento últimamente parece usar esto como un mecanismo de escape. En lugar de romper una implementación existente (al necesitar cambiar el constructor), simplemente ocultan la nueva dependencia a través del ObjectManager. No puedo decir que esté de acuerdo con este enfoque: escribir un código peor para evitar una interrupción de BC.
Creo que su pregunta ya incluye suficientes razones. En general, crea una dependencia oculta, en otras palabras, la dependencia está en los detalles de implementación y no es visible solo desde el constructor.
fuente
¡No debería usar el Administrador de objetos directamente!
Por ejemplo:
Además, si está trabajando con observadores de eventos o complementos, nunca debe usarlo directamente.
Puede usarlo en Fábricas, pero excepto que primero debe inyectar el Administrador de objetos en el Constructor y luego puede usar su objeto en su método
Preferido de usar:
1) declarar objeto privado:
2) inyectar en el constructor e inicializar:
3) uso en algún método:
fuente
::getInstance()
La razón principal por la que se desaconseja encarecidamente a los desarrolladores el uso directo del Administrador de objetos es que el uso directo del Administrador de objetos hace que la extensión no sea instalable en el modo de lanzamiento compilado.
Por lo tanto, se rompe para sus clientes que usan el modo de lanzamiento, incluidos todos los clientes en Magento Cloud.
Parece que una proporción razonablemente grande de desarrolladores (aproximadamente el 75%) no prueba sus extensiones para ver si pueden instalarse en modo de lanzamiento, por lo que no se tope con los problemas que plantea el uso incorrecto de ObjectManager.
A partir de 2017, Magento Marketplace ejecuta una prueba de compilación e instalación en todas las extensiones vendidas a través de él. Si su extensión utiliza el Administrador de objetos directamente, fallará estas pruebas y será rechazado del Mercado hasta que resuelva este problema y vuelva a cargarlo.
fuente
Puede intentarlo creando un objeto de objectManager y no debe usar objectManager directamente .
Usa algo como,
fuente