[英]Laravel eloquent limit results
I have a working query: 我有一个有效的查询:
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);
}])
or 要么
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?
我该如何实现?
Eloquent way
口才
Make one relationship like below in your model class 在模型课程中建立如下所示的一种关系
public function reviews() {
return $this->hasMany( 'Reviews' );
}
//you can pass parameters to make limit dynamic
public function firstReviews() {
return $this->reviews()->limit( 3 );
}
Then call 然后打电话
Object::with('firstReviews')->get();
Faster way(if you just need one review)
更快的方式(如果您只需要进行一次审核)
Make a derived table to get the latest review 1st and then join it. 制作派生表以获取最新评论1st,然后加入。
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();
You can create a helper relation to handle this very easily... 您可以创建一个助手关系来非常轻松地处理此问题。
In your Object
model 在您的
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();
If you need more than 1, things start to become quite a bit more complex. 如果您需要的数量超过1,事情会变得越来越复杂。 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
. 我正在针对此问题改编https://softonsofa.com/tweaking-eloquent-relations-how-to-get-n-related-models-per-parent/上找到的代码,并将其用于特征而不是一个
BaseModel
。
I created a new folder app/Traits
and added a new file to this folder NPerGroup.php
我创建了一个新的文件夹
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);
}
}
In your Object
model, import the trait use App\\Traits\\NPerGroup;
在
Object
模型中, use App\\Traits\\NPerGroup;
导入特征use App\\Traits\\NPerGroup;
and don't forget to add use NPerGroup
right under your class declaration. 并且不要忘记在类声明下添加
use NPerGroup
。
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);
}
Now you can use it just like any other relationship and it will load up the 3 latest reviews for each object. 现在,您可以像使用其他任何关系一样使用它,它将为每个对象加载3条最新评论。
Object::with('latestReviews')->get();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.