Repository Interfaces

The Repository interfaces are a sub-type of the Service interfaces.

Suppose you have an object of type Magento\Catalog\Model\Product to which, as usual, can call the save() method. This either creates new product or updates an existing one.

https://gist.github.com/marjan7790/c2eae95a18d82f4ecc7738e70a2c07cf

In Magento 2, there is another way to save a product by using an instance from Magento\Catalog\Model\ProductRepository like

https://gist.github.com/marjan7790/ad996e02280faae659947230576c528d

What happens here?

Well, instead of calling the save() method on the Magento\Catalog\Model\Product object itself, we pass this object to the save() method of an object of type Magento\Catalog\Model\ProductRepository.

So, what is the difference?


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

https://gist.github.com/marjan7790/c2eae95a18d82f4ecc7738e70a2c07cf

The model class itself is Magento\Catalog\Model\Product

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

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

Interesting…

Thus, we need to turn our attention to 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

https://gist.github.com/marjan7790/eedc8bf5de69e042c58e409d138e5f5b

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

This last one is not surprising given that we’ve been 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

https://gist.github.com/marjan7790/75447e3365349fc90d08bd3015a90122

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

https://gist.github.com/marjan7790/91a239f07e44ee326efb5682c9be4870

So, we can check the implementation of the save() method inside

https://gist.github.com/marjan7790/c1785b49970b6d8d677d07c1d66c8472

and it starts on line 444, looking something like

https://gist.github.com/marjan7790/b1177f20a84ec36c52250a6e38679240

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, within a try statement, we see something like

https://gist.github.com/marjan7790/71257c9886e4ece4c1c8d2b042e4d2ca
You guessed well! $this->resourceModel is of type \Magento\Catalog\Model\ResourceModel\Product, declared as protected property on line 77.

So, again, the RESOURCE MODEL actually does the saving.


But now we can spot the difference. Specifically, in the following code.

https://gist.github.com/marjan7790/30c7dc10204c9225d05164378edd52ff

All the code executed here, indeed, eventually may and will lead to differences in behavior 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 existing product in the first place etc.


Conclusion

Magento 2 has added yet another layer of abstraction towards working with models. With the downside of having a more complicated code for debugging, comes a positive moment where the model object is managed by yet another object, rather than directly instructed to do the things we like it to do. Often, these things are not there by default.

So, 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 would prefer to use the product repository object over the product model object.

Thank you for reading this article!