¿Cómo debo guardar entidades de modelos nuevas o actualizadas?

10

En Magento 2 tenemos clases de repositorios. El método clásico save()utilizado en gran medida en Magento 1.9 está en desuso, si estoy en lo cierto, de 2.04 o 2.05. Estaba usando fábricas para crear nuevos objetos y después de establecer propiedades de nuevos, por ejemplo, un producto al que llamé save():

$productFactory->create()->setName()...->save()

Por otro lado tenemos repositorios que también contienen método save. Lo estoy usando en pocas palabras como este:

$product = $productFactory->create()->setName()... $productRepository->save($product)

En mi código tengo clases que funcionan en ambos sentidos. También he notado que a veces diferentes formas significan un comportamiento diferente. ¿Tiene el camino con los repositorios alguna validación adicional de los datos proporcionados?

¿De qué manera debería hacerlo?

Bartosz Kubicki
fuente

Respuestas:

10

Veamos primero qué sucede si usa el save()método directamente en un productmodelo como

/**
 * @var Magento\Catalog\Model\Product $product
 */
$product->save();

La clase de modelo en sí es

Magento\Catalog\Model\Product

Dentro de esta clase, busque la definición del método save ().

Ninguno encontrado ¿verdad? Bueno, hay beforeSave () y afterSave (), pero no save () en sí. Interesante, no?

Luego, debemos mirar las clases principales de Magento\Catalog\Model\Product.

Necesitamos pasar Magento\Catalog\Model\AbstractModely Magento\Framework\Model\AbstractExtensibleModel, finalmente, llegar a Magento\Framework\Model\AbstractModel.

Efectivamente, hay un método save () aquí y se ve algo así como

public function save()
{
    $this->_getResource()->save($this);
    return $this;
}

Vemos ahora, cada vez que se llama a save () en cualquier modelo, se llama al método save () AbstractModel, y la implementación es que el MODELO DE RECURSOS realmente guarda.

Esto último no es sorprendente dado que siempre lo estamos, ya que desde el principio del tiempo en Magento 1.0, creamos un modelo y un modelo de recursos para casi cualquier entidad.


Ahora, echemos un vistazo a cómo ProductRepositoryfunciona.

Permite abrir archivo

/vendor/magento/module-catalog/Api/ProductRepositoryInterface.php

Esta interfaz exige que haya un método save (), entre otros métodos.

¿Quién está implementando realmente esta interfaz?

Permite abrir archivo

/etc/di.xml

y verifique la línea 10

<preference for="Magento\Catalog\Api\ProductRepositoryInterface" type="Magento\Catalog\Model\ProductRepository" />

Entonces, naturalmente, encontramos la implementación del método save () dentro

/vendor/magento/module-catalog/Model/ProductRepository

y comienza en la línea 444, luciendo como

public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveOptions = false)
{
    $tierPrices = $product->getData('tier_price');

    try {
    .... other code here ....

Este método espera que se \Magento\Catalog\Api\Data\ProductInterfacepase un objeto $ product de tipo , pero por defecto esto se resuelve en Magento\Catalog\Model\Product.

Mirando abajo en la línea 500, ganando una trydeclaración, vemos algo así como

$this->resourceModel->save($product);

¡Lo has adivinado bien! $this->resourceModeles de tipo \Magento\Catalog\Model\ResourceModel\Product, declarado como protectedpropiedad en la línea 77.

Entonces, de nuevo, en ResourceModelrealidad hace el ahorro.

Pero, entre la línea 444 y 500 es en realidad la respuesta a su pregunta. Todo el código ejecutado aquí, de hecho, eventualmente puede y conducirá a diferencias de comportamiento entre el guardado directo del modelo y esta forma de guardar el repositorio.

Por ejemplo, el repositorio de productos obtendrá y procesará enlaces de productos si ignore_links_flagestá configurado como 0, compruebe si este es un producto existente en primer lugar, etc.

Probablemente necesitemos concluir que si es necesario cambiar la forma en que se guarda el producto en el futuro, quizás la mejor manera de hacerlo es anular el repositorio del producto en lugar del modelo del producto.

Lo mismo vale para guardar y actualizar productos. Prefiero usar el objeto del repositorio del producto.

También me remito amablemente a /vendor/magento/module-cms/Model/PageRepository.php

Así es como se guardaría una página CMS a través del repositorio. Aquí, las cosas son más simples. Se establece la identificación de la tienda y se llama al modelo de recurso para guardar de inmediato.

Con este último aviso, concluirá que en algunos casos, puede que no haya tantas diferencias entre el repositorio y el guardado del modelo, pero de todos modos espero que esté equipado para detectarlos cada vez que necesite hacerlo.

Marjan
fuente
1

Se recomienda usar interfaces de datos (por ejemplo \Magento\Catalog\Api\Data\ProductInterface) en lugar del modelo directamente y usar los repositorios para cargar y guardar modelos.

Consulte la documentación del desarrollador de Magento

ochnygosch
fuente
1
ok, esa es la forma correcta para toda la entidad, pero solo para actualizar el valor de algunos atributos, creo que no se recomienda cargar / guardar toda la entidad.
Bartosz Kubicki