如何保存模型的新实体或更新实体?


10

在Magento 2中,我们有存储库类。save()如果我正确的话,Magento 1.9中大量使用的经典方法已从2.04或2.05弃用。我使用工厂创建新对象,并在设置了新属性后,例如我调用的产品save()

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

另一方面,我们的存储库中也包含method save。我正在像这样概括地使用它:

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

在我的代码中,我有两种方式都可以工作的类。我也注意到有时不同的方式意味着不同的行为。使用存储库的方式是否提供了对数据的一些附加验证?

我应该采取哪种方式?

Answers:


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\AbstractModelMagento\Framework\Model\AbstractExtensibleModel,只是最终到达处Magento\Framework\Model\AbstractModel

当然,这里有一个save()方法,它看起来像

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

现在我们看到,每当在任何模型上调用save()时,都会调用该方法的save()方法AbstractModel,并且实现是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是type \Magento\Catalog\Model\ResourceModel\Productprotected在第77行声明为property。

因此,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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.