Ayudantes de instanciación en Magento 2

26

Las últimas versiones de Magento 2 han eliminado la Mageclase. Esto significa que hemos perdido el Mage::helpermétodo.

¿Existe una técnica de reemplazo (fábrica de ayudantes) para crear instancias de ayudantes en Magento 2? ¿O se espera que usemos la nueva clase de administrador de objetos y solo creemos una instancia del ayudante como un objeto único / en caché con get(vs. create)

Alan Storm
fuente

Respuestas:

31

Veo que llegaste a la solución correcta, solo quiero resumir.

La inyección de constructor debe usarse para recuperar ayudante (o cualquier otra instancia) en cualquier clase que necesite:

class SomeClass
{
    public function __construct(\Magento\Core\Helper\Data $helper)
    {
        $this->helper = $helper;
    }

    public function doSmth()
    {
        $this->helper->someMethod();
    }
}

Tenga en cuenta que no se requieren comentarios phpDoc , Magento leerá la firma del constructor directamente para determinar qué dependencias se requieren.

\ Magento \ Core \ Helper \ Factory solo debe usarse en esos casos excepcionales en los que tiene que llamar a muchos ayudantes múltiples, o no sabe exactamente cuál necesita.

Se desaconseja estrictamente el uso de Object Manager directamente . Así que por favor evite usar:

\Magento\Core\Model\ObjectManager::getInstance()

Está ahí solo para la serialización / deserialización.

Anton Kril
fuente
no use static, ya que no se puede probar con la unidad PHP y sí, se desaconseja. Todas las dependencias de M2 ​​se realizan a través del constructor, y son administradas internamente por el Administrador de objetos, y lo recuperarán como Singleton. Tampoco use _ para indicar una visibilidad de la propiedad, Todos los nombres de M2 ​​deben usar el camecase
PartySoft
@Anton Kril si usamos helperen plantilla, ¿ $this->helper('Magento\Catalog\Helper\Image')sigue la mejor práctica?
Khoa TruongDinh
2
No, no lo hace. Las plantillas solo deben hacer referencia a bloques. Deben evitarse los ayudantes
Anton Kril
10

Parece que las personas alentadoras de Magento usan su nuevo sistema de inyección de dependencia automática para obtener ayudantes y modelos en objetos a través del constructor del objeto.

La versión corta? Si tiene un objeto instanciado por el administrador de objetos y decora un constructor con un PHPDoc@param , y los parámetros tienen un conjunto de sugerencias de tipo adecuado, el administrador de objetos creará una instancia automática del ayudante (o, creo, otros objetos) para usted.

Por ejemplo, el siguiente constructor inyectaría un ayudante de datos centrales en el objeto.

/**
* @param \Magento\Core\Helper\Data $coreData
*/        
public function __construct(\Magento\Core\Helper\Data $coreData)
{
    $this->_coreHelper = $coreData;            
}
Alan Storm
fuente
Esta es la respuesta correcta: gran investigación; No era totalmente obvio para mí, incluso después de mucho cavar.
philwinkle
2
OK ... ahora me duele la cabeza ... mucho. ¿Quiere decir que se supone que debemos usar PHPDoc para "escribir" código? Esto es una locura. Lo dejo.
Marius
@Marius jajaja, esto no es tan raro: el blog de Alan lo explica en cierta medida
philwinkle
3
@philwinkle. He leído su artículo. Muy interesante, pero aún digo que esto es una locura. Llámame anticuado, pero el código "en mis días" era código y los comentarios eran cosas que casi nadie se molestaba en escribir.
Marius
Oh, y a propósito. +1. Buena pregunta y buena respuesta.
Marius
7

Además de todas las respuestas anteriores, si tiene que usar helper en la plantilla phtml, simplemente puede hacer lo siguiente:

$this->helper('[Vendor]\[Module]\Helper\[Helper Name]');

Espero que sea útil si alguien no lo sabía antes;)

rbncha
fuente
6

La forma en que se instancian los ayudantes (al menos para el nuevo módulo Backend (~ dev50)) es a través de un helperFactory:

/**
 * Return helper object
 *
 * @param string $name
 * @return \Magento\Core\Helper\AbstractHelper
 */
public function helper($name)
{
    return $this->_helperFactory->get($name);
}

Que es esencialmente solo un tipo especializado de una fábrica de modelos. Por ejemplo: Magento \ Core \ Block \ Context line 143 (dev50) como parte del constructor:

\Magento\Core\Model\Factory\Helper $helperFactory

La fábrica de ayuda devolverá el modelo solicitado en función del nombre de la clase y se asegurará de que sea una instanceofclase abstracta de ayuda:

/**
 * Get helper singleton
 *
 * @param string $className
 * @param array $arguments
 * @return \Magento\Core\Helper\AbstractHelper
 * @throws \LogicException
 */
public function get($className, array $arguments = array())
{
    $className = str_replace('_', '\\', $className);
    /* Default helper class for a module */
    if (strpos($className, '\Helper\\') === false) {
        $className .= '\Helper\Data';
    }

    $helper = $this->_objectManager->get($className, $arguments);

    if (false === ($helper instanceof \Magento\Core\Helper\AbstractHelper)) {
        throw new \LogicException(
            $className . ' doesn\'t extends Magento\App\Helper'
        );
    }

    return $helper;
}

Si tuviera que implementar esto usted mismo , parece que el núcleo de Magento lo está cargando de una de dos maneras:

Ruede su propia fábrica:

$objectManager = \Magento\Core\Model\ObjectManager::getInstance();

$helperFactory = $objectManager->get('\Magento\Core\Model\Factory\Helper');
$helper = $helperFactory->get('\PulseStorm\Commercebug\Helper\Data');

O simplemente tómalo directamente:

$helper = \Magento\Core\Model\ObjectManager::getInstance()->get('Magento\Core\Helper\Data');
philwinkle
fuente
1
+1 para obtener información útil, pero ¿le gustaría crear una instancia de la fábrica directamente así? ¿O se debe crear una instancia de una sola fábrica auxiliar con Object Manager como una clase en caché get?
Alan Storm
No está totalmente claro, porque la fábrica de ayuda se hereda de \ Mage \ Core \ Block \ Abstract: creo que la intención es proporcionar su propia fábrica de ayuda. Sin embargo, no parece que estén creando intencionalmente un singleton para la fábrica.
philwinkle
Parece que necesito / la mejor fuente es rastrear cómo se inyecta _helperFactory en esos objetos y ver cómo el equipo central lo instancia.
Alan Storm
Mi resumen de simplificación es incorrecto y el constructor requiere una instancia de ObjectManager. Lo editaré momentáneamente.
philwinkle
Ver editar. Debería funcionar, difícil de determinar en este momento porque mi entorno de cli shell no está cargando la instancia de configuración de la tienda como se esperaba. Sin embargo, esto debería ser suficiente para llevarte por el camino correcto.
philwinkle
0

Intenta de esta manera

$helper = \Magento\Framework\App\ObjectManager::getInstance()->get('Xx\Xx\Helper\Xx');
Thushan
fuente
Se desaconseja estrictamente el uso de Object Manager directamente.
sv3n
@ sv3n ¿podría explicar, por qué? Gracias.
Así,
1
Mejor usar inyecciones de dependencia en su lugar ... respondido aquí, por ejemplo ... magento.stackexchange.com/questions/142352/…
sv3n