Instanciando ajudantes no Magento 2

26

As últimas versões do Magento 2 acabaram com a Mageclasse. Isso significa que perdemos o Mage::helpermétodo.

Existe uma técnica de substituição (fábrica de auxiliares?) Para instanciar ajudantes no Magento 2? Ou devemos usar a nova classe do gerenciador de objetos e instanciar o auxiliar como um objeto singleton / em cache com get(vs. create)

Alan Storm
fonte

Respostas:

31

Vejo que você veio à solução certa, só quero resumir.

A injeção de construtor deve ser usada para recuperar o auxiliar (ou qualquer outra instância) em qualquer classe que você precisar:

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

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

Observe que nenhum comentário do phpDoc é necessário , o Magento lerá a assinatura do construtor diretamente para descobrir quais dependências são necessárias.

\ Magento \ Core \ Helper \ Factory deve ser usado apenas em casos raros, quando você precisar chamar muitos auxiliares ou não souber exatamente qual deles precisa.

O uso do Object Manager diretamente é estritamente desencorajado . Portanto, evite usar:

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

Está lá apenas para serialização / desserialização.

Anton Kril
fonte
não use estática, pois não pode ser testado com a unidade PHP e sim, é desencorajado. Todas as dependências M2 são feitas através do construtor, e gerenciado pelo Gerenciador de objetos internamente, e vai baixá-la como Singleton Também não use _ para indicar uma visibilidade propriedade, All M2 nomeação deve usar o camecase
PartySoft
@ Anton Kril se usarmos helperno modelo, como $this->helper('Magento\Catalog\Helper\Image'), segue as melhores práticas?
precisa saber é o seguinte
2
Não, não tem. Os modelos devem fazer referência apenas aos blocos. Ajudantes deve ser evitado
Anton Kril
10

Parece que o pessoal do Magento usa seu novo sistema de injeção automática de dependências para levar ajudantes e modelos para objetos através do construtor do objeto.

A versão curta? Se você tiver um objeto instanciado pelo gerenciador de objetos e decorar um construtor com um PHPDoc@param , e os parâmetros tiverem uma dica de tipo adequada, o gerenciador de objetos instanciará automaticamente o auxiliar (ou, acredito, outros objetos) para você.

Por exemplo, o construtor a seguir injeta um auxiliar de dados principais no objeto.

/**
* @param \Magento\Core\Helper\Data $coreData
*/        
public function __construct(\Magento\Core\Helper\Data $coreData)
{
    $this->_coreHelper = $coreData;            
}
Alan Storm
fonte
Esta é a resposta correta - excelente investigação; não era totalmente óbvio para mim, mesmo depois de muita pesquisa.
philwinkle
2
OK ... agora minha cabeça dói ... muito. Você quer dizer que devemos usar o PHPDoc para "escrever" código? Isso é loucura. Eu desisto.
Marius
@ Marius hahaha isso não é incomum - o blog de Alan explica isso até certo ponto.
philwinkle
3
@philwinkle. Eu li o artigo dele. Muito interessante, mas ainda digo que isso é loucura. Me chame de antiquado, mas o código "antigamente" era código e comentários eram coisas que quase ninguém se importava em escrever.
Marius
Ah, e falando nisso. +1. Boa pergunta e boa resposta.
Marius
7

Além de todas as respostas acima, se você precisar usar o helper no modelo phtml, poderá simplesmente fazer o seguinte:

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

Espero que seja útil se alguém não soubesse antes;)

rbncha
fonte
6

A maneira como os auxiliares são instanciados (pelo menos para o novo módulo Back-end (~ dev50)) é por meio de um helperFactory:

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

Que é essencialmente apenas um tipo especializado de uma fábrica de modelos. Por exemplo: Magento \ Core \ Block \ Context linha 143 (dev50) como parte do construtor:

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

A fábrica auxiliar ajudará o modelo solicitado com base no nome da classe e garantirá que seja uma instanceofclasse abstrata auxiliar:

/**
 * 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;
}

Se você implementou isso sozinho , parece que o núcleo do Magento está carregando de uma de duas maneiras:

Role sua própria fábrica:

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

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

Ou simplesmente pegue-o diretamente:

$helper = \Magento\Core\Model\ObjectManager::getInstance()->get('Magento\Core\Helper\Data');
philwinkle
fonte
11
+1 para obter informações úteis, mas você gostaria de instanciar a fábrica diretamente assim? Ou uma única fábrica auxiliar deve ser instanciada com o Gerenciador de Objetos como uma classe em cache get?
Alan Storm
Não está totalmente claro, porque a fábrica auxiliar é herdada de \ Mage \ Core \ Block \ Abstract - acho que a intenção é fornecer sua própria fábrica auxiliar. Ele não parecem que estão criando intencionalmente um singleton para a fábrica, no entanto.
philwinkle
Parece que eu preciso / a melhor fonte é rastrear como _helperFactory é injetado nesses objetos e ver como a equipe principal a instancia.
Alan Storm
Meu resumo de simplificação está incorreto, assim como o construtor requer uma instância do ObjectManager. Vou editar momentaneamente.
philwinkle
Veja editar. Deveria ser difícil determinar neste momento, porque meu ambiente cli shell não está carregando a instância de configuração da loja conforme o esperado. Isso deve ser suficiente para você seguir o caminho certo.
philwinkle
0

Tente desta maneira

$helper = \Magento\Framework\App\ObjectManager::getInstance()->get('Xx\Xx\Helper\Xx');
Thushan
fonte
O uso do Object Manager diretamente é estritamente desencorajado.
sv3n 23/02
@ sv3n você poderia explicar, qual o motivo? Obrigado.
Thushan
11
Melhor usar injeções de dependência em vez disso ... respondidas aqui por exemplo ... magento.stackexchange.com/questions/142352/…
sv3n 25/02