强制以特定的数组ID顺序在Eloquent

时间:2019-06-19 10:51:01

标签: laravel eloquent

我正在使用Laravel(因此雄辩)。

我雄辩地非常复杂,多联合,多表联接查找。它需要通过多个表/子联接进行特定的排序。这意味着即使有说服力的方面,也不适合使用laravel的ORM部分。

我已经成功实现了该查询,并且正在返回一组ID。正如我提到的那样,这些命令的顺序正确。

Laravel具有以下方法:

  • $object::find($ids)
  • $object::whereIn('id', $ids)->get()

从根本上讲,如果这些响应与以下数组一起运行,则它们是相同的:

  • [1,2,3]
  • [3,2,1]

即:他们的回答就像是按ID排序一样。

如何强制传递给我的特定命令?

我知道可以通过以下方式在MySQL中完成

  • select * from records where id in (3,4,5) order by field(id,4,5,3)

先谢谢了。

3 个答案:

答案 0 :(得分:1)

这未经测试,但是通过创建query scope来完成所有预期的工作,您应该可以完成此操作。

您可以创建一个global scope,然后将其应用于应用程序中的任何模型。

查询范围可以包含几个参数(不包括必需的$query参数):$field$values。在此示例中,您可以传递一个id字段,其值是ID数组。

然后它将执行常规的where调用,获取所有结果,然后创建一个新的结果集合,这些结果现在按指定顺序显示。

注意:通过返回集合,作用域将模拟->get()方法返回的集合。

public function getInOrder($query, $field, $values)
{
    $results = $query->whereIn($field, $values)->get();

    $reorder = collect();

    foreach ($ids as $id) {
        $reorder[] = $results->where($field, $values)->first();
    }

    return $reorder;
}

您使用以下方法调用此作用域函数:

$object::getInOrder('id', $ids);

注意:由于此操作返回一个集合,因此不再使用查询生成器方法,而仅使用该集合方法。

答案 1 :(得分:0)

您可以使用结果的集合来处理它:

https://laravel.com/docs/5.8/collections#method-sortby

答案 2 :(得分:0)

这很大程度上取决于@thisiskelvin给出的答案

请投票给他,而不是这个答案(或两者都选)

我创建了一个特征..我在AdvancedModelLookup中称其为app\Traits

在此过程中,我根据提供的代码创建了一个稍微修改的函数:

<?

namespace App\Traits;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;

trait AdvancedModelLookup
{
    /**
     * This run a query and orders the objects as per a provided array/collection.
     *
     * @param $query Builder
     * @param $field
     * @param $ids Collection|array
     *
     * @return Collection
     */
    public static function getInOrder(Builder $query, string $field, $ids): Collection
    {
        $results = $query->whereIn($field, $ids)->get();

        $reorder = collect([]);
        foreach ($ids as $id) {
            $reorder->push($results->where($field, $id)->first());
        }

        return $reorder;
    }}

现在使用此特征:

use App\Traits\AdvancedModelLookup;

class SomeObject extends Model
{

    use AdvancedModelLookup;

    //...

}

示例用法:

$order = [4,5,3];
$query = SomeObject::whereIn('id', $order);

$normal_lookup = $query->get();
$sorted_lookup = SomeObject::getInOrder($query, 'id', $order);

dd($normal_lookup, $sorted_lookup);

// Normal lookup order: 3,4,5
// Sorted lookup order: 4,5,3

请注意,您可以轻松扩展或创建此功能样式的其他版本,例如pluck()等...

此特征提供了一个快速选项,可以在每个模型的基础上将其包括在内,而不必弄乱对象的继承。