Laravel如何使用Eloquent获取对象的行号?

时间:2014-05-01 12:53:30

标签: laravel laravel-4 eloquent

我想知道用户根据其创建日期的位置。我如何使用Eloquent做到这一点?

我希望能够做到这样的事情:

User::getRowNumber($user_obj);

4 个答案:

答案 0 :(得分:9)

我想你想要MySQL解决方案,所以你可以这样做:

DB::statement(DB::raw('set @row:=0'));
User::selectRaw('*, @row:=@row+1 as row')->get();
// returns all users with ordinal 'row'

所以你可以实现这样的东西:

public function scopeWithRowNumber($query, $column = 'created_at', $order = 'asc')
{
    DB::statement(DB::raw('set @row=0'));

    $sub = static::selectRaw('*, @row:=@row+1 as row')
        ->orderBy($column, $order)->toSql();

    $query->remember(1)->from(DB::raw("({$sub}) as sub"));
}

public function getRowNumber($column = 'created_at', $order = 'asc')
{
    $order = ($order == 'asc') ? 'asc' : 'desc';

    $key = "userRow.{$this->id}.{$column}.{$order}";

    if (Cache::get($key)) return Cache::get($key);

    $row = $this->withRowNumber($column, $order)
        ->where($column, '<=',$this->$column)
        ->whereId($this->id)->pluck('row');

    Cache::put($key, $row);

    return $row;
}

这需要从表中选择所有行,直到找到您要查找的行,然后仅选择该特定行号。

它可以让你这样做:

$user = User::find(15);

$user->getRowNumber(); // as default ordered by created_at ascending

$user->getRowNumber('username'); // check order for another column

$user->getRowNumber('updated_at', 'desc'); // different combination of column and order

// and utilizing the scope:
User::withRowNumber()->take(20)->get(); // returns collection with additional property 'row' for each user

由于此范围要求每次将原始语句设置@row设置为0,因此我们使用缓存1分钟以避免不必要的查询。

答案 1 :(得分:2)

$query = \DB::table(\DB::raw('Products, (SELECT @row := 0) r'));
$query = $query->select(
                            \DB::raw('@row := @row + 1 AS SrNo'),                                
                            'ProductID', 
                            'ProductName', 
                            'Description',                 
                             \DB::raw('IFNULL(ProductImage,"") AS ProductImage')
                        );

// where clauses
if(...){
    $query = $query->where('ProductID', ...));
}

// orderby clauses
// ...
// $query = $query->orderBy('..','DESC');

// count clause
$TotalRecordCount = $query->count();

$results =  $query
                ->take(...)                
                ->skip(...)
                ->get();

答案 2 :(得分:0)

我相信您可以使用Raw Expresssions来实现这一目标:

$users = DB::table('users')
         ->select(DB::raw('ROW_NUMBER() OVER(ORDER BY ID DESC) AS Row, status'))
         ->where('status', '<>', 1)
         ->groupBy('status')
         ->get();

然而,通过source code看起来在使用SQLServer和offset时可以达到相同的效果。消息来源表明,如果你喜欢以下内容:

$users = DB::table('users')->skip(10)->take(5)->get();

生成的SQL查询将包含 row_number over 语句。

答案 3 :(得分:0)

[对于Postgres]

  • 在您的模型中

    public function scopeWithRowNumber($query, $column = 'id', $order = 'asc'){ $sub = static::selectRaw('*, row_number() OVER () as row_number') ->orderBy($column, $order) ->toSql(); $query->from(DB::raw("({$sub}) as sub")); }

  • 在您的控制器中

    $user = User::withRowNumber()->get();