Laravel嵌套渴望加载特定列

时间:2019-11-23 14:30:19

标签: php laravel eager-loading

我正在处理嵌套的紧急加载,有没有一种方法可以从account.user.location的中间关系中挑选出某些列?

用户模型

 public function account(): HasMany
    {
        return $this->hasMany(Account::class);
    }

 public function location(): BelongsTo
    {
        return $this->belongsTo(Location::class);
    }

帐户模型

 public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

位置模型

 public function user(): HasMany
{
    return $this->hasMany(User::class);
}

有效的控制器方法

此方法返回嵌套关系,但我希望从用户关系中获取某些列,而不是全部列出。

    public function show(string $id)
{
    $film = Film::with([
        'account.user.location'
    ])->findOrFail($id);
}

无效的控制器方法

这是我的示例代码,我试图从用户中选择name列,然后显示位置关系。

    public function show(string $id)
{
    $film = Film::with([
        'account.user:id,name',
        'account.user.location:id',city
    ])->findOrFail($id);
}

回复

这是从不起作用的方法返回的响应,返回的位置为null

 +"account": {#2061
  +"id": "191067a6-4c38-423d-a972-bb3a842ca89e"
  +"user": {#2064
    +"id": "d9f381c1-3899-367c-8d60-6d2bc3db6d23"
    +"name": "Domenick"
    +"location": null

我不确定如何从中间关系中选择特定的列,然后再加入该位置。我可以在哪里出问题时得到一些帮助吗?

2 个答案:

答案 0 :(得分:0)

更新您的用户模型

public function account()
    {
        return $this->hasMany(Account::class, 'user_id');
    }

 public function location()
    {
        return $this->belongsTo(Location::class);
    }

将您的帐户类别更新为

public function user()
{
    return $this->belongsTo(User::class, 'user_id');
}

在您的控制器方法中尝试此

public function show($id)
{
    $film = Film::where('id', $id)
    ->with([
        'account.user:id,name',
        'account.user.location:id',city
    ])->get();
}

答案 1 :(得分:0)

Laravel正在依次加载每个级别的关系。换句话说,如果您使用A::with('b.c')->get(),则Eloquent将首先加载所有A,然后加载它们引用的所有B,最后加载被引用的所有C已加载的B。 ORM使用导航属性(即外键)来执行此操作。如果在中间模型上省略这些外键,则该框架将无法再加载引用的模型。

如果手动进行操作,则将使用以下查询(使用的ID和外键为示例):

SELECT * FROM a;                         // returns As with ids 1, 2, 3
SELECT * FROM b WHERE a_id IN (1, 2, 3); // returns Bs with ids 4, 5, 6
SELECT * FROM c WHERE b_id IN (4, 5, 6);

对于您而言,使用以下代码就足够了:

public function show(string $id)
{
    $film = Film::with([
        'account.user:id,account_id,location_id,name',
        'account.user.location:id,city'
    ])->findOrFail($id);
}