我与反向方法有一个标准的一对多关系:
class Place
{
public function hotels()
{
return $this->hasMany('Hotel');
}
}
class Hotel
{
public function place()
{
return $this->belongsTo('Place');
}
}
一切正常。
在我的控制器中,我需要在一个方框中显示每个酒店的列表,所以我创建了类似的东西:
//place.blade
<h1>{{ $place->name }}</h1>
@foreach($place->hotels as $hotel)
@include('partials.hotels-box', ['hotel' => $hotel])
@endforeach
//partials/hotels-box.blade
<a href="route('hotelRoute', ['hotel' => $hotel->name, 'place' => $hotel->place->name) }}">
{{ $hotel->name }}
</a>
@endforeach
一切正常。
但是,在hotels-box.blade里面,每当我访问$hotel
内的地方模型时,Eloquent都会启动一个新查询(即使该地点总是相同的,它也是触发{{ {1}})。
我想到的唯一想法是避免这些问题:
@foreach
传递给部分并使用它而不是$place
$hotel->place
但我不喜欢他们。
答案 0 :(得分:1)
您可以将$place
模型与$hotel
一起传递到部分视图。然后,不是使用反向关系来获取地名,而是可以通过$place->name
得到它。
或者,如果由于某种原因你不喜欢这样做,你也可以在查询中急切加载反向关系:
$places = Place::with('hotels', 'hotels.place')->get();
答案 1 :(得分:0)
您似乎遇到的是一个急切的加载问题,也称为n + 1。酒店模型尚未加载Place
关系,因此每次都必须执行新查询。
最简单的解决方案似乎是你可以在你的部分中调用$place->name
而不是$hotel->place->name
,但这只能解决问题,如果只从你的代码中调用部分。提供。如果从$place
不存在的其他地方调用它,那么您将不得不解决急切的加载问题。
您应该能够像控制器那样急切地加载控制器:
$place = Place::with('hotels.place')->get ()
请注意,点符号用于添加关系的子关系。因此,原始html将无需任何更改即可使用,我们只添加了一个新查询。
答案 2 :(得分:0)
如果在从DB获取“模型”值时未获取关联数据,则每次访问该数据时都会进行查询。要解决此问题,您应该在从db获取时获取关联数据。
例如,当你写:
$palce = Place::all();
它仅查询以获取places
表的所有行。需要注意的是,此查询不会提取任何关联的hotel
。
如果你写,
$hotels = $place->hotels;
将对db进行另一个查询,以获取与该hotels
相关联的$place
表的所有行。
然后写下如下:
foreach($palce->hotels as $hotel){
$palce = $hotel->place;
}
然后,在每次迭代时foreach
循环内部,都会进行新的JOIN
查询,以便与place
关联hotels
。
解决方案1: 您可以在执行第一个查询时加载所有必需的数据,如下所示:
$places = Place::with('hotels', 'hotels.place')->get();
但是这个解决方案的问题是,你得到hotels by place
,然后得到相同的place by hotels
。由于您已经拥有join
,因此无需place
次查询,无需再次获取place by hotels
。
解决方案2(更好):
$places = Place::with('hotels')->get();
在视图中,做这样的事情:
@foreach($place->hotels as $hotel)
@include('partials.hotels-box', ['hotel' => $hotel, 'place' => $place])
@endforeach
然后,在$palce
中使用partials.hotels-box
。我想你明白了我的意思。