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

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.


<?php
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 :


<?php

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()
{
parent::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.



<?php 
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 :


<?php
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 {
    $this->resourceStudent->save($student);
  } 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 {
    $this->resourceStudent->delete($student);
  } 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">
<arguments>
<argument name="entities" xsi:type="array">
<item name="MyVendor\MyModule\Api\Data\StudentInterface">MyVendor\MyModule\Api\StudentRepositoryInterface</item>
</argument>
</arguments>
</type>
</config>

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 !

Write your comment

Ready
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.

Contact
+339 50 66 21 38


Legal terms
Agency 30, Avenue du Rhin
67100 Strasbourg
France
SEE MAP
FR - EN