Модель Laravel относится к проблеме загрузки отношений

У меня есть две модели: Box и BoxLocations. Box имеет hasMany отношение к BoxLocations, а BoxLocations имеет belongsTo отношение к Box.

BoxLocations также имеет атрибут, который добавляется к модели, требующей одной части информации из отношения Box.

Я заметил, что при вызове Box::with(['BoxLocations']->)all(); я вижу, что модель BoxLocations перезагружает отношение Box. Это происходит для каждого BoxLocation (50 с лишним раз)

Разве laravel не отслеживает, что Box уже был загружен из первоначального запроса Box::with(['BoxLocations']->)all();, а затем передает это в отношение BelongsTo?

Я пытаюсь оптимизировать веб-систему, и когда загруженный атрибут загружается (досадно, что он требуется каждый раз, когда он также загружается), он вызывает 50 нечетных обращений к базе данных для той же модели Box, которую он уже загрузил.

Если laravel этого не делает - есть ли лучший способ добиться этого?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
0
0
629
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Laravel использует нетерпеливая загрузка, когда вы используете метод with().

When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. However, Eloquent can "eager load" relationships at the time you query the parent model. Eager loading alleviates the N + 1 query problem.

Итак, если вы сделаете это:

$boxes = Box::with('BoxLocations')->get();

Он уже загрузит отношения, но, скажем, вы сделаете это:

$boxes = Box::all();

foreach($boxes as $box)
{
  echo box->boxlocation->name;
}

Если у вас есть 50 ящиков, этот цикл будет выполнять 51 запрос.

Но когда вы используете метод with и загружаете отношение, этот цикл будет выполнять только 2 запроса.

Вы также можете использовать Ленивая нетерпеливая загрузка и решить, когда вы хотите загрузить отношения

Я отметил этот ответ как правильный; однако я обнаружил, что laravel по-прежнему выполняет больше запросов, чем мне нужно, с помощью этого метода. Я обнаружил, что гораздо лучше написать запрос к БД, чтобы получить поля, которые я хотел, в одном вызове БД, а не позволять отношениям laravels обращаться к базе данных несколько раз.

Scott-David Jones 13.03.2019 16:43

Спасибо, не могли бы вы сказать мне, сколько запросов выполнялось с использованием отношений? это может быть ошибка, и мы могли бы сообщить об этом. Кроме того, я был бы признателен, если бы вы показали запрос, который вы сделали

Piazzi 13.03.2019 16:53

Я не могу сейчас вспомнить код, но в основном у меня была таблица производителей, скажем, «Apple», и таблица устройств с множеством продуктов Apple. При выполнении Devices::with('manufacturers')->get() вы получаете один запрос для каждого производителя устройств. Я думаю, что он должен получить производителя для первого, а затем кэшировать его для остальных. Однако это в устаревшем коде laravel 5.5 ... так что сейчас это может не быть проблемой.

Scott-David Jones 10.04.2019 13:04

Другие вопросы по теме