ElasticModel permet de stocker des données structurées en JSON tout en les manipulant comme des propriétés PHP classiques. Cette couche technique combine la flexibilité du JSON avec la puissance des ActiveRecord Yii2, offrant ainsi un modèle de données qui peut évoluer sans casser le code existant.
Concrètement, ElasticModel résout le problème classique des CMS : comment gérer des types de contenu différents sans multiplier les tables ni créer des colonnes inutilisées. La solution repose sur trois piliers : stockage JSON flexible, validation via JSON Schema, et manipulation transparente via ActiveRecord.
Important
ElasticModel répond à des cas d'usage très spécifiques dans Blackcube. Pour des besoins de stockage JSON plus généraux, privilégier une base de données orientée documents.
Pourquoi ElasticModel ?
Le problème des CMS traditionnels
Dans un CMS, gérer différents types de contenu pose un problème architectural :
- Table
articles, tableproduits, tabletemoignages, etc. - Complexe à maintenir quand on a des dizaines de types
- Code dupliqué pour chaque type
- Colonnes
field1,field2...field50 - Utilisées ou pas selon le type
- Confusion : quelle colonne pour quel type ?
- Gaspillage d'espace
- Flexible mais pas structuré
- Impossible de valider
- Pas de recherche sur les champs
- Risques de sécurité
- Une seule table avec JSON structuré
- Schéma défini par type
- Validation automatique
- Structure maintenue
La solution : modèle élastique
ElasticModel combine :
- JSON pour stocker les données de manière flexible
- JSON Schema pour valider la structure selon le type
- ActiveRecord Yii2 pour manipuler comme du code classique
Chaque type de contenu a sa propre structure, stockée de manière cohérente, sans multiplication de tables ou de colonnes.
Exemple concret d'évolution
Version 1 - Structure "contact" :
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
}
},
"required": ["name", "email"]
}
Données existantes :
{
"name": "Marie Dupont",
"email": "marie@example.com"
}
Version 2 - Ajout d'un téléphone :
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"phone": {
"type": "string"
}
},
"required": ["name", "email"]
}
Les anciennes données restent valides. Le champ phone est optionnel. Le code continue de fonctionner, $item->phone retourne null pour les anciens enregistrements.
Attention
La rétrocompatibilité ne fonctionne que dans un sens : ajouter des champs optionnels. Si un champ est supprimé du schéma, même si les données existent encore en base, la propriété n'est plus accessible via ElasticModel.
Exemple : schéma v1 avec username et email, schéma v2 sans username. Même si les anciennes données contiennent encore username en base, $bloc->username lèvera une exception car le champ n'est plus déclaré dans le schéma.
Pour gérer ces cas, vérifier l'existence de l'attribut :
if ($bloc->hasAttribute('username')) {
echo $bloc->username;
} else {
// Le champ n'est plus dans le schéma actuel
}
Avantages concrets
- Modèle élastique : La structure peut grossir sans toucher au code
- Rétrocompatibilité : Les anciennes données continuent de fonctionner
- Validation automatique : Chaque sauvegarde vérifie la conformité au schéma
- Flexibilité : Ajouter/supprimer des champs à volonté
Comment ça marche ?
Le schéma définit la structure
Un JSON Schema décrit la structure attendue des données :
{
"type": "object",
"properties": {
"title": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
}
}
}
Les données sont stockées en JSON
Dans la base de données, un champ data contient les valeurs réelles :
table_example
├─ id : 1
├─ schemaId : 5
└─ data : {"title": "Contact", "email": "contact@example.com"}
Manipulable comme un ActiveRecord
ElasticModel transforme le JSON en propriétés PHP accessibles naturellement :
$item = Item::findOne(1);
// Lecture
echo $item->title; // "Contact"
echo $item->email; // "contact@example.com"
// Écriture
$item->title = "Nouveau titre";
$item->email = "nouveau@example.com";
$item->save();
Sous le capot :
$item->titlelit dansdata->title$item->title = "..."modifiedata->title$item->save()valide contre le JSON Schema puis sauvegarde
Requêtes sur les données JSON
ElasticModel permet de requêter directement dans le JSON :
// Rechercher par email
$items = ElasticModel::find()
->andWhere(['email' => 'johndoe@example.com'])
->all();
// Rechercher par nom
$items = ElasticModel::find()
->andWhere(['name' => 'John Doe'])
->all();
// Combiner plusieurs conditions
$items = ElasticModel::find()
->andWhere(['active' => true])
->andWhere(['email' => 'johndoe@example.com'])
->all();
Contrairement au HTML brut, les données restent requêtables même en JSON.
JSON Schema : validation automatique
Qu'est-ce que JSON Schema ?
JSON Schema est un standard pour décrire et valider des structures JSON. Il définit :
- Les propriétés attendues
- Leurs types (string, number, boolean, etc.)
- Les contraintes (requis, format, longueur, etc.)
Exemple de schéma complet
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 3,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
},
"description": {
"type": "string"
},
"active": {
"type": "boolean",
"default": false
}
},
"required": ["name", "email"]
}
Ce schéma dit :
name: chaîne obligatoire, entre 3 et 100 caractèresemail: email obligatoire, validé automatiquementdescription: chaîne optionnelleactive: booléen optionnel, false par défaut
Validation à la sauvegarde
Quand des données sont sauvegardées, Blackcube :
- Récupère le JSON Schema associé
- Valide les données saisies
- Si valide :
active = 1, les données sont utilisables - Si invalide :
active = 0, les données restent en brouillon
Exemple de validation échouée :
{
"name": "AB",
"email": "contact@example.com"
}
Erreur : name fait 2 caractères, minimum requis = 3. Les données restent active = 0 jusqu'à correction.
Formats spéciaux
Formats supportés par JSON Schema
Le JSON Schema supporte plusieurs formats de validation :
"format": "email": Validation d'email"format": "uri": URL valide"format": "date": Date au format ISO"format": "date-time": Date + heure"format": "ipv4": Adresse IPv4"format": "ipv6": Adresse IPv6
Exemple :
{
"email": {
"type": "string",
"format": "email"
},
"website": {
"type": "string",
"format": "uri"
}
}
Format spécifique Blackcube : file
Blackcube ajoute un format file pour les fichiers uploadés :
{
"avatar": {
"type": "string",
"format": "file"
}
}
Le fichier est stocké avec un préfixe spécial @blackcubefs/ :
{
"avatar": "@blackcubefs/photo-2024.jpg"
}
Cas d'usage
Quand utiliser ElasticModel ?
Parfait pour :
- Contenu structuré variable
- Données qui évoluent fréquemment
- Structures différentes selon le contexte
- Validation de formulaires dynamiques
Exemples concrets :
- Contenu éditorial structuré
- Formulaires configurables
- Paramètres d'applications
- Configuration dynamique
Quand NE PAS utiliser ElasticModel ?
Éviter pour :
- Données relationnelles complexes
- Requêtes SQL avancées sur les données
- Index de recherche dans les données JSON
- Relations many-to-many dans le JSON
Exemples où SQL classique est préférable :
- Tables d'utilisateurs
- Système de commandes e-commerce
- Relations produits/catégories
- Logs avec recherche avancée
Limites à connaître
- Performance : JSON moins rapide que colonnes SQL natives pour les requêtes complexes
- Index : Index possible sur certains champs mais pas aussi performant que SQL natif
- Relations : Les foreign keys ne fonctionnent pas dans le JSON
ElasticModel utilise les fonctions JSON de MySQL/MariaDB pour rendre les données requêtables, ce qui est un avantage par rapport au HTML brut.
Application dans Blackcube
ElasticModel est la couche technique qui permet à Blackcube de gérer du contenu structuré flexible.
Blackcube utilise ElasticModel pour stocker des données structurées dont le schéma peut évoluer. Le modèle s'adapte automatiquement quand la structure grossit.
En pratique :
// Un élément avec son schéma :
{
"title": { "type": "string" },
"description": { "type": "string" },
"email": { "type": "string", "format": "email" }
}
// Manipulation via ElasticModel :
$item->title = "Mon élément";
$item->description = "Description détaillée";
$item->email = "contact@example.com";
$item->save();
Le modèle est élastique : ajouter un champ phone dans le schéma ne casse pas le code existant. $item->phone retourne simplement null pour les anciens enregistrements.
Points clés à retenir
- Modèle élastique : La structure peut grossir sans remettre le code en question
- JSON Schema : Validation automatique de la structure
- Rétrocompatibilité : Les anciennes données continuent de fonctionner
- Requêtable : Les données JSON sont interrogeables comme du Yii2 classique
- Transparent : Le développeur manipule des propriétés PHP, pas du JSON
- Utilisé par le système de blocs : Base technique de Blackcube
- Cas spécifiques : Pour du stockage JSON général, préférer une base de données orientée documents