Comment stocker une implémentation d'interface sur un modèle ?
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 !
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
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;
}
Vous ne pouvez pas répondre à ce sujet.