Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Senior Eloquent

Що таке глобальні скопи і в чому їхня небезпека?

Глобальний скоп додає умову до всіх запитів моделі автоматично. SoftDeletes - саме такий скоп: він дописує where deleted_at is null, і тому видалені записи не з'являються у вибірках.

Свій скоп через атрибут:

use Illuminate\Database\Eloquent\Attributes\ScopedBy;

#[ScopedBy(PublishedScope::class)]
class Post extends Model
{
}

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

Зняти на один запит:

Post::withoutGlobalScope(PublishedScope::class)->get();
Post::withoutGlobalScopes()->get();

У чому небезпека. Умова застосовується там, де її ніхто не бачить у коді виклику:

  • Адмінка показує не все. Редактор відкриває список і не бачить чернеток, бо скоп мовчки їх відрізав. Помилка виглядає як зникнення даних.
  • Підрахунки брешуть. Post::count() рахує лише опубліковані, і звіт розходиться з базою без видимої причини.
  • Зв'язки теж під скопом. $user->posts віддає відфільтроване, і зовні це не помітно.
  • updateOrCreate може створити дубль. Пошук не знаходить існуючий запис, бо той відрізаний скопом, і замість оновлення відбувається вставка.

Практичне правило: глобальний скоп доречний, коли умова справді інваріант для всієї моделі - як SoftDeletes чи розділення по тенантах. Для «зазвичай потрібні лише опубліковані» краще локальний скоп: він явний у місці виклику.

public function scopePublished(Builder $query): void
{
    $query->where('is_published', true);
}

Post::published()->get();   // видно, що фільтр застосовано

Докладніше в документації: Eloquent

2

Схожі питання