3/22/2018 - #development #ecommerce #magento
by: Kévin Weyhaupt

EDIT : The content of this article may no longer be current following the new best practices suggested by Magento.

Part 2 : Adding flavour

Binding between the model and the data

Reminder, find the complete and commented code here : https://github.com/blackbird-agency/magento-2-data-model-sample.

At the moment we only have the business-class-model part, we need to add the relation with our datas. To do so, we will create our “resource models”.
The resource models enable to link our models with the data base. Here the classes inherite from AbstractDb in order to accomplish some operations before or after different actions on the database, for instance « after/beforeDelete», « after/beforeSave » but above all to define in the constructor the table and the primary key related to our object using the “_init” method.

namespace MyVendor\MyModule\Model\ResourceModel;

use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
use MyVendor\MyModule\Api\Data\StudentInterface;

class Student extends AbstractDb
  protected function _construct()
    $this->_init('student', StudentInterface::ID);

Collections Management

In some cases, we need to quickly get the collection of our whole entity, to able to display it in a grid for instance. The best thing is to use MyVendor/MyModule/Model/ResourceModel/Student.
By inheriting from AbstractCollection, we only need to apply the “_init” method to link the business model and the resource model :


namespace MyVendor\MyModule\Model\ResourceModel\Student;

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use MyVendor\MyModule\Model;

class Collection extends AbstractCollection

protected function _construct()
$this->_init(Model\Student::class, Model\ResourceModel\Student::class);

Garnish it with some “repositories”

The repositories

A repository is another piece of the service contract that will help to manage the CRUD of our model. Most of the time we will find the following methods : getById, save, delete …

Before the creation of the repositories, the CRUD of a model was managed by the model itself using the save/load/delete methods of the AbstractModel (by inheritance). These methods are now depreciated since a model in not supposed to be responsible of its CRUD management. It is managed by the repositories using the resource models.

namespace MyVendor\MyModule\Api;
* @api
interface StudentRepositoryInterface
public function save(Data\StudentInterface $student);
public function getById($studentId);
public function delete(Data\StudentInterface $student);
public function deleteById($studentId);

Implémentation of the « Repositories »

Here is an example of the implementations of the different methods for the repository :

namespace MyVendor\MyModule\Model;

use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\CouldNotDeleteException;
use Magento\Framework\Exception\NoSuchEntityException;
use MyVendor\MyModule\Api\Data;
use MyVendor\MyModule\Api\StudentRepositoryInterface;
use MyVendor\MyModule\Model\ResourceModel;

class StudentRepository implements StudentRepositoryInterface
  private $resourceStudent;

  private $studentFactory;

  public function __construct(
    ResourceModel\Student $resourceStudent,
    Data\StudentInterfaceFactory $studentFactory
  ) {
      $this->resourceStudent = $resourceStudent;
      $this->studentFactory = $studentFactory;
  public function save(Data\StudentInterface $student)
  try {
  } catch (\Exception $e) {
    throw new CouldNotSaveException(__($e->getMessage()));
    return $student;

  public function getById($studentId)
    $student = $this->studentFactory->create();
    $this->resourceStudent->load($student, $studentId);
    if (!$student->getId()) {
      throw new NoSuchEntityException(__('Student with id "%1" does not exist', $studentId));
    return $student;
public function delete(Data\StudentInterface $student)
  try {
  } catch (\Exception $e) {
    throw new CouldNotDeleteException(__($e->getMessage()));
    return $student;
  public function deleteById($studentId)
    return $this->delete($this->getById($studentId));

One of the main benefit of the Repositories is that they can be managed with the “Lazy Loading”. We will be able to load only what we need and only when this is necessary. Moreover, we check if the entity that we want to use hasn’t already been loaded before and if we can use the existing entity again instead of instantiating it again. It also allows a better performance as the use of the RAM of the server is optimized.

Ensuite pour finir avec les Repositories, comme dans la partie 1, on va appliquer l’injection de dépendance entre l’interface de l’API et le modèle. En plus de ça, on ajoute aussi un “RepositoryFactory” pour spécifier sur quel entité va déprendre de quel Repository.
Then, to finish with the Repositories, like in the part 1, we will apply some injection of dependency between the API's interface and the model. Moreover, we also add a "RepositoryFactory" to be more specific about the entity and the Repository it will depend from.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MyVendor\MyModule\Api\StudentRepositoryInterface" type="MyVendor\MyModule\Model\StudentRepository"/>
<type name="Magento\Framework\Model\Entity\RepositoryFactory">
<argument name="entities" xsi:type="array">
<item name="MyVendor\MyModule\Api\Data\StudentInterface">MyVendor\MyModule\Api\StudentRepositoryInterface</item>

Part 2 is now over. If you're still motivated and want to improve your recipe, I invite you to read the third and final part : the Chef's touch !

Your comments

Jun 7, 2019
Hi Lounik,

Yes you're right, I made a mistake. The right answer is indeed in the blog article. I will fix the GitHub code.

Thank you !

Jun 7, 2019
Hi Radu, Thank you for the feedback !

As explained in the article, the Lazyloading principle is to load entity only one time and only if it's needed.
With that we automatically optimize the usage of the RAM because we only use what we need, and that's all.

Hoping that answer your question.

May 24, 2019
in this post you wrote "item name="MyVendor\MyModule\Api\Data\StudentInterface">MyVendor\MyModule\Api\StudentRepositoryInterfaceBlackbird\DataModelSample\Api\StudentRepositoryInterface
Basically in the post it is written that item name is Api\DATA\STUDENTINTERFACE while the github gives Api\StudentRepositoryInterface in the item name. Which is the correct one?
May 7, 2019
Really nice tutorial! Great job! To the end of part 2 there is the following remark: "It also allows a better performance as the use of the RAM of the server is optimized." - can you please share more details on this one?

Write your comment

for take-off?

Blackbird is a web agency specialized in the development of eCommerce websites. We are Magento Experts and we offer our services and advice for e-marketing, strategy, branding, deployment and methodology.

+339 50 66 21 38

Legal terms
Agency 30, Avenue du Rhin
67100 Strasbourg