【问题标题】:How to sort by eager loading results in Laravel?如何在 Laravel 中按预先加载的结果排序?
【发布时间】:2018-03-29 18:08:30
【问题描述】:

我对急切加载非常陌生,并且遇到了我认为只是我不理解它的简单问题。我查看了一些 the materials here 并环顾四周,但似乎无法为我的要求找到正确的术语。

目前在我的设备模型中我有以下关系:

public function registrationsExpireLatest()
{
       return $this->hasOne(EquipmentLicense::class,'equipmentID','id')
    ->orderByDesc('expirationDate');
}

这很好用,但是如果我想把它放在@foreach 下的索引刀片上,我会得到我需要的一切,包括使用下面的代码的到期日期:

        @foreach ($equipments as $equipment)

             <tr>
                 <td><a href="/origins/{{$equipment['id']}}">{{$equipment['unit_id']}}</a></td>
                 <td>{{\Crypt::decryptString($equipment->licensePlate)}}</td>
                 <td>@if (count($equipment->registrationsExpireLatest))
                     {{$equipment->registrationsExpireLatest->expirationDate}}
                    @endif</td>
            </tr>

        @endforeach

来自此控制器代码:

    $equipments = Equipment::with(['registrationsExpireLatest' => function ($query) {
                                    $query->orderBy('expirationDate', 'asc');
                                }])
                                ->where([
                                    ['unit_type','<',3],
                                    ['active','=',1]
                                    ])
                                ->limit(10)
                                ->get();

所有的输出都是这样的:

11      086-YRR     2015-05-31
26      062-XWE     2018-11-30
33      880-HNV     2018-04-30
39      820-YYT     2018-01-31
203     279-WWU     2013-12-31
31      BMR 199     2018-04-30
UNK3    997-WLH     2011-09-30
1       957-VDN     2018-05-31
1096    187-MFF     2015-01-31
2105    154-CLU     2018-01-31 

正如您在我的控制器中看到的那样,我已经尝试按照我认为正确的方式进行排序:https://laravel.com/docs/5.3/eloquent-relationships#constraining-eager-loads

但正如您从我的结果表中看到的那样,根据到期日期,它们是乱序的。

我希望它按日期提前(如 2011 年)到晚些时候(如 2018 年)。有没有办法做到这一点?

【问题讨论】:

  • 这是另一回事。如果你搜索“laravel orderby on relationship”,你会找到你的解决方案。
  • @Spacemudd - 你有例子吗?我查看了一些,他们似乎都希望我使用 join,但我不确定如何将其限制为一个设备项目(实际上数据库中可能有几十个 EquipmentLicense。如果我按照他们建议的方式进行,现在出现了多条设备记录(比如上表中的 11 条,由于关系,只有 1 条(最新),但现在有 9 条,包括最新的和所有较早的注册。

标签: php laravel laravel-5 eloquent laravel-eloquent


【解决方案1】:

您当前所做的是对相关集合进行排序,即如果registrationsExpireLatest 是一对多关系,则相关模型将按其expirationDate 为您的每个Equipments 升序排序.据我从您的模型中可以看出,您已经加入了最新的实体。

在关系上对Equipments 进行排序通常并不难,您只需加入相关表即可。但是在您的情况下,如果每个Equipment 在相关表中有多个元素,则连接会更复杂一些。我认为类似以下的方法可以工作:

Equipment::where([
        ['unit_type','<',3],
        ['active','=',1]
    ])
    ->join(DB::raw('(SELECT equipmentID, MAX(expirationDate) AS latest FROM equipment_license GROUP BY equipmentID) AS tmp'), 'equipment.id', '=', 'tmp.equipmentID')
    ->orderBy('tmp.latest')
    ->select('equipment.*', 'tmp.latest')
    ->limit(10)
    ->get();

【讨论】:

  • 我提出了你的建议,但我遇到了这个问题: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“SELECT deviceID, MAX(expirationDate) AS latest FROM equipment_licenses GROUP”附近使用正确的语法(SQL:select * from equipment inner join SELECT equipmentID, MAX( expireDate) AS latest FROM equipment_licenses GROUP BY equipmentID on equipment.id = equipment_licenses.equipmentID where (unit_type active = 1)
  • equipment_licenses.latest asc limit 10 排序
  • 我不确定equipment_license 表名,因为在您的问题中提到了模型 - 这是正确的吗?你检查了吗?
  • 我做了一些更改(都必须更改为设备许可证,而不是单数。但是当我通过 mysql 运行它时,一切都很好,直到我到达 orderBy 部分并显示列未知:' device_license.latest'
  • 试试不带equipment_licenses.ORDER BY latest。另一种解决方案是围绕它进行包装 SELECT 查询,但我怀疑这是必要的......
【解决方案2】:

(基于Namoshek's answer

JOIN 需要别名:

Equipment::where([
        ['unit_type','<',3],
        ['active','=',1]
    ])
    ->join(DB::raw('(SELECT equipmentID, MAX(expirationDate) AS latest FROM equipment_license GROUP BY equipmentID) as license'), 'equipment.id', '=', 'license.equipmentID')
    ->orderBy('license.latest')
    ->limit(10)
    ->get();

【讨论】:

  • 到此为止,我想我会非常感谢你。非常感谢您的所有帮助!我非常感激!
猜你喜欢
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 2018-02-10
  • 1970-01-01
  • 2015-07-11
  • 2019-06-17
  • 2015-05-30
  • 1970-01-01
相关资源
最近更新 更多