• Magento
  • Développement

La recette pour un bon modèle de données Magento 2 - partie 1

kevin_2234efd45f
Kevin Weyhaupt, Lead Technique
Le 22 mars 2018
cooking_magento_1_b74e280d27
  • ecommerce

Lecture :11 minutes

EDIT : Le contenu de cet article peut ne plus être d'actualité suite aux nouvelles bonnes pratiques suggérées par Magento.

Intro

 

Chaque début d’année peut se résumer par une succession de bonnes recettes bien gourmandes, malgrés toutes les résolutions autour des régimes et de la perte de poids. Après la galette des rois, les crêpes de la chandeleur et les beignets, je vous propose une recette afin de réaliser de bons modèles de données pour vos futurs projets sous Magento 2. S'agissant d'une grosse recette, elle se déroulera en plusieurs étapes. En voici la liste d’ingrédients et de préparations à réaliser :



Pour cet article je vais utiliser les deux entités suivantes, « Student » et « Teacher » afin d’avoir une table associative (étudiant à plusieurs professeurs et inversement). Avant tout je tiens à préciser deux choses. Premièrement, les exemples de code n’ont pas de PHP Doc pour un gain de place. Mais bien évidemment c’est une pratique que tout bon développeur doit mettre en place. (Le code complet et commenté est disponible ici https://github.com/blackbird-agency/magento-2-data-model-sample).Et deuxièmement cet article ne concerne que les modèles de données “classiques” (c’est à dire avec différentes entitées et des relations entre elles) et non le modèle Entity Attribute Value (EAV).
schéma tables

Partie 1: Préparation des principaux ingrédients

Un beau morceau du Service Contract …

Avant toute chose qu’est-ce que le « Service Contract » ? Le « Service Contract » est le contrat entre le développeur et le code de l’application. Pour le définir simplement, c’est un ensemble d’interfaces qui, par exemple, va permettre de définir l’ensemble des services et structures des différents modèles de données... Pour notre recette nous en utiliserons une bonne partie, sans pour autant tout y voir. (Probablement le sujet d’un futur article).

Définition de nos modèles

Tout d’abord les interfaces du « Service Contract » se définissent dans un dossier nommé « Api » à la racine de notre module concerné. Et dans ce même dossier nous allons créer un dossier « Data » où nous y mettrons nos interfaces faisant référence à chacun de nos modèles avec les accesseurs et les propriétés statiques tels que les noms de champs dans la base afin de pouvoir les modifier simplement, sans avoir à parcourir tout notre code.
Ici le tag @api de la PHPDoc indique que la classe fait bien partie de l’api et qu’on peut ainsi lui faire confiance.

<?php
namespace MyVendor\MyModule\Api\Data;
/**
* Student Interface
* @api
*/
interface StudentInterface
{
  const ID = 'student_id';
  const NAME = 'name';
  public function getId();
  public function getName();
  public function setId($id);
  public function setName($name);
}


La réalisation du modèle

Une fois nos interfaces du service contract prêtes, nous pouvons les implémenter dans MyVendor\MyModule\Model.

Implémentation des modèles

Le but ici est de simplement implémenter les accesseurs en utilisant les propriétés de classe définies dans les interfaces. Notre modèle va hériter d’Abstract Model pour plusieurs raisons :

  • Faire appel à la méthode “_init” dans le constructeur afin de faire directement le lien avec le “resource model” et ainsi faire la relation entre notre objet et la base de données. (Le “resource model” sera expliqué dans la seconde partie)
  • Gérer les attributs de notre objet avec par exemple :
    • setData/getData: permet de définir ou récupérer la valeur d’un attribut.
    • setOrigData/getOrigData: permet de récupérer les données de notre objet au moment de son instanciation, c’est à dire les données initiales provenant de la base de données.
    • --Et ainsi Magento va uniquement mettre à jour les données qui ont été modifiées.
  • Utiliser les méthodes magiques, c’est à dire les méthodes commencant par set, get, uns ou encore has + le nom de l’attribut (en camelCase) pour gérer un attribut, si l’objet lui même n’a pas encore de méthode pour y accéder.

Dans le cas où notre objet est plutôt simpliste et n’est utile que pour de la manipulation de données (et éventuellement gérer la mise à jour dans la base en passant par des services) il est plus intéressant d’hériter d’AbstractSimpleObject car il est plus léger en offrant uniquement les méthodes get/setData et __toArray. Si en plus d’un objet simple nous souhaitons utiliser les collections, sans pour autant hériter du AbstractModel, nous pouvons utiliser le DataObject.

<?php
namespace MyVendor\MyModule\Model;
use Magento\Framework\Model\AbstractModel;
use MyVendor\MyModule\Api\Data\StudentInterface;
class Student extends AbstractModel implements StudentInterface
{
protected function _construct()
{
    parent::construct();
$this->_init(\MyVendor\MyModule\Model\ResourceModel\Student::class)
;
}
  public function getId()
  {
    return $this->_getData(self::ID);
  }
 
  public function getName()
  {
    return $this->_getData(self::NAME);
  }

  public function setId($id)
  {
    return $this->setData(self::ID, $id);
  }

  public function setName($name)
  {
    return $this->setData(self::NAME, $name);
  }
}


L’assaisonnement à la sauce « Injection de dépendance »

L’injection de dépendance est un principe utilisé dans plusieurs frameworks. Celui ci permet de définir les dépendances entre modules et se charge de l’instanciation et de l’injection des paramètres q’on lui passe.
Magento 2 fonctionnant avec ce principe, l'intérêt ici est de faire le lien entre nos interfaces du « service contract » avec la balise « preference ». Cela va donc permettre ici de dire que dès qu’on appelle notre interface “Student”, de l’API, ce sera la classe concrète du modèle qui sera utilisée. Donc pour respecter les bonnes pratiques, si vous souhaitez utiliser le modèle il faudra passer par l’interface de l’API. 

Cette bonne pratique facilite la maintenance du code mais améliore aussi sa flexibilité.

<?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\Data\StudentInterface" 
type="MyVendor\MyModule\Model\Student"/>
  <preference for="MyVendor\MyModule\Api\StudentRepositoryInterface" 
type="MyVendor\MyModule\Model\StudentRepository"/>
</config>

Bien évidemment l’injection de dépendance ne se limite pas uniquement à ce petit morceau de code. Plus vous avancerez dans cette recette, plus vous en saurez !  

La première partie est désormais finie. Une recette a souvent besoin de laisser un peu reposer les préparations, allez prendre un petit café et revenez vite pour la seconde partie : Apporter de la saveur. Car c’est bien beau d’avoir des objets mais pour l’instant ils sont encore un peu fades non ?


>>> Lire la Partie 2 : Apporter de la saveur.

Nos articles

Découvrir aussi

  • Une analyse profonde d’un site Magento est cruciale pour comprendre les enjeux avant d’entamer une reprise de projet. Dans la première partie de notre article, nous avons abordé les problématiques liées à la qualité du code et aux performances. Dans ce second volet nous allons nous concentrer sur les aspects techniques et marketing d’un audit de projet Magento.

  • Lors de nos développements en local, nous utilisons généralement PHPMyAdmin ou l’outil embarqué de PHPStorm, car ils sont simples d’utilisation, rapides et complets. Mais quand il s’agit de manipuler des bases de préproduction et production, c’est un peu plus délicat, car il n’est pas recommandé d’installer un PHPMyAdmin sur ces environnements pour une question de sécurité. Mais du coup comment faire ? Faire du SQL en CLI, connecté en SSH ? Non merci, pas très pratique.

  • Ô noble voyageur du web ! Votre longue route vous a mené ici, poussé par la curiosité et une appétence certaine pour le monde du e-commerce. Vos doigts courent sur le clavier, tel un matelot s’affairant sur le pont d’un navire. Votre âme est un trois-mâts en quête de connaissance, et voici le dénouement de votre épuisant périple. Cet article sera je l’espère, une escale des plus enrichissantes : voici le « Store Locator » illustré par sa mise en place technique sur Bananamoon.

Abonnez-vous au blog pour ne rien louper