111

I have gone through a couple of tutorials in Magento 2, and this confuses me a little. I can see there are basically two ways by which we can read/write business entities:

Retrieve Data

Using A Factory Approach

$object = $this->myFactory->create();
$object->load($myId);

Using A Repository Approach

$repo   = $this->myRepository();
$object = $repo->getById($myId);

Save Data

Using A Factory Approach

$object = $this->myFactory->create();
$object->load($myId);
$object->setData('something', 'somethingDifferent')->save();

Using A Repository Approach

$repo   = $this->myRepository();
$object = $repo->getById($myId);
$object->setData('something', 'somethingDifferent');
$repo->save($object);

I can also see that, both a repository and a factory class can be injected using dependency injection. This is confusing at least for me.

When should we use a repository approach and a factory approach? What is the best practice we need to follow?

1
  • A good example of use of Factory, CollectionFactory and Repository can be seen on \Magento\Setup\Fixtures\CategoryResolver Commented Jan 30, 2019 at 22:51

6 Answers 6

107

If there is a repository and it does what you need well, always prefer the repository.

Repositories are part of the Service Contracts (they are implementations of interfaces in Api), this means they are meant as a public interface to other modules.

Use Repositories for full loading

$model->load() is not part of the service contract. I had a question on that particular topic, you might find the answers useful: Is there ever a reason to prefer $model->load() over service contracts?

Use Factories to create new entities

Repositories do not come with methods to create a new entity, so in that case, you will need a factory. But use the factory for the interface, such as Magento\Catalog\Api\Data\ProductInterfaceFactory - it will create the right implementation based on DI configuration.

Then use the repository->save() method to save it.

Use Collection Factories if you need more control

The following is not official Magento best practice, but currently, repositories do not give you fine control over what to load. The search criteria API lets you define filters, but for example, there is no way to select particular EAV attributes or specify which index tables to join.

These are implementation details, hidden from the service contract APIs, but often these implementation details matter and you get poor performance if you ignore them. For that reason, as soon as the repositories are limiting me I don't hesitate anymore to use the underlying collections.

6
  • 3
    Could you give a code example about use Factories to create new entities, the explanation miss some details and hard to understand. Thank you very much.
    – Key Shang
    Commented Nov 14, 2017 at 9:01
  • 1
    @Key does this help? devdocs.magento.com/guides/v2.2/extension-dev-guide/… Commented Nov 14, 2017 at 9:21
  • Thanks. but the use the factory for the interface, such as Magento\Catalog\Api\Data\ProductInterfaceFactory - it will create the right implementation based on DI configuration. is the point which I can not understand, the dev guides doesn't introduce the InterfaceFactory , how to use repository->save() method to save new entities? I can just only use factory to save new entities, not repository.
    – Key Shang
    Commented Nov 14, 2017 at 10:43
  • @Key Shang, it means that interface will give you all set data functions to save each and every column of the table so try to use interface wherever possible to save new records. InterfaceFactory classes do get created as part of di:compile so you can see them in var/generation folder. Commented Dec 2, 2018 at 4:04
  • @stevensagaar Thanks, I can understand it now.
    – Key Shang
    Commented Dec 3, 2018 at 6:20
30

Good question.

Even if both Repositories and Factories let us access an Entity I think we should focus on their responsibility.

From Magento documentation: "Factories are service classes that instantiate non-injectable classes, that is, models that represent a database entity. They create a layer of abstraction between the ObjectManager and business code."

From Alan Storm's article: "A repository object is responsible for reading and writing your object information to an object store"

My interpretation is: If our purpose is to work with non-injectable (so called "newable") objects we should use Factories; if our focus is on searching/reading/writing objects within an object store we should use Repositories.

This is my idealistic approach to the topic; keep in mind that actual implementation may force us to mess up things, as pointed out by Alan.

7

I would say the way forward it's to start using repositories as they allow code separation between data reading/writing and business logic.

There is a very detailed article written by Alan Storm about this, explaining how to use repositories but also looking into some drawbacks of this new method: http://alanstorm.com/magento_2_understanding_object_repositories/

Also, from the Magento documentation, explaining the benefits of this new aproach: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-contracts.html

5
  • 2
    thanks for the answer. I actually get this doubt on my head from alanstorm's article ifself. :) Commented Feb 4, 2017 at 9:02
  • 3
    Indeed, it leaves you thinking, but that is probably a good thing. Even if this is the best practice suggested by Magento, it doesn't mean developers can not raise questions and critique some aspects of it. Also, there are still situations that aren't covered by the repositories. However, in the context of building extensions that won't break on future releases using repositories should be considered. Also, I'm sure they will develop further and offer more coverage on what developers need. Commented Feb 4, 2017 at 9:18
  • I 100% agree with your comment. I really hope so. Also please see fabian's answer too. Commented Feb 4, 2017 at 9:20
  • Yes, I saw :) already upvoted his answer. Thanks for the great question! Commented Feb 4, 2017 at 9:24
  • Further, I read somewhere that using lower level data manipulation method is ok in install/upgrade scripts $setup->updateTableRow(...); or factories, I'm not sure but it feels like the arguments for using higher level apply to that area as well, what do you think ?
    – medmek
    Commented Dec 10, 2018 at 16:10
2

Hope this answer might help other extension developers as well.

We have to save model using Repository only.

  1. Factory Model in Magento 2 hold very limited data.
  2. On the Other hand, Repository Model contains all data, in case of eav attributes related to customer, products , etc.
  3. For saving model, always use Repository to save any entity, if factory model is used for saving model, it deletes all non-system eav attributes related to that entity (customer, product, etc.).

  4. For loading model purpose, Repository are best option to get model using getById() method.

I will recommend to use Repository as much as possible specially for model save purpose.

0

Using solely collections seems like the lazy way out. If an existing repository underperforms, simply create a new collection that meets your needs and create a new repository to leverage the new collection. In this way you are still following best practices by abstracting away the collection and you can still implement the service contract.

Many answers, including the accepted one, seem to ignore the fact that repositories use collections under the hood. There is nothing stopping you from getting finer control when using a custom repository, since you can use a custom collection.

-2

Now load,save,delete methods (models) are deprecated.So we can use resource model or repository.

Magento now using entity manager concept for save,delete,load operations.

Resource models have entity manager object to fulfil those operations.

$categoryModel = $this->_objectManager->create('\Magento\Catalog\Model\CategoryFactory')->create();        
  $categoryResource = $this->_objectManager->create('\Magento\Catalog\Model\ResourceModel\Category');        
  $categoryResource->load($categoryModel, 3);        
  echo $categoryModel->getName();
1
  • Object manager is not recomended
    – Asssd
    Commented Nov 30, 2021 at 10:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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