Magento2 – When to Prefer $model->load() Over Service Contracts

Architecturemagento2modelrepositoryservice-contract

I understand that the preferred way to work in between modules in Magento 2 is using the service contracts.

So if I want to load a product, I use the product repository:

$product = $productRepository->getById($id);

which is by contract returning an instance of Magento\Catalog\Api\Data\ProductInterface.

But I could also use the old way instead, calling the domain layer directly:

$product = $productFactory->create()->load($id);

Is there any case where this would be necessary or useful?

The devdocs say (highlight added):

A module can directly call into another module. This tightly coupled solution is not recommended for most situations, but is sometimes unavoidable.

[…]

Your strategy for calling another module’s domain-layer code is highly dependent upon the unique configuration and needs of your system.

Source: http://devdocs.magento.com/guides/v2.0/architecture/archi_perspectives/domain_layer.html

And a comment on a related question stated:

using the Repository will give you a Product data model (Api/Data/Product), which is a Product model converted into a dumbed-down DTO. Something to consider, as they're quite different

But as far as I can see the objects are the same under normal conditions, just the return types per phpDoc differ (Magento\Catalog\Api\Data\ProductInterface / Magento\Catalog\Model\Product)

Best Answer

The reason to use ProductRepository's get/getById instead of a ProductFatory's load() method, is because the former is of a higher level than the latter.

A ProductRepository - just like a ProductFactory - might return a Product model, but that is not what M2 wants you to consider. That's not what \Magento\Catalog\Api\ProductRepositoryInterface::getById()'s doc block says. It says @return \Magento\Catalog\Api\Data\ProductInterface, which is an interface a Product model is implementing.

SO, you should use the API layer whenever possible, because:

  • Api/Data layer is used in the Web Api, as well
  • models can - and probably will - be refactored at some point; Api/Data/Product will not.
  • To get a product in your classes, you need to inject either a concrete factory (ProductFactory) or an interface (ProductRepository). I don't think you want your module to rely on anything but an interface. Hence I disagree with this type of injection.

I consider it to be just another tiny abstraction layer above models, to cater for the Web API (REST, SOAP etc.).

Quoting this answer:

Hopefully, you will love service contracts when your custom module will not be broken after the next releases of Magento 2 (of course if you do not bypass service contracts and use models/collections/resource models directly). And when you start consuming/exposing Magento 2 web API, which is now based on the same service contracts. So you have to make changes only in one place (e.g. via plugin) and they will be applied everywhere. This was impossible in Magento 1.

Related Topic