Как сохранить новые или обновленные объекты моделей?

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 ().

Ни один не найден верно? Ну, есть beforeSave () и afterSave (), но нет самой save (). Интересно, нет?

Затем нам нужно взглянуть на родительские классы 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 () из этого , и реализация заключается в том, что RESOURCE MODEL фактически выполняет сохранение.

Последнее не удивительно, учитывая, что мы всегда, так как, как и в начале времени в 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" />

Итак, естественно, мы находим применение метода save () внутри

/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передан объект $ product типа , но по умолчанию он разрешается в 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

ochnygosch
источник
1
хорошо - это правильный путь для всей сущности - но только для обновления значения некоторого атрибута - я думаю, что загрузка / сохранение всей сущности не рекомендуется.
Бартош Кубицки