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

Що вмикає Model::shouldBeStrict і які помилки він ловить до продакшену?

Eloquent за замовчуванням поблажливий: багато помилок не падають, а мовчки дають неправильний результат. Model::shouldBeStrict() вмикає три перевірки одночасно:

// AppServiceProvider::boot()
Model::shouldBeStrict(! $this->app->isProduction());

1. preventLazyLoading - заборона лінивого завантаження зв'язків:

$posts = Post::all();
foreach ($posts as $post) {
    $post->author->name;   // LazyLoadingViolationException
}

Ловить N+1 у момент написання коду, а не після скарг на повільну сторінку. Виправлення - Post::with('author').

2. preventSilentlyDiscardingAttributes - помилка при масовому заповненні полями, яких немає в $fillable:

User::create(['name' => 'Olena', 'is_admin' => true]);   // MassAssignmentException

Без суворого режиму is_admin мовчки відкидається. Звучить безпечно, але це й джерело багів: додали поле у форму, забули в $fillable - дані не зберігаються, і ніхто не розуміє чому.

3. preventAccessingMissingAttributes - помилка при зверненні до атрибута, якого немає в моделі:

$user = User::select('id', 'name')->first();
$user->email;   // MissingAttributeException замість тихого null

Ловить запити з неповним select() і опечатки в назвах атрибутів.

Чому не на продакшені: виняток у лінивому завантаженні ламає сторінку для користувача там, де раніше вона просто працювала повільніше. Тому типова схема - суворо в розробці й тестах, м'яко на продакшені з логуванням:

Model::preventLazyLoading();

Model::handleLazyLoadingViolationUsing(function (Model $model, string $relation): void {
    if (app()->isProduction()) {
        Log::warning('Lazy loading', ['model' => $model::class, 'relation' => $relation]);

        return;
    }

    throw new LazyLoadingViolationException($model, $relation);
});

Нюанси:

  • одна модель - лінивий виклик зв'язку для моделі, отриманої не в колекції, не вважається порушенням (N+1 там неможливий);
  • Model::automaticallyEagerLoadRelationships() - альтернативний підхід: Eloquent сам довантажує зв'язок для всієї колекції при першому зверненні;
  • увімкнення на старому проєкті покаже десятки порушень - вмикайте поступово й лагодьте, інакше команда просто вимкне перевірку;
  • тести - найкраще місце для суворого режиму: порушення в тестах ламають CI ще до рев'ю.

Докладніше в документації: Eloquent: суворий режим

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

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