Laravel:如何将联接表加载到子数组中?

时间:2019-12-12 13:32:59

标签: php sql laravel eloquent eager-loading

我有2张桌子:

User:
id
schedule_id
name

Schedules:
id
date

我使用eager loading执行查询:

User::with (['schedules'])->get()->first();

并得到了这样的结果:

[
    'id' => '3',
    'schedule' => [
        'id' => '13',
        'date' => '20.11.2020',
    ],
    'name' => 'John',
];

但是当我使用join执行类似的查询时,

User::join ('schedules', 'user.schedule_id', '=', 'schedules.id')->get()->first();

我得到了这样的结果,合并了数组:

[
    'id' => '13',
    'date' => '20.11.2020',
    'name' => 'John',
];

如何在Eloquent中使用join来获得分离数组的结果?

注意:在原始PHP和PDO中,对于带有连接的任何查询,我总是得到分离的数组。

2 个答案:

答案 0 :(得分:1)

来自数据库查询的数据将始终格式化为平面数组,这就是数据库的工作方式。 Eloquent在幕后发挥了很多魔力,可以将正确的相关值映射到集合中的正确模型。

使用联接时,Eloquent无法知道应该将哪些数据映射到哪个关系或属性。

如果要使用联接查询,则必须为模型上的这些属性使用别名。或者,您可以在使用数据之前按照所需方式手动映射属性。

答案 1 :(得分:0)

好吧,我可以建议一种更合适的方法,以按Laravel的Eloquent中的关系列对结果进行排序。

您应该使用2个查询。

首先,仅获取ID,但按任何关系的列排序。 (您无法使用急切的加载按关系的列对结果进行排序)

$idsRaw = User::join ('schedules', 'user.schedule_id', '=', 'schedules.id')
    ->select ('users.id')
    ->orderBy ('schedules.date')
    ->get ()->toArray ();
$ids = \array_column ($idsRaw, 'id');

通过热切加载,使用子数组获得良好的关系结果:

User::with (['schedules'])
    ->whereIn ('user.id', \implode (',', $ids))
    ->orderByRaw('FIELD(' . $ids . ',' . \implode(',', $ids) . ')')
    ->get()->toArray ();

优势:

您不需要手动将列和别名映射到子数组中(如果您有很多关系,可能会非常困难)。

缺点:

此方法的运行速度与您拥有的ID一样慢。

是的,如果查询中有数千个id,则应对所有关系使用一个带有联接的复杂查询,并手动将别名映射到子数组中以获得最佳性能。