Laravel雄辩限制结果

时间:2017-02-16 19:35:06

标签: php laravel laravel-5 eloquent

我有一个有效的查询:

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);
        }])

它限制了评论总数,其中我想限制每个对象返回的评论。我怎样才能做到这一点?

2 个答案:

答案 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)

每位父母劫持1名儿童

您可以创建帮助关系来轻松处理...

Object模型中

public function approvedReview()
{
    return $this->hasOne(Review::class)->where('approved', 1);
}

然后你只使用它而不是你的其他关系。

Object::with('approvedReview')->get();


每个父母抓住n个孩子

如果你需要超过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();