Як слід зберігати нові або оновлені об'єкти моделей?


10

У Magento 2 у нас є класи сховищ. Класичний метод, save()який сильно використовується в Magento 1.9, є застарілим, якщо я правильно, з 2,04 або 2,05. Я використовував фабрики для створення нового об'єкта і після встановлення властивостей нового, наприклад продукту, якого я назвав save():

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

З іншого боку, у нас є також сховища, що містять метод save. Я використовую це в двох словах так:

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

У моєму коді у мене є класи, що працюють обома способами. Я також помітив, що іноді різні способи означають різну поведінку. Чи надано шлях із сховищами додаткову перевірку даних?

Яким чином я повинен це зробити?

Відповіді:


10

Давайте спочатку розберемося, що станеться, якщо використовувати save()метод безпосередньо на productподібній моделі

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

Сам клас моделі є

Magento\Catalog\Model\Product

У межах цього класу знайдіть визначення методу save ().

Не знайдено правильно? Що ж, є ранішеSave () та afterSave (), але не зберегти (). Цікаво, ні?

Потім нам потрібно переглянути батьківські класи Magento\Catalog\Model\Product.

Нам потрібно пройти Magento\Catalog\Model\AbstractModelі Magento\Framework\Model\AbstractExtensibleModel, щоб нарешті приїхати Magento\Framework\Model\AbstractModel.

Звичайно, тут є метод save (), і це виглядає приблизно так

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

Ми бачимо, щоразу, коли виклик save () на будь-якій моделі AbstractModelвикликається, метод save () викликається, і реалізація полягає в тому, що РЕЗУЛЬТАТНА МОДЕЛЬ дійсно робить економію.

Останнє не дивно, враховуючи, що ми завжди, оскільки, як і з початком часу в Magento 1.0, створюємо як модель, так і модель ресурсу майже для будь-якої сутності.


Тепер давайте подивимось, як це ProductRepositoryпрацює.

Дозволяє відкрити файл

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

Цей інтерфейс вимагає, щоб серед інших методів існував метод save ().

Хто реально реалізує цей інтерфейс?

Дозволяє відкрити файл

/etc/di.xml

і перевірити рядок 10

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

Отже, ми, природно, знаходимо реалізацію збереження () ментоду всередині

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

і він починається на лінії 444, виглядаючи щось подібне

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

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

Цей метод очікує, що $ об'єкт продукту типу \Magento\Catalog\Api\Data\ProductInterfaceпереданий, але за замовчуванням це вирішує значення Magento\Catalog\Model\Product.

Дивлячись нижче на лінію 500, перемагаючи tryзаяву, ми бачимо щось на кшталт

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

Ви добре здогадалися! $this->resourceModelтипу \Magento\Catalog\Model\ResourceModel\Product, оголошений як protectedвластивість по лінії 77.

Отже, знову ж таки, ResourceModelнасправді це економія.

Але між рядком 444 і 500 насправді є відповіддю на ваше запитання. Весь код, виконаний тут, справді, зрештою, може і призведе до відмінностей у поведінці між прямим збереженням моделі та цим способом збереження сховища.

Наприклад, сховище продукту отримає та обробить посилання на продукти, якщо ignore_links_flagвстановлено значення 0, перевірте, чи в першу чергу це вже існуючий продукт тощо.

Напевно, нам потрібно зробити висновок, що якщо в майбутньому виникне потреба змінити спосіб збереження продукту, можливо, кращий спосіб зробити це шляхом переопределення продуктового сховища замість моделі продукту.

Те саме стосується збереження та оновлення продуктів. Я вважаю за краще використовувати об'єкт продуктового сховища.

Я також люб'язно посилаюся на вас на /vendor/magento/module-cms/Model/PageRepository.php

Так зберігається CMS-сторінка через сховище. Тут все простіше. Встановлюється ідентифікатор магазину, а модель ресурсу викликається для збереження відразу.

За допомогою цього останнього повідомлення ви зробите висновок, що в деяких випадках може бути не так багато відмінностей між сховищем та збереженням моделі, але все одно я сподіваюся, що ви зараз готові помітити їх, коли вам потрібно це зробити.


1

Рекомендується використовувати інтерфейси даних (наприклад \Magento\Catalog\Api\Data\ProductInterface) замість моделі безпосередньо та використовувати сховища для завантаження та збереження моделей.

Дивіться документацію для розробників Magento


1
ОК - це правильний шлях для всієї сутності, але лише для оновлення значення атрибутів - я думаю, що завантажувати / зберігати цілу сутність не рекомендується.
Bartosz Kubicki
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.