如果没有为对象本身设置,我有一个可以从父级继承的关系。
对于示例设置,假设我们有具有场地的事件。
class Event extends Model
{
public function venue()
{
return $this->belongsTo('App\Venue');
}
public function activities()
{
return $this->hasMany('App\Activity');
}
}
活动中的活动主要发生在同一地点,但有时可能在其他地方,同时仍然属于同一事件。
class Activity extends Model
{
public function event()
{
return $this->belongsTo('App\Event');
}
public function venue()
{
if ($this->venue_id)
return $this->belongsTo('App\Venue');
return $this->event->venue();
}
}
如果我只是为活动请求活动并与他们一起工作,那很好。但是,如果我试图加载场地进行活动,我只会获得直接在活动中设置的场景,而不是从父级请求场景。
$activities = $event->activities;
$activities->load('venue'); // Works correctly without this line
foreach ($activities as $activity)
if ($activity->venue) // Doesn't take venue from the parent (event)
echo $activity->venue->name; //Only shows if venue_id is set on activity
有没有机会修复关系,以便我可以批量加载它们?
答案 0 :(得分:0)
就其本质而言,急切加载的关系没有为每个父模型运行关系方法。如果他们这样做了,你就会遇到N + 1问题,这正是急切加载意味着要解决的问题。
关系方法在用于启动查询的模型上运行一次。这将使基本查询运行,然后将所有父模型ID注入到该查询中。
为了做你想做的事,你需要稍微改变一下。首先,您的Activity
可以与场地直接相关,因此无任何条件地设置该关系。接下来,创建一个访问者方法,该方法将返回Activity
的正确位置。
因此,您的代码看起来像:
class Activity extends Model
{
public function event()
{
return $this->belongsTo('App\Event');
}
public function venue()
{
return $this->belongsTo('App\Venue');
}
public function getActivityVenueAttribute()
{
return $this->venue ?? $this->event->venue ?? null;
}
}
另一种选择是始终在venue_id
上分配Activity
,即使它与Event
venue_id
相同。然后您不必担心活动中缺少场地ID。