Laravel雄辩的极限结果 [英] Laravel eloquent limit results
问题描述
我有一个有效的查询:
Object::all()->with(['reviews' => function ($query) {
$query->where('approved', 1);
}])
我想限制返回的每个对象的评论数.如果我使用:
And I want to limit the number of reviews, per object, that is returned. If I use:
Object::all()->with(['reviews' => function ($query) {
$query->where('approved', 1)->take(1);
}])
或
Object::all()->with(['reviews' => function ($query) {
$query->where('approved', 1)->limit(1);
}])
它限制了评论总数,其中我想限制每个对象返回的评论.我该如何实现?
it limits the total number of reviews, where I want to limit the reviews that are returned by each object. How can I achieve this?
推荐答案
每个父母抓住1个孩子
您可以创建一个助手关系来非常轻松地处理此问题...
Grabbing 1 child per parent
You can create a helper relation to handle this very easily...
在您的Object
模型中
public function approvedReview()
{
return $this->hasOne(Review::class)->where('approved', 1);
}
然后,您只使用它而不是其他关系.
Then you just use that instead of your other relation.
Object::with('approvedReview')->get();
如果需要的数量超过1,事情就会变得复杂得多.我正在调整在 https://softonsofa.com/tweaking-eloquent-relations-how-to-get-n-related-models-per-parent/来解决此问题,并将其用于特质而不是
If you need more than 1, things start to become quite a bit more complex. I'm adapting the code found at https://softonsofa.com/tweaking-eloquent-relations-how-to-get-n-related-models-per-parent/ for this question and using it in a trait as opposed to a BaseModel
.
我创建了一个新文件夹app/Traits
,并将新文件添加到该文件夹NPerGroup.php
I created a new folder app/Traits
and added a new file to this folder 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
.
In your Object
model, import the trait use App\Traits\NPerGroup;
and don't forget to add use NPerGroup
right under your class declaration.
现在,您想设置一个关系函数以使用特征.
Now you'd want to setup a relationship function to use the trait.
public function latestReviews()
{
return $this->hasMany(Review::class)->latest()->nPerGroup('object_id', 3);
}
现在您可以像使用其他任何关系一样使用它,它将为每个对象加载最新的3条评论.
Now you can use it just like any other relationship and it will load up the 3 latest reviews for each object.
Object::with('latestReviews')->get();
这篇关于Laravel雄辩的极限结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!