Ok, ontem tivemos uma grande conversa com outras pessoas da comunidade Magento sobre o uso direto do ObjectManager
nas aulas / modelos .
Eu já estou ciente dos motivos pelos quais não devemos usar o ObjectManager diretamente, citando Alan Kent :
Existem várias razões. O código funcionará, mas é uma prática recomendada não fazer referência diretamente à classe ObjectManager.
- Porque dizemos isso! ;-) (melhor expresso como código consistente é bom código)
- O código pode ser usado com uma estrutura de injeção de dependência diferente no futuro
- O teste é mais fácil - você passa argumentos simulados para a classe necessária, sem precisar fornecer um ObjectManager falso
- Mantém as dependências mais claras - é óbvio do que o código depende via lista de construtores, em vez de ter dependências ocultas no meio do código
- Incentiva os programadores a pensarem melhor em conceitos como encapsulamento e modularização - se o construtor crescer, talvez seja um sinal de que o código precisa ser refatorado
Pelo que vi no StackExchange, muitas pessoas tendem a procurar a solução fácil / curta / não recomendada, por exemplo, algo como isto:
<?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);
Em vez de passar pelo doloroso, mas recomendado, processo de:
- criando um módulo
- declarando preferências
- injetar dependências
- declarar um método público
No entanto, e aqui está o dilema, os arquivos principais do Magento 2 costumam chamar o ObjectManager diretamente . Um exemplo rápido pode ser encontrado aqui: https://github.com/magento/magento2/blob/develop/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php#L57
Então, aqui estão as minhas questões:
- Por que o Magento está fazendo o que eles recomendam que não façamos? Isso significa que existem alguns casos em que devemos usar o
ObjectManager
diretamente ? Se sim, quais são esses casos? - Quais são as consequências de usar o ObjectManager diretamente ?
fonte
The intent of zend-servicemanager is for use as an Inversion of Control container. It was never intended as a general purpose service locator [...]
. O que também se aplica ao M2. Verifique também aThere are valid use cases
seção, que novamente se aplica aqui também.Respostas:
Você não deve usar o ObjectManager diretamente!
As exceções da regra são:
__wakeup
,serialize
, etc.fonte
Resposta brutal: M2 é uma porta do M1 - não uma reescrita completa. Portanto, não assuma que todo o código M2 ainda esteja perfeitamente portado (infelizmente). Só porque você encontra algo na base de código M2, isso não significa "é a melhor maneira de fazê-lo". Às vezes, é apenas "ainda não conseguimos corrigi-lo".
Menos brutal: como em outras respostas, às vezes você DEVE usá-lo, pois não há alternativa. Outras vezes, pode ser por motivos de compatibilidade com versões anteriores. E o código da estrutura às vezes faz sentido usá-lo diretamente, porque é um código da estrutura. Mas se eu tivesse que adivinhar sem olhar para o código, muitos realmente deveriam ser corrigidos, mas ainda não foi uma prioridade alta o suficiente.
Lembre-se do bom conselho para os pais: "Crianças, façam o que eu digo, não o que eu faço!"
fonte
Você nunca deve usar
\Magento\Framework\App\ObjectManager::getInstance()
.Ele anula o objetivo da injeção de dependência. Estamos de volta às
Mage::getModel()
.O gerenciador de objetos deve ser usado apenas em fábricas e depois como injetado em um construtor.
A vantagem de usar isso é menos código para escrever. Mas isso não faz tudo certo.
O fato de isso ainda ser usado no núcleo é porque ainda não foi refatorado. Espero que seja.
fonte
di.xml
para criar um mapa key => class name e injetar esse mapa no construtor da fábrica e usar a factory para instanciar a classe através do gerenciador de objetosSem saber a história completa, aqui está o meu palpite:
Durante o desenvolvimento do M2 a equipe Magento em algum estágio correu um script automatizado que substituiu ocorrências
Mage:getModel()
,Mage::getSingleton()
,$layout->createBlock()
, etc, para usar o ObjectManager.A refatoração posterior deveria ter corrigido isso para usar a injeção de dependência adequada, mas não havia tempo / recursos suficientes para converter todas as ocorrências.
Além disso, a equipe do Magento recentemente parece usar isso como um mecanismo de fuga. Em vez de interromper uma implementação existente (precisando alterar o construtor), eles simplesmente ocultam a nova dependência por meio do ObjectManager. Não posso dizer que concordo com essa abordagem - escrever código pior para evitar uma quebra de BC.
Acho que sua pergunta já inclui motivos suficientes. Geralmente, ele cria uma dependência oculta; em outras palavras, a dependência está nos detalhes da implementação e não é visível apenas pelo construtor.
fonte
Não deve usar o gerenciador de objetos diretamente!
Por exemplo:
Além disso, se você estiver trabalhando com observadores de eventos ou plug-ins, nunca deve usá-lo diretamente.
Você pode usá-lo em Fábricas, mas, exceto que você deve injetar o Gerenciador de Objetos no Construtor primeiro, então você pode usar o objeto em seu método
Preferido para usar:
1) declarar objeto privado:
2) injete no construtor e inicialize:
3) use em algum método:
fonte
::getInstance()
O principal motivo pelo qual os desenvolvedores são fortemente desencorajados a usar o Gerenciador de Objetos diretamente é que o uso direto do Gerenciador de Objetos faz com que a extensão não seja instalável no modo de versão compilada.
Por isso, é importante para seus clientes usando o modo de liberação, incluindo todos os clientes no Magento Cloud.
Parece que uma proporção razoavelmente grande de desenvolvedores (aproximadamente 75%) não testa suas extensões para ver se elas podem ser instaladas no modo de liberação, portanto, não se deparem com os problemas causados pelo uso incorreto do ObjectManager.
A partir de 2017, o Magento Marketplace executa um teste de compilação e instalação em todas as extensões vendidas através dele. Se sua extensão usar o Gerenciador de Objetos diretamente, ela falhará nesses testes e será rejeitada no Marketplace até você resolver esse problema e fazer o upload novamente.
fonte
Você pode tentar criar um objeto de objectManager e não deve usá-lo diretamente .
Use algo como,
fonte