¿Cuándo debemos usar un repositorio y una fábrica en Magento 2?

76

He leído un par de tutoriales en Magento 2, y esto me confunde un poco. Puedo ver que básicamente hay dos formas en que podemos leer / escribir entidades comerciales:

Recuperar datos

Usando un enfoque de fábrica

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

Usando un enfoque de repositorio

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

Guardar datos

Usando un enfoque de fábrica

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

Usando un enfoque de repositorio

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

También puedo ver que, tanto un repositorio como una clase de fábrica se pueden inyectar usando inyección de dependencia. Esto es confuso al menos para mí.

¿Cuándo debemos usar un enfoque de repositorio y un enfoque de fábrica? ¿Cuál es la mejor práctica que debemos seguir?

Rajeev K Tomy
fuente
Un buen ejemplo de uso de Factory, CollectionFactory y Repository se puede ver en \ Magento \ Setup \ Fixtures \ CategoryResolver
Ricardo Martins

Respuestas:

73

Si hay un repositorio y hace lo que necesita bien, siempre prefiera el repositorio.

Los repositorios son parte de los contratos de servicio (son implementaciones de interfaces Api), esto significa que están destinados como una interfaz pública para otros módulos.

Utilice los repositorios para la carga completa

$model->load()no es parte del contrato de servicio. Tenía una pregunta sobre ese tema en particular, podría encontrar útiles las respuestas: ¿Hay alguna razón para preferir $ model-> load () sobre los contratos de servicio?

Usa Fábricas para crear nuevas entidades

Los repositorios no incluyen métodos para crear una nueva entidad, por lo que necesitará una fábrica. Pero use la fábrica para la interfaz , como por ejemplo Magento\Catalog\Api\Data\ProductInterfaceFactory: creará la implementación correcta basada en la configuración DI.

Luego use el repository->save()método para guardarlo.

Use las Fábricas de colecciones si necesita más control

La siguiente no es la mejor práctica oficial de Magento, pero actualmente, los repositorios no le dan un control preciso sobre qué cargar. La API de criterios de búsqueda le permite definir filtros, pero, por ejemplo, no hay forma de seleccionar atributos EAV particulares o especificar a qué tablas de índice unirse.

Estos son detalles de implementación, ocultos de las API del contrato de servicio, pero a menudo estos detalles de implementación son importantes y obtiene un rendimiento deficiente si los ignora. Por esa razón, tan pronto como los repositorios me limitan, ya no dudo en usar las colecciones subyacentes.

Fabian Schmengler
fuente
2
¿Podría dar un ejemplo de código sobre el uso de Fábricas para crear nuevas entidades? La explicación pierde algunos detalles y es difícil de entender. Muchas gracias.
Key Shang
1
@Key ¿esto ayuda? devdocs.magento.com/guides/v2.2/extension-dev-guide/…
Fabian Schmengler
Gracias. pero este use the factory for the interface, such as Magento\Catalog\Api\Data\ProductInterfaceFactory - it will create the right implementation based on DI configuration.es el punto que no puedo entender, las guías de desarrollo no presentan InterfaceFactory , ¿cómo usar el repository->save()método para guardar nuevas entidades? Solo puedo usar la fábrica para guardar nuevas entidades, no el repositorio.
Key Shang
@Key Shang, significa que la interfaz le dará todas las funciones de datos configuradas para guardar todas y cada una de las columnas de la tabla, así que intente usar la interfaz siempre que sea posible para guardar nuevos registros. Las clases de InterfaceFactory se crean como parte de di: compile para que pueda verlas en la carpeta var / generation.
stevensagaar
@stevensagaar Gracias, puedo entenderlo ahora.
Key Shang
21

Buena pregunta.

Incluso si tanto los repositorios como las fábricas nos permiten acceder a una entidad, creo que deberíamos centrarnos en su responsabilidad .

De la documentación de Magento : "Las fábricas son clases de servicio que instancian clases no inyectables, es decir, modelos que representan una entidad de base de datos. Crean una capa de abstracción entre el ObjectManager y el código comercial".

Del artículo de Alan Storm : "Un objeto de repositorio es responsable de leer y escribir la información de su objeto en un almacén de objetos"

Mi interpretación es: si nuestro propósito es trabajar con objetos no inyectables (llamados "renovables"), deberíamos usar Fábricas; Si nuestro foco está en buscar / leer / escribir objetos dentro de un almacén de objetos, deberíamos usar repositorios.

Este es mi enfoque idealista del tema; tenga en cuenta que la implementación real puede obligarnos a estropear las cosas, como señaló Alan.

Disfrutar.

Alessandro Ronchi
fuente
5

Diría que el camino a seguir es comenzar a usar repositorios ya que permiten la separación de código entre la lectura / escritura de datos y la lógica empresarial.

Hay un artículo muy detallado escrito por Alan Storm sobre esto, que explica cómo usar los repositorios, pero también analiza algunos inconvenientes de este nuevo método: http://alanstorm.com/magento_2_understanding_object_repositories/

Además, de la documentación de Magento, que explica los beneficios de este nuevo enfoque: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-contracts.html

Marina Vilcea
fuente
2
gracias por la respuesta. De hecho, tengo esta duda en mi cabeza del artículo de alanstorm si mismo. :)
Rajeev K Tomy
3
De hecho, te deja pensando, pero eso es probablemente algo bueno. Incluso si esta es la mejor práctica sugerida por Magento, no significa que los desarrolladores no puedan plantear preguntas y criticar algunos aspectos de la misma. Además, todavía hay situaciones que no están cubiertas por los repositorios. Sin embargo, en el contexto de la construcción de extensiones que no se rompan en futuras versiones utilizando repositorios, debe considerarse Además, estoy seguro de que se desarrollarán aún más y ofrecerán más cobertura sobre lo que los desarrolladores necesitan.
Marina Vilcea
Estoy 100% de acuerdo con tu comentario. Realmente espero eso. También por favor vea la respuesta de fabian también.
Rajeev K Tomy
Sí, vi :) ya votó su respuesta. Gracias por la gran pregunta!
Marina Vilcea
Además, leí en alguna parte que usar el método de manipulación de datos de nivel inferior está bien en los scripts $setup->updateTableRow(...);o fábricas de instalación / actualización , no estoy seguro, pero parece que los argumentos para usar el nivel superior también se aplican a esa área, ¿qué piensas?
medmek
1

Espero que esta respuesta también pueda ayudar a otros desarrolladores de extensiones.

Tenemos que guardar el modelo usando solo el repositorio.

  1. El modelo de fábrica en Magento 2 contiene datos muy limitados.
  2. Por otro lado, el modelo de repositorio contiene todos los datos, en el caso de atributos eav relacionados con clientes, productos, etc.
  3. Para guardar el modelo, use siempre el Repositorio para guardar cualquier entidad, si el modelo de fábrica se usa para guardar el modelo, elimina todos los atributos eav que no sean del sistema relacionados con esa entidad (cliente, producto, etc.).

  4. Para cargar el propósito del modelo, el repositorio es la mejor opción para obtener el modelo usando el método getById ().

Recomendaré usar el Repositorio tanto como sea posible, especialmente para guardar el modelo.

Sachin
fuente
1

Ahora los métodos de carga, guardado y eliminación (modelos) están en desuso, por lo que podemos usar el modelo o repositorio de recursos.

Magento ahora utiliza el concepto de administrador de entidades para operaciones de guardar, eliminar y cargar.

Los modelos de recursos tienen un objeto administrador de entidad para cumplir con esas operaciones.

$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
fuente