清除 Laravel 的订单

问题描述 投票:0回答:7

我有一个通用函数,它为我提供通用查询集,例如:

class Model extends Eloquent {
  public static function get_queryset(){
    $queryset = self::where('foo','=','bar');
    // Do tons of stuff with the query and then...
    return $queryset->orderBy('somefield');
  }
}

这个函数在我的项目的任何地方都使用,但在特定点上我需要使用这个查询集,但改变 ORDER BY,就像这样:

public static function get_specific_field(){
  return self::get_queryset()->select('singlefield')->orderBy('singlefield');
}

如果我运行此代码,ORDER BY 将仅附加到前一个并生成无效查询,因为“somefield”不在所选字段上。即:

SELECT singlefield FROM table ORDER BY somefield ASC, singlefield ASC

如何清除 orderBy 以便我可以重用查询集?

php laravel eloquent
7个回答
47
投票

我同意应该在查询生成器中添加一个

clearOrderBy()
方法。然而,由于 orderbys 的注册表是
Illuminate\Database\Query\Builder
上的公共财产,您今天实际上可以自行清除它。诀窍是访问基本查询对象:

$query = YourModel::where('status', 1)->orderBy('created_at','desc');
// ... lots of other code, something needs to reset the order by ...
$query->getQuery()->orders = null;
$query->orderBy('other_column', 'desc');

在其他时候,例如在操作关系查询时,您需要访问基本查询(

Illuminate\Database\Query\Query
)。例如:

$query = YourModel::find(1)->load('children', function ($query) {
    $query->getBaseQuery()->orders = null;
});

就是这样。我也计划提交

clearOrderBy()
的 PR。


12
投票

在 Laravel 7 中,现在有一种方法可以从查询生成器中删除订单(#32186):

public static function get_specific_field(){
    return self::get_queryset()->select('singlefield')->reorder('singlefield');
}

7
投票

由于这是一个相当老的问题,并且可能大多数人已经升级到 Laravel 7 及更高版本,因此您可以使用内置的

reorder()
方法,如 @halloei 提到的(#32186)。

但是,如果您无法使用 Laravel 7 版,您可以使用 PR 中的想法制作一个宏。然后你就可以像使用 Laravel 7 一样使用

reorder()
。只需在
AppServiceProvider@boot
中注册即可。

\Illuminate\Database\Query\Builder::macro('reorder', function ($column = null, $direction = 'asc') {
   $this->orders = null;
   $this->unionOrders = null;
   $this->bindings['order'] = [];
   $this->bindings['unionOrder'] = [];

   if ($column) {
      return $this->orderBy($column, $direction);
   }

   return $this;
});

2
投票

为什么不“通用”你的查询集?

class Model extends Eloquent {
  public static function get_queryset($orderBy = 'somefield'){
    $queryset = self::where('foo','=','bar');
    // Do tons of stuff with the query and then...
    return $queryset->orderBy($orderBy);
  }
}

然后就可以使用了

public static function get_specific_field(){
  return self::get_queryset('singlefield')->select('singlefield');
}

2
投票

这是一个简单的解决方案,小包,您只需调用

->clearOrdersBy()
即可使用它 https://github.com/phpfalcon/laravel-clear-orders-by


2
投票

@halloei 答案的后面可能被认为有点不清楚,您可以简单地执行以下操作,这将清除所有现有订单,同时应用新订单。

// get all users and sort by ID
$builder = User::query()->orderBy('id');

// now scrap that order and sort by email
$builder->reorder('email');

0
投票

至少从 8.0 版本开始,这已经成为 Laravel 的一部分:

https://laravel.com/docs/11.x/queries#removing-existing-orderings

// remove all existing "order by" clauses
$unorderedUsers = $query->reorder()->get();

// optionally also apply an entirely new order to the query immediately:
$usersOrderedByEmail = $query->reorder('email', 'desc')->get();
© www.soinside.com 2019 - 2024. All rights reserved.