我有一个有效的查询:
Object::all()->with(['reviews' => function ($query) {
$query->where('approved', 1);
}])
我想限制返回的每个对象的评论数量。如果我使用:
Object::all()->with(['reviews' => function ($query) {
$query->where('approved', 1)->take(1);
}])
或
Object::all()->with(['reviews' => function ($query) {
$query->where('approved', 1)->limit(1);
}])
它限制了评论总数,其中我想限制每个对象返回的评论。我怎样才能做到这一点?
答案 0 :(得分:2)
雄辩的方式
在模型类中建立一个如下所示的关系
public function reviews() {
return $this->hasMany( 'Reviews' );
}
//you can pass parameters to make limit dynamic
public function firstReviews() {
return $this->reviews()->limit( 3 );
}
然后致电
Object::with('firstReviews')->get();
更快的方式(如果你只需要一次评论)
制作派生表以获取最新评论1,然后加入。
Object->select('*')
->leftJoin(DB::raw('(SELECT object_id, reviews FROM reviews WHERE approved=1 ORDER BY id DESC limit 0,1
as TMP'), function ($join) {
$join->on ( 'TMP.object_id', '=', 'object.id' );
})
->get();
答案 1 :(得分:2)
您可以创建帮助关系来轻松处理...
在Object
模型中
public function approvedReview()
{
return $this->hasOne(Review::class)->where('approved', 1);
}
然后你只使用它而不是你的其他关系。
Object::with('approvedReview')->get();
如果你需要超过1,事情开始变得更加复杂。我正在调整https://softonsofa.com/tweaking-eloquent-relations-how-to-get-n-related-models-per-parent/中找到的代码来解决此问题,并将其用于特征而不是BaseModel
。
我创建了一个新文件夹app/Traits
,并在此文件夹中添加了一个新文件NPerGroup.php
namespace App\Traits;
use DB;
trait NPerGroup
{
public function scopeNPerGroup($query, $group, $n = 10)
{
// queried table
$table = ($this->getTable());
// initialize MySQL variables inline
$query->from( DB::raw("(SELECT @rank:=0, @group:=0) as vars, {$table}") );
// if no columns already selected, let's select *
if ( ! $query->getQuery()->columns)
{
$query->select("{$table}.*");
}
// make sure column aliases are unique
$groupAlias = 'group_'.md5(time());
$rankAlias = 'rank_'.md5(time());
// apply mysql variables
$query->addSelect(DB::raw(
"@rank := IF(@group = {$group}, @rank+1, 1) as {$rankAlias}, @group := {$group} as {$groupAlias}"
));
// make sure first order clause is the group order
$query->getQuery()->orders = (array) $query->getQuery()->orders;
array_unshift($query->getQuery()->orders, ['column' => $group, 'direction' => 'asc']);
// prepare subquery
$subQuery = $query->toSql();
// prepare new main base Query\Builder
$newBase = $this->newQuery()
->from(DB::raw("({$subQuery}) as {$table}"))
->mergeBindings($query->getQuery())
->where($rankAlias, '<=', $n)
->getQuery();
// replace underlying builder to get rid of previous clauses
$query->setQuery($newBase);
}
}
在Object
模型中,导入特征use App\Traits\NPerGroup;
,不要忘记在您的课程声明下添加use NPerGroup
。
现在您要设置关系函数以使用特征。
public function latestReviews()
{
return $this->hasMany(Review::class)->latest()->nPerGroup('object_id', 3);
}
现在你可以像任何其他关系一样使用它,它将为每个对象加载3个最新评论。
Object::with('latestReviews')->get();