Laravel-渴望在多对多实现中加载单个项目


Laravel - Eager Load Single Item in a ManyToMany Realtionship

在拉拉维尔中,是否可以从BelongsToMany关系中预先加载"第一个"项目? 例如,从该关系中返回Item,而不是Collection

根据我尝试(和阅读)的内容,应用first()limit('1')或任何其他约束不会返回单个项目

使用访问器。

我想你需要像 latestfirst 或集合中的此类单项,所以你可以这样做:

public function items()
{
  return $this->belongsToMany(Item::class);
}
public function getLatestItemAttribute()
{
  return $this->items->sortByDesc('created_at')->first();
}

然后,您可以简单地使用:

$yourModel->latestItem; // single related model OR null

编辑:正如@Hkan在注释中提到的,上面的代码将导致获取整个集合并对其进行处理。也就是说,您可以使用替代关系对象并直接查询表:

public function getLatestItemAttribute()
{
  return $this->items()->latest()->first();
}

但是,这样,只要您调用 $model->latestItem 即可运行查询。因此,您将获得模型的新副本,而不是相同的实例,显然您可以查询数据库任意次数,具体取决于您的用例。

困难但最好的方法是模仿这种关系:

public function getLatestItemAttribute()
{
  if (!$this->relationLoaded('latestItem')) {
    $this->setRelation('latestItem', $this->items()->latest()->first());
  }
  return $this->getRelation('latestItem');
}

在这种情况下,加载后$model->latestItem被视为任何其他单一关系。也就是说,每当调用访问器时,它都将是单个实例,并且在使用push方法时将被保存。

@djt我也在寻找一个我可以eager load relationship with only one item的解决方案,并尝试了一切,似乎除了joins之外没有这样的解决方案

Collection::select('items.item_name as name', 'items_sub.sub_name as subname')
->leftJoin('items_sub', function ($join) {
    $join->on('items.id', '=', 'items_sub.item_id')->where('items_sub.type', '=', 0);
})->get();

这样你就可以得到所有Collection function helpers而且它减少了您对数据库的查询量,因为当您eager load with Eloquent时,它至少会对数据库进行 2 次查询我添加了where作为示例。