Besoin d'aide ?

Comment stocker une implémentation d'interface sur un modèle ?

Avatar de PierreL
PierreL

Bonjour à tous,

J'ai un problème pour modéliser la relation entre un modèle et les différentes implémentations d'une interface. Je m'explique : j'ai un modèle Shop, qui représente des boutiques en ligne.

class Shop extends Model {
}

Chaque Shop est d'un certain type (Shopify, PrestaShop, WooCommerce etc.), qui porte ses particularités (connexion API par exemple). Mon idée était donc de faire une interface Api, avec une implémentation pour chaque type de boutique. On aurait donc les classes suivantes :

interface Api {
    public function listOrders();
}

class PrestaShop implements Api {
     public function listOrders()
     {
         // appels api
     }
}

class Shopify implements Api {
     public function listOrders()
     {
         // appels api
     }
}

Mon problème est la manière dont je doit m'y prendre pour stocker l'implémentation de cette interface sur chacune des entités de mon modèle.

  • Est-ce que je dois, par exemple, stocker en base de données le nom de la classe dans une colonne ?
  • Ou alors m'y prendre différemment et créer des extensions de mon modèle principal Shop pour chaque type (final class ShopifyShop extends Shop) ?
  • Ou encore regarder du côté des relations polymorphiques ?
  • Ou bien existe-t-il une manière plus adaptée pour établir ce genre de relation ?

EDIT je suis tombé sur ce package qui ressemble à ce que je veux obtenir : https://github.com/calebporzio/parental. Je reste curieux de connaître vos bonnes pratiques.

Merci !

Posté il y a 1 mois
Avatar de nash
nash

salut,

Pense dans un premier temps ton model object avec orm de laravel et on schema de db, ensuite tu pourra voir ta logique metier. je t'invite à regarder ce patron de conception (à titre d'exemple selon ta demande) pour ta logique metier. https://refactoring.guru/fr/design-patterns/factory-method/php/example#lang-features

Posté il y a 1 mois
Avatar de PierreL
PierreL

Merci pour la ressource, c'est très clair.

Pour mon problème, j'ai finalement opté pour l'hértitage de mon modèle principal en sous-modèles spécifiques, et chacun de mes modèles enfants implémentent une même interface. Dans mon parent, je surcharge la méthode newFromBuilder (comme le fait le package calebporzio/parental), ce qui permet d'obtenir une instance du modèle enfant de mon choix.

Voilà à quoi ressemble désormais mon modèle parent :

public function shopTypesMap()
{
    // tableau associatif "type" => "classe du modèle enfant"
    return [
        'woocommerce'  => WooCommerce::class,
        'prestashop'   => PrestaShop::class,
        'shopify'      => Shopify::class,
        // ...
    ];
}

public function newFromBuilder($attributes = [], $connection = null)
{
    $type = data_get($attributes, 'type'); // colonne "type" en BDD
    $types = $this->shopTypesMap();

    if( !array_key_exists($type, $types) ){
        throw new ShopWithoutValidType();
    }

    $classname = $types[$type];
    $model = new $classname;

    $model->exists = true;
    $model->setRawAttributes((array) $attributes, true);
    $model->setConnection($connection ?: $this->connection);

    return $model;
}
Posté il y a 1 mois

Vous ne pouvez pas répondre à ce sujet.