10

In Magento 2 we have repositories classes. Classic method save() used heavily in Magento 1.9 are deprecated, if I am correct, from 2.04 or 2.05. I was using factories to create new object and after setting properties of new, for example product i have called save():

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

On the other hand we have repositories also containing method save. I am using it in nutshell like this:

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

In my code I have classes working both ways. I also have noticed that sometimes different ways means different behaviour. Has the way with repositories some additional validation of data provided?

Which way I should do it?

9
+50

Let us first see, what happens if you use the save() method directly on a product model like

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

The model class itself is

Magento\Catalog\Model\Product

Within this class, search for the definition of the save() method.

None found right? Well, there's beforeSave() and afterSave(), but not save() itself. Interesting, no?

Then, we need to look at the parent classes of Magento\Catalog\Model\Product.

We need to pass through Magento\Catalog\Model\AbstractModel and Magento\Framework\Model\AbstractExtensibleModel, just to finally arrive at Magento\Framework\Model\AbstractModel.

Sure enough, there is a save() method here and it looks something like

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

We see now, whenever save() is called on any model, the save() method from this AbstractModel is called, and the implementation is that the RESOURCE MODEL actually does the saving.

This last one is not surprising given that we are always, since like from the beggining of time in Magento 1.0, creating both a Model and a Resource model for just about any entity.


Now, lets take a look at how the ProductRepository works.

Lets open file

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

This interface demands that there is a save() method, among other methods.

Who is actually implementing this interface?

Lets open file

/etc/di.xml

and check line 10

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

So, naturally we find the implentation of the save() menthod inside

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

and it starts on line 444, looking something like

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

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

This method expects a $product object of type \Magento\Catalog\Api\Data\ProductInterface passed, but by default this resolves to Magento\Catalog\Model\Product.

Looking down below on line 500, winthin a try statement, we see something like

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

You guessed well! $this->resourceModel is of type \Magento\Catalog\Model\ResourceModel\Product, declared as protected property on line 77.

So, again, the ResourceModel actually does the saving.

But, between line 444 and 500 is actually the answer to your question. All the code executed here, indeed, eventually may and will lead to differences in behaviour between direct model save and this repository way of saving.

For example the product repository will get and process product links if the ignore_links_flag is set to 0, check if this is an existing product in the first place etc.

We probably need to conclude that if any need in the future to change how the product is saved, perhaps the better way to do it is by overriding the product repository instead of the product model.

The same goes for saving and updating products. I'd rather use the product repository object.

I also kindly refer to you to /vendor/magento/module-cms/Model/PageRepository.php

This is how a CMS page would be saved via repository. Here, things are simpler. The store id is set and the resource model is called to save right away.

With this last notice, you will conclude that in some cases, there may not be that much differences between repository and model save, but anyway I hope you are equipped now to spot them whenever you need to do so.

1

It is encouraged to use data interfaces (e.g. \Magento\Catalog\Api\Data\ProductInterface) instead of the model directly and use the repositories to load and save models.

See Magento developer documentation

  • 1
    ok - that is the right way for whole entity - but only to update some attribute's value - I think load/saving whole entity is not recommended. – Bartosz Kubicki Dec 28 '16 at 7:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.