doganddev
Accueil Blog Boutique

Scopes Eloquent : global scopes et local scopes

DOG&DEV · 25/01/2025

Informatique Technique
Scopes Eloquent : global scopes et local scopes

Scopes Eloquent : global scopes et local scopes

Les scopes Eloquent permettent d’encapsuler des contraintes de requêtes (ex. is_active = true, deleted_at IS NULL, tenant_id = ?) pour les réutiliser et composer sans duplication. On distingue les global scopes (appliqués à toutes les requêtes du modèle) et les local scopes (appliqués sur appel : scopeActive(), scopeRole(), etc.). Ce guide couvre la création, l’enregistrement et le contournement avec withoutGlobalScope.

Prérequis

  • Projet Laravel avec Eloquent
  • Modèles avec colonnes utilisées dans les scopes (is_active, tenant_id, published_at, etc.)

1. Global scope (classe)

Un global scope est une classe qui implémente Illuminate\Database\Eloquent\Scope.

Création :

php artisan make:scope ActiveScope

Implémentation :

namespace App\Models\Scopes;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class ActiveScope implements Scope
{
    public function apply(Builder $builder, Model $model): void
    {
        $builder->where('is_active', true);
    }
}

Enregistrement sur le modèle :

use App\Models\Scopes\ActiveScope;

class User extends Model
{
    protected static function booted(): void
    {
        static::addGlobalScope(new ActiveScope);
    }
}

Dès lors, User::all(), User::find(1), User::count(), etc. incluent WHERE is_active = true.

2. Désactiver un global scope

Un scope précis :

User::withoutGlobalScope(ActiveScope::class)->get();

Tous les global scopes :

User::withoutGlobalScopes()->get();

Indispensable pour admin, jobs, audits ou exports qui doivent voir les enregistrements « inactifs » ou hors périmètre.

3. Global scope anonyme

Pour une règle simple et propre au modèle :

protected static function booted(): void
{
    static::addGlobalScope('published', function (Builder $builder) {
        $builder->where('published_at', '<=', now());
    });
}

Désactivation : withoutGlobalScope('published').

4. Local scope (méthode)

Un local scope est une méthode scope + Nom sur le modèle. Il n’est appliqué que lorsqu’on l’appelle.

Définition :

use Illuminate\Database\Eloquent\Builder;

class User extends Model
{
    public function scopeActive(Builder $query): Builder
    {
        return $query->where('is_active', true);
    }

    public function scopeRole(Builder $query, string $role): Builder
    {
        return $query->where('role', $role);
    }
}

Utilisation :

User::active()->get();
User::active()->role('admin')->get();
User::role('editor')->where('created_at', '>', now()->subMonth())->get();

5. Local scope qui retire un global scope

Parfois un local scope doit contourner un global (ex. « avec inactifs ») :

public function scopeWithInactive(Builder $query): Builder
{
    return $query->withoutGlobalScope(ActiveScope::class);
}
User::withInactive()->get();

6. Combiner global et local scopes

User::active()->role('editor')->latest()->paginate(20);

Le global applique la règle de visibilité ; les locaux filtrent selon le métier. Architecture typique pour une app qui grossit.

Quand ne pas utiliser de scopes

  • Logique métier complexe (workflows, calculs) → Services, Actions.
  • Décisions d’autorisationGates, Policies.
  • Orchestration entre plusieurs modèles → Services, Jobs.

Les scopes restent des contraintes de requêtes réutilisables, pas du domaine applicatif.

Dépannage

Symptôme Cause possible Correctif
Des lignes « inactives » apparaissent Global scope non enregistré ou désactivé Vérifier booted() et les appels withoutGlobalScope
scopeActive inconnu Faute de nom (scopeactive, ScopeActive) Méthode scopeActive ; appel User::active()
Conflit entre scopes Ordre ou logique where contradictoire Vérifier les where dans les scopes et les combiner (and/or) de façon cohérente

Bonnes pratiques

  • Global pour les contraintes obligatoires (soft delete, multi-tenant, is_active).
  • Local pour les filtres optionnels (role, statut, plage de dates).
  • Scopes nommés de façon claire (scopeActive, scopePublished, scopeForTenant).

Ressources


Cet article s’inscrit dans notre série de guides technique et développement web. Pour un serveur ou une application sur-mesure, contact.

Commentaires (0)

Laisser un commentaire