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

Як не допустити N+1 у продакшені системно, а не ловити його вручну?

Змусити застосунок падати на ліниве завантаження під час розробки й тестів - тоді N+1 не доходить до рев'ю.

// AppServiceProvider::boot()
Model::preventLazyLoading(! app()->isProduction());

Тепер $post->author без попереднього with('author') у локальному оточенні й тестах кидає LazyLoadingViolationException. Тести, що проходять сторінку, ловлять пропущені with() автоматично.

У продакшені не падати, а повідомляти:

Model::handleLazyLoadingViolationUsing(function (Model $model, string $relation) {
    Log::warning('Lazy loading', ['model' => $model::class, 'relation' => $relation]);
});

Model::shouldBeStrict() вмикає разом три перевірки: ліниве завантаження, мовчазне відкидання атрибутів поза $fillable і звернення до відсутніх атрибутів.

Інші інструменти:

  • Model::automaticallyEagerLoadRelationships() - Laravel сам довантажить зв'язок для всієї колекції, щойно звернулися до нього в однієї моделі. Зручна страховка, але приховує, які дані сторінка насправді тягне;
  • chaperone() на hasMany - дочірні моделі отримують посилання на батька без зайвого запиту ($comment->post у циклі);
  • лічильник запитів у тестах: перевірка, що сторінка робить не більше N запитів незалежно від кількості записів.

Пастка: ліниве завантаження в Blade-компонентах і вкладених Livewire-компонентах ховається найкраще - саме там ця заборона окупається.

Докладніше в документації: Заборона лінивого завантаження

Перевір себе

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

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