У меня есть 2 модели, например, Country
и City
с отношениями one-to-many
.
Когда я запускаю этот код
$countries = Country::query()->with('cities')->get();
foreach ($countries as $country) {
$cities = $country->cities;
foreach ($cities as $city) {
dump($city->country);
}
}
, при каждом вызове $city->country
у меня есть запрос к БД
select * from `countries` where `countries`.`id` = ? limit 1
Если отношение (в моем случае cities.country
) не загружалось с жадной загрузкой, есть ли возможность предотвратить выполнение запроса к БД при каждом вызове $city->county
?
Мне не нужна переменная $country
. Мне нужно получить null
, если отношение cities.country
не было загружено в основном запросе.
@WouterVanDamme это просто для примера. Мне нужно получить null
, когда я звоню $city->country
в моем случае
Это не то, как работает laravel. Если вы попытаетесь вызвать отношение, которое не загружено, оно его загрузит. Как устроен ваш код, никогда не будет случая, когда $city->country
вернет null
. Если вы запросили City
напрямую и зациклили результаты, они могут быть, но вы запрашиваете Country
, а затем зациклили, так что этого никогда не будет.
@ТимЛьюис, спасибо
Я не понимаю, почему мой вопрос был заминусован. Это мой случай, и мне нужно решить его внутри моего Mapper и HttpResource. Это понижение является предвзятым.
Почему бы тогда не сделать обратное:
$cities = City::with('country')->get();
// this way you would loop only once:
foreach ($cities as $city) {
dump($city->country);
}
Используя ваш подход, тогда это:
foreach ($countries as $country) {
$cities = $country->cities;
foreach ($cities as $city) {
dump($country);
// here the $country variable
// is the same as the $city->country one, so no need to query it again..
}
}
Спасибо, но мне не нужно обратное, мне нужно прекратить вложенность отношений.
Вы хотите древовидную структуру? github.com/lazychaser/laravel-nestedset#installation
Тогда вы можете использовать мое редактирование.. не нужно вызывать $city->country
, когда в этом цикле $country
— это то, что у вас уже есть.. так зачем запрашивать его снова?
Мне не нужна переменная $country
. Мне нужно прекратить отношения вложенности, поэтому мне нужно null
при вызове dump($city->county)
Не могли бы вы посмотреть на свой вопрос и изменить его на то, что вам нужно, потому что из того, что вы сейчас спрашиваете, это ответ.
переопределите city
в вашей модели и явно поставьте return null;
, потому что ваш вариант использования вообще не имеет смысла :) Если вам нужно вернуть null, просто поставьте null
и все.
Благодаря
В моем случае
//...
if ($city->relationLoaded('country')) {
dump($city->country);
} else {
dump(null);
}
//...
Это хорошая проверка, но, пожалуйста, дайте мне знать, будет ли это когда-нибудь правдой для вашего варианта использования. Я действительно сомневаюсь в этом.
@nakov Если я хочу получить не нулевое, а значение $country
, я должен установить запрос with
как with('cities.country')
. Итак, с этой проверкой (relationLoaded
) у меня больше контроля над запросами к БД, основная цель достигнута.
Я хочу сказать, что это $city->relationLoaded('country')
никогда не вернется, потому что вы никогда не стремитесь загрузить страну из города, как вы упомянули в своем комментарии. Так что не вижу смысла в проверке вообще. Но вы лучше знаете свое дело, так что продолжайте, дискуссия все равно ни к чему не приведет :)
Это несправедливо, чем этот ответ был отклонен. Человек, который это сделал, не понял предмета. Может ли этот человек объяснить здесь, почему за него проголосовали?
зачем вам делать $city->country ? У вас уже есть объект страны прямо здесь....