Quando devemos usar um repositório e uma fábrica no Magento 2?

75

Passei por alguns tutoriais no Magento 2, e isso me confunde um pouco. Eu posso ver que existem basicamente duas maneiras pelas quais podemos ler / gravar entidades comerciais:

Recuperar dados

Usando uma abordagem de fábrica

$object = $this->myFactory->create();
$object->load($myId);

Usando uma abordagem de repositório

$repo   = $this->myRepository();
$object = $repo->getById($myId);

Guardar dados

Usando uma abordagem de fábrica

$object = $this->myFactory->create();
$object->load($myId);
$object->setData('something', 'somethingDifferent')->save();

Usando uma abordagem de repositório

$repo   = $this->myRepository();
$object = $repo->getById($myId);
$object->setData('something', 'somethingDifferent');
$repo->save($object);

Também vejo que tanto um repositório quanto uma classe de fábrica podem ser injetados usando injeção de dependência. Isso é confuso, pelo menos para mim.

Quando devemos usar uma abordagem de repositório e uma abordagem de fábrica? Qual é a melhor prática que precisamos seguir?

Rajeev K Tomy
fonte
Um bom exemplo de uso de Factory, CollectionFactory e Repository pode ser visto em \ Magento \ Setup \ Fixtures \ CategoryResolver
Ricardo Martins

Respostas:

72

Se houver um repositório e ele fizer o que você precisa bem, sempre prefira o repositório.

Os repositórios fazem parte dos Contratos de Serviço (são implementações de interfaces Api), o que significa que são uma interface pública para outros módulos.

Use Repositórios para carregamento completo

$model->load()não faz parte do contrato de serviço. Eu tinha uma pergunta sobre esse tópico em particular, você pode encontrar as respostas úteis: Existe alguma razão para preferir $ model-> load () sobre contratos de serviço?

Use Fábricas para criar novas entidades

Os repositórios não vêm com métodos para criar uma nova entidade; portanto, nesse caso, você precisará de uma fábrica. Mas use a fábrica para a interface , como Magento\Catalog\Api\Data\ProductInterfaceFactory- ela criará a implementação correta com base na configuração da DI.

Em seguida, use o repository->save()método para salvá-lo.

Use fábricas de cobrança se precisar de mais controle

A seguir, não é uma boa prática oficial do Magento, mas atualmente, os repositórios não oferecem um bom controle sobre o que carregar. A API de critérios de pesquisa permite definir filtros, mas, por exemplo, não há como selecionar atributos EAV específicos ou especificar quais tabelas de índice ingressar.

Esses são os detalhes da implementação, ocultos nas APIs do contrato de serviço, mas geralmente esses detalhes da implementação são importantes e você obtém um desempenho ruim se os ignorar. Por esse motivo, assim que os repositórios estão me limitando, não hesito mais em usar as coleções subjacentes.

Fabian Schmengler
fonte
2
Você poderia dar um exemplo de código sobre o uso de Fábricas para criar novas entidades , a explicação não contém alguns detalhes e é difícil de entender. Muito obrigado.
Key Shang
1
@Key isso ajuda? devdocs.magento.com/guides/v2.2/extension-dev-guide/…
Fabian Schmengler
Obrigado. mas esse use the factory for the interface, such as Magento\Catalog\Api\Data\ProductInterfaceFactory - it will create the right implementation based on DI configuration.é o ponto que eu não consigo entender, os guias de desenvolvimento não apresentam o InterfaceFactory , como usar o repository->save()método para salvar novas entidades? Só posso usar o factory para salvar novas entidades, não o repositório.
Key Shang
@Key Shang, significa que a interface fornecerá todas as funções de dados definidas para salvar cada coluna da tabela; portanto, tente usar a interface sempre que possível para salvar novos registros. As classes InterfaceFactory são criadas como parte do di: compile, para que você possa vê-las na pasta var / generation.
stevensagaar
@stevensagaar Obrigado, eu posso entender isso agora.
Key Shang
21

Boa pergunta.

Mesmo que Repositórios e Fábricas nos permitam acessar uma Entidade, acho que devemos nos concentrar em suas responsabilidades .

Da documentação do Magento : "Fábricas são classes de serviço que instanciam classes não injetáveis, ou seja, modelos que representam uma entidade de banco de dados. Eles criam uma camada de abstração entre o ObjectManager e o código comercial".

No artigo de Alan Storm : "Um objeto de repositório é responsável por ler e gravar as informações do objeto em um armazenamento de objetos"

Minha interpretação é: Se nosso objetivo é trabalhar com objetos não injetáveis ​​(chamados de "novos"), devemos usar Fábricas; se nosso foco estiver na pesquisa / leitura / gravação de objetos em um armazenamento de objetos, devemos usar Repositórios.

Esta é minha abordagem idealista ao tópico; tenha em mente que a implementação real pode nos forçar a atrapalhar as coisas, como apontado por Alan.

Desfrutar.

Alessandro Ronchi
fonte
5

Eu diria que o caminho a seguir é começar a usar repositórios, pois eles permitem a separação de código entre leitura / gravação de dados e lógica de negócios.

Há um artigo muito detalhado, escrito por Alan Storm, explicando como usar repositórios, mas também analisando algumas desvantagens desse novo método: http://alanstorm.com/magento_2_understanding_object_repositories/

Além disso, na documentação do Magento, explicando os benefícios dessa nova abordagem: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-contracts.html

Marina Vilcea
fonte
2
obrigado pela resposta. Na verdade, tenho essa dúvida na cabeça do artigo de Alanstorm. :)
Rajeev K Tomy
3
De fato, isso deixa você pensando, mas isso provavelmente é uma coisa boa. Mesmo que essa seja a melhor prática sugerida pelo Magento, isso não significa que os desenvolvedores não possam levantar perguntas e criticar alguns aspectos dela. Além disso, ainda existem situações que não são cobertas pelos repositórios. No entanto, no contexto da criação de extensões que não quebram em versões futuras usando repositórios, deve ser considerado. Além disso, tenho certeza de que eles desenvolverão mais e oferecerão mais cobertura sobre o que os desenvolvedores precisam.
Marina Vilcea
Eu concordo 100% com o seu comentário. EU realmente espero. Veja também a resposta de fabian também.
Rajeev K Tomy
Sim, eu vi :) já votou positivamente em sua resposta. Obrigado pela ótima pergunta!
Marina Vilcea
Além disso, li em algum lugar que o uso do método de manipulação de dados de nível inferior é bom em scripts $setup->updateTableRow(...);ou fábricas de instalação / atualização , não tenho certeza, mas parece que os argumentos para o uso de nível superior se aplicam a essa área também, o que você acha?
medmek
1

Espero que esta resposta possa ajudar outros desenvolvedores de extensão também.

Temos que salvar o modelo usando apenas o Repositório.

  1. O modelo de fábrica no Magento 2 contém dados muito limitados.
  2. Por outro lado, o Modelo de Repositório contém todos os dados, no caso de atributos eav relacionados a cliente, produtos, etc.
  3. Para salvar o modelo, sempre use o Repositório para salvar qualquer entidade; se o modelo de fábrica for usado para salvar o modelo, ele excluirá todos os atributos eav que não sejam do sistema relacionados a essa entidade (cliente, produto etc.).

  4. Para carregar o modelo, o Repository é a melhor opção para obter o modelo usando o método getById ().

Recomendarei usar o Repositório o máximo possível, especialmente para fins de salvamento do modelo.

Sachin
fonte
1

Agora carregue, salve, exclua métodos (modelos) estão obsoletos. Assim, podemos usar o modelo ou o repositório de recursos.

Magento agora usando o conceito de gerenciador de entidades para salvar, excluir, carregar operações.

Os modelos de recursos têm um objeto de gerenciador de entidades para realizar essas operações.

$categoryModel = $this->_objectManager->create('\Magento\Catalog\Model\CategoryFactory')->create();        
  $categoryResource = $this->_objectManager->create('\Magento\Catalog\Model\ResourceModel\Category');        
  $categoryResource->load($categoryModel, 3);        
  echo $categoryModel->getName();
Siva Kumar Koduru
fonte