Image de couverture : PostgreSQL JSONB dans Laravel : dites adieu aux migrations infinies
tech

PostgreSQL JSONB dans Laravel : dites adieu aux migrations infinies

23 March 2026
5 min de lecture
1 vues
Sébastien Muler

PostgreSQL JSONB dans Laravel : dites adieu aux migrations infinies

Toute application SaaS finit par rencontrer le même problème architectural : la gestion de données dynamiques. Vous commencez avec une table users bien propre, puis les demandes s'accumulent — préférences d'affichage, paramètres de notification, options métier... À chaque nouvelle fonctionnalité, une nouvelle migration, une nouvelle colonne nullable. Résultat : une table gonflée, difficile à maintenir, avec des dizaines de champs vides pour la majorité des utilisateurs.

Cet article s'appuie sur un excellent article publié sur dev.to par Paresh Prajapati pour explorer comment le type JSONB de PostgreSQL, combiné à Laravel, permet de résoudre élégamment ce problème.


Le problème : la table des paramètres cauchemardesque

Imaginez ce scénario classique :

  1. Semaine 1 — Le Product Manager demande une préférence de thème (clair/sombre).
  2. Semaine 3 — Il faut ajouter une heure de notification personnalisée.
  3. Semaine 6 — On veut stocker la langue préférée, le fuseau horaire, les préférences de dashboard...

Chaque étape génère une migration. Après quelques mois, votre table users ressemble à ceci :

ALTER TABLE users ADD COLUMN theme VARCHAR(20) NULL;
ALTER TABLE users ADD COLUMN notification_time TIME NULL;
ALTER TABLE users ADD COLUMN language VARCHAR(10) NULL;
ALTER TABLE users ADD COLUMN timezone VARCHAR(50) NULL;
-- ... et ça continue

Certains tentent de fuir vers MongoDB pour retrouver de la flexibilité. Mais ce choix implique de sacrifier l'intégrité relationnelle, les transactions ACID et les clés étrangères. La bonne nouvelle : PostgreSQL offre le meilleur des deux mondes avec le type JSONB.


JSONB : stockage binaire intelligent

PostgreSQL propose deux types pour stocker du JSON : JSON et JSONB. La différence est fondamentale :

  • JSON : stocke le texte brut tel quel. Rapide à l'écriture, mais lent à la lecture et non indexable efficacement.
  • JSONB : parse et stocke la donnée dans un format binaire optimisé. Les clés sont dédoublonnées, les espaces supprimés, et surtout — le champ est pleinement indexable.

Avec JSONB, PostgreSQL peut filtrer, trier et indexer les données imbriquées aussi efficacement qu'une colonne entière classique.

Mise en place dans Laravel

Ajouter une colonne JSONB dans une migration Laravel est trivial :

Schema::table('users', function (Blueprint $table) {
    $table->jsonb('preferences')->default('{}');
});

Une seule colonne pour remplacer des dizaines de colonnes nullables. ✅


Intégration avec Eloquent : le cast automatique

Laravel facilite considérablement la manipulation des colonnes JSONB grâce au système de casts Eloquent. En déclarant le cast array (ou object) dans votre modèle, Laravel se charge de la sérialisation et désérialisation automatiquement.

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'preferences' => 'array',
    ];
}

Lecture et écriture des préférences

// Lire une préférence
$theme = $user->preferences['theme'] ?? 'light';

// Modifier une préférence
$user->preferences = array_merge($user->preferences ?? [], [
    'theme' => 'dark',
    'language' => 'fr',
]);
$user->save();

Plus de colonne dédiée à gérer. La structure évolue côté applicatif, sans toucher au schéma de base de données.

💡 Conseil MulerTech : Pour les projets Symfony/PHP, une approche similaire est possible avec Doctrine et le type json de PostgreSQL. L'essentiel est de centraliser la logique de lecture/écriture dans un service dédié pour éviter la dispersion.


Requêtes avancées sur les données JSONB

L'un des atouts majeurs de JSONB est la possibilité d'interroger les données imbriquées directement en SQL, via les opérateurs PostgreSQL.

Filtrer par valeur JSON

// Récupérer tous les utilisateurs ayant le thème "dark"
$users = User::whereRaw("preferences->>'theme' = ?", ['dark'])->get();

Vérifier l'existence d'une clé

// Utilisateurs ayant défini une langue
$users = User::whereRaw("preferences \?\? 'language'")-> get();

Indexation GIN pour les performances

Pour les tables volumineuses, un index GIN permet d'accélérer drastiquement les recherches dans les données JSONB :

Schema::table('users', function (Blueprint $table) {
    $table->rawIndex("preferences", 'users_preferences_gin_idx', 'gin');
});

Ou directement en SQL :

CREATE INDEX users_preferences_gin_idx ON users USING gin(preferences);

Avec cet index, même sur des millions de lignes, les requêtes sur les champs JSONB restent performantes.


Bonnes pratiques et limites à connaître

Si JSONB est puissant, il ne doit pas devenir une solution miracle appliquée partout. Voici quelques recommandations :

✅ Utiliser JSONB pour :

  • Les préférences utilisateur
  • Les métadonnées variables (tags, attributs produit)
  • Les configurations spécifiques à un tenant (multi-tenant SaaS)
  • Les données dont la structure peut évoluer fréquemment

❌ Éviter JSONB pour :

  • Les données sur lesquelles vous faites des jointures régulières
  • Les champs utilisés dans des contraintes d'unicité ou des clés étrangères
  • Les colonnes nécessitant une validation stricte du type au niveau base de données

En résumé : JSONB complète le modèle relationnel, il ne le remplace pas.


Conclusion

Le type JSONB de PostgreSQL, combiné aux mécanismes de cast d'Eloquent, offre une solution pragmatique et performante pour gérer les données dynamiques dans vos applications Laravel. Vous évitez l'accumulation de migrations, vous gardez un schéma propre, et vous bénéficiez malgré tout des capacités de requêtage avancées de PostgreSQL.

Chez MulerTech, nous recommandons cette approche dans les projets où la flexibilité du schéma est un enjeu réel — notamment les applications SaaS multi-tenant ou les plateformes à forte personnalisation utilisateur.

N'hésitez pas à parcourir l'article source de Paresh Prajapati pour aller plus loin sur les cas d'usage avancés.

Partager cet article