Laravel - Eager在ManyToMany Realtionship中加载单个项目

时间:2016-03-07 04:15:12

标签: php laravel

在Laravel中,是否有可能首先加载“第一个'来自BelongsToMany关系的项目?如同,请从该关系返回Item,而不是Collection

我尝试(并阅读)应用first()limit('1')或任何其他约束不会返回单个项目

2 个答案:

答案 0 :(得分:4)

使用accessor

我猜您需要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方法时将被保存。

答案 1 :(得分:0)

@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 而且它还减少了您对DB的查询量, 因为当您eager load with Eloquent时,它会向提交至少2个查询 我添加了where jsut作为示例。