🔹 Query Scopes
Смотришь на свой код и замечаешь одно и то же в пяти местах:
->where('status', 'active')->where('deleted_at', null)
->where('status', 'active')->where('deleted_at', null)
->where('status', 'active')->where('deleted_at', null)Это не переиспользование кода. Это его копирование. Разница важная.
▪️ Local Scope — прячем логику в модель
// User.php
public function scopeActive(Builder $query): Builder
{
return $query->where('status', 'active')
->whereNull('deleted_at');
}
public function scopeVerified(Builder $query): Builder
{
return $query->whereNotNull('email_verified_at');
}
Теперь вместо цепочки условий — читаемый вызов
// Было
User::where('status', 'active')
->whereNull('deleted_at')
->whereNotNull('email_verified_at')
->get();
// Стало
User::active()->verified()->get();
▪️ Scope с параметром
Иногда нужна гибкость. Scope принимает аргументы:
public function scopeOlderThan(Builder $query, int $days): Builder
{
return $query->where('created_at', '<', now()->subDays($days));
}
phpUser::active()->olderThan(30)->get();
▪️ Global Scope — когда условие должно быть всегда
Если SoftDeletes работает по всему приложению — это глобальный скоуп под капотом. Можно написать свой:
// В модели
protected static function booted(): void
{
static::addGlobalScope('tenant', function (Builder $builder) {
$builder->where('tenant_id', auth()->user()?->tenant_id);
});
}
Теперь все запросы к этой модели автоматически фильтруются по тенанту. Без единого where в контроллерах.
Библиотека пхпшника
#php_азбука