【问题标题】:Get properties of eager loaded objects without running queries again无需再次运行查询即可获取预先加载的对象的属性
【发布时间】:2016-01-31 11:47:31
【问题描述】:

我正在运行这个查询:

Music::where('title', $title)->with(['artists.images'])->get();

结果,我有一个音乐列表

array:4 [▼
    0 => Music {#276 ▶}
    1 => Music {#275 ▶}
    2 => Music {#274 ▶}
    3 => Music {#273 ▶}
]

每首音乐都与艺术家有关(例如由 3 位艺术家演唱的音乐)

// Music #1
...
relations: array:1 [▼
    "artists" => Collection {#269 ▼
        items: array:3 [▶]
    }
]
...

每个艺术家都与图像有关系(例如,一个艺术家有 7 个图像)

// Artist #1 of Music #1
...
relations: array:2 [▼
    "pivot" => Pivot {#329 ▶}
    "images" => Collection {#505 ▼
        items: array:7 [▶]
    }
]
...

一切正常。

但在我的视图文件中,当我这样做时(在 foreach 循环中)

@foreach($music->artists()->where('type', 'feature')->get() as $feature)
    {{ $feature->name }}
@endforeach

它再次运行许多查询来实现这一点。 $music->artists 应该已经预先加载,因此不必再次运行查询。当我在上面运行dd() 时,它实际上包含了上面提到的关系。

如何在不再次运行这些查询的情况下简单地获取属性?

【问题讨论】:

  • 您是否尝试在with 函数中添加“艺术家”,例如:->with(['artists','artists.images'])
  • 还是一样的结果。问题是当我运行dd() 时,所有想要的关系都会显示出来。这意味着它已经成功地预先加载了对象。现在我想在不再次运行 SQL 查询的情况下获取这些属性。如我所见,调用$music->artists()->where(xxx) 将再次运行查询。
  • 当我运行$music->artists 时,没有执行其他查询。但是当我运行$music->artists()->where(xxx) 时,会执行额外的查询。
  • 在使用 artists() 时创建一个新查询。另一种检查方法是在循环if($artist->type == 'feature') 中使用正常的 php/blade 条件。或者,如果可能,您可以在执行查询之前应用 where 子句(在使用 get() 之前)
  • 啊,解决办法是$artist->pivot->type

标签: php laravel


【解决方案1】:

Eager loading 关系可以这样完成

@foreach($music->with(['artists.images'] )->artists()->where('type', 'feature')->get() as $feature)
{{ $feature->name }}
@endforeach

如果这不起作用,那么用过滤器替换你的 where ..

@foreach($music->with(['artists.images'] )->artists->filter(function($it){return $it->type===' feature'} ) as $feature)
{{ $feature->name }}
@endforeach

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 2011-12-10
    • 2015-08-12
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    相关资源
    最近更新 更多