Я делаю приложение для планирования свадьбы, где пользователи могут добавлять своих гостей к определенным столам, группам и т. д.
Я пытаюсь составить список всех групп и внутри каждой группы показать каждого гостя в этой группе (на той же странице, что и аккордеон)
Кажется достаточно простым, и это работает, но при использовании DebugBar я вижу, что он делает 2 абсолютно одинаковых запроса, и я не могу понять, почему.
В мероприятии может участвовать множество групп, и в каждой группе может быть много гостей.
$event = Event::find($id_event);
$event->load('group');
$event->group->load([
"guest" => function ($q) {
return $q->paginate(10);
}
]);
Результат:
Редактировать
Забыл упомянуть, что если я добавлю к этому какие-либо другие отношения, они также будут дублировать их.
$event->group->load([
'guest.plusone',
"guest" => function ($q) {
$q->paginate(10);
}
]);
Редактировать 2
Пытаясь сделать то, что вы предложили, я нашел причину этого, но до сих пор не знаю, почему.
Когда я пытаюсь сделать то, что вы предложили, я получаю тот же результат
$event->load(['group', 'group.guest' => function ($query) {
$query->paginate(10);
}]);
Но если я удалю обратный вызов для нумерации страниц, я получу только один запрос. Это нормально? Я знаю, что нумерация страниц выполняет один дополнительный запрос, чтобы получить общие результаты, но в данном случае она делает 3 запроса, и 2 из них абсолютно одинаковы.
@krisgjika На самом деле это приложение уже готово, но было создано одним из наших стажеров, поэтому у него есть множество проблем с производительностью. Я боюсь менять эти отношения, поскольку они могут создать еще больше проблем. Что касается вашей рекомендации, вы можете увидеть изменения выше.
возможно, вы путаете limit
с paginate
? зачем вам разбивать модели отношений на страницы?
также убедитесь, что вы используете Laravel 11 при использовании ограничений на запросы внутренних отношений, поскольку результат может быть не таким, как вы ожидаете.
Нам нужна разбивка на страницы, потому что вы можете иметь неограниченное количество групп. Если мы перечислим 100 групп, в каждой из которых будет по 100 гостей, будет загружено более 1000 гостей. Мы использовали разбиение на страницы, чтобы не выполнять нумерацию страниц вручную. Но я только что проверил с лимитом, и все работает нормально.
Я попробовал обновиться до laravel 11, но это так же просто: нам нужно переделать всю интеграцию кассовой полосы. Я думаю, что предпочту сделать нумерацию вручную
При использовании очереди диспетчеризация не должна выполняться в методах, приводящих к отображению представления, попробуйте использовать ее в методах, не возвращающих представление.
Прежде всего, для того, что вы делаете, результат двух запросов очень ожидаем. См. ниже объяснение:
Объяснение:
$event = Event::query()->find($id_event);
$event->load(['group.guest' => fn ($with) $with->paginate(10)]);
при вызове paginate вы принудительно запускаете запрос, тот же запрос, который был построен на основе определений отношений до этого момента. То же самое произойдет при звонке $with->get()
. Но замыкание не ожидает, что вы запустите запрос, и не заботится об этом, а только изменяет запрос, предоставленный внутри. Итак, после того, как запрос выполняется через paginate
, обратите внимание, что его результат нигде не используется, замыкание заканчивается, и Laravel запускает запрос на загрузку отношений, как обычно.
Для Ларавел 11:
для того, чего вы хотите достичь, ограничьте количество загруженных моделей отношений до 10 на группу, вам нужно использовать ограничение. Limit не запускает запрос, но изменяет объект запроса, включив в него ограничение при его запуске.
$event = Event::query()->find($id_event);
$event->load(['group.guest' => fn ($with) $with->limit(10)]);
До Laravel 11:
хотя вы можете сделать то же самое в Laravel 10, результат будет другим. Ограничение будет применяться ко всем загруженным гостям, а не к группе. Итак, если у вас есть группы А и Б по 10 гостей в каждой. Полученные данные будут включать 10 гостей группы A и 0 гостей группы B. Это связано с тем, что всего загружено только 10 гостей, а не 10 для каждой группы.
$event = Event::query()->find($id_event);
$event->load(['group.guest' => fn ($with) $with->limit(10)]);
Чтобы добиться той же функциональности, вам необходимо включить https://github.com/staudenmeir/eloquent-eager-limit в свой проект и следовать его инструкциям. (В Laravel 11 этот пакет был объединен)
Прежде всего, попробуйте назвать свои отношения по их типу, например, если в мероприятии много групп, назовите отношение «группы», а не «группа», то же самое для гостей. Во-вторых, можете попробовать
$event->load('group.guest');
и посмотреть, какие запросы выполняются. Какие запросы выполняются в этом случае не только без вызова load?