61

可能不是 Eloquent 系列特有的问题,但它只是在使用它们时突然袭击了我。让我们假设我们有一个$collection对象,它是Illuminate\Support\Collection.

现在,如果我们想对其进行迭代,使用each()闭包与常规foreach. 有吗?

foreach ($collection as $item) {
    // Some code
}

相对

$collection->each(function ($item) {
    // Some code
});
4

6 回答 6

60

语句应该用作一种foreach循环遍历集合并对其执行某种逻辑的方式。如果其中的内容影响程序中的其他内容,则使用此循环。

.each方法用于array_map循环遍历集合中的每个对象并对每个对象执行闭包。然后它返回结果数组。那是关键!.each如果您想以某种方式更改集合,则应使用。也许这是一系列汽车,您想让模型大写或小写。您只需将闭包传递给.each获取对象并调用strtoupper()每个 Car 对象的模型的方法。然后,它返回包含所做更改的集合。

故事的精神是这样的:使用.each方法以某种方式改变数组中的每一项;使用foreach循环来使用每个对象来影响程序的其他部分(使用一些逻辑语句)。

更新(2015 年 6 月 7 日)

正如下面所说的雄辩(看看我在那里做了什么?),上面的答案有点偏离。使用的.each方法array_map从未实际使用过array_map调用的输出。因此,由创建的新数组array_map不会保存在Collection. 要更改它,您最好使用该.map方法,该方法也存在于Collection对象上。

使用foreach语句对它们中的每一个进行迭代更有意义,因为除非您确保使用语句,否则您将无法访问闭包之外的变量use,这对我来说似乎很尴尬。

可以在此处找到最初编写上述答案时的实现。

.each在 Laravel 5.1 中

他们下面说的新.each的不再使用array_map。它只是遍历集合中的每个项目并调用传入的$callback,将项目及其在数组中的键传递给它。从功能上讲,它似乎工作相同。我相信在阅读代码时使用foreach循环会更有意义。但是,我看到了使用的好处,.each因为它允许您将方法链接在一起,如果您喜欢的话。如果您的业务逻辑要求您能够这样做,它还允许您从回调中返回 false 以尽早离开循环。

有关新实现的更多信息,请查看源代码

于 2013-09-03T16:26:30.883 回答
19

现有答案中有很多令人困惑的错误信息。

简短的回答

简短的回答是:使用迭代 Laravel 集合之间没有重大区别。.each()foreach 两种技术都达到了相同的结果。

修改物品呢?

您是否正在修改项目与您是否使用.each()vs.无关foreach。它们都允许(也不允许!)根据我们所讨论的项目类型来修改集合中的项目。

  • 如果 Collection 包含对象,则修改项目:如果 Collection 是一组 PHP 对象(例如 Eloquent 集合),.each()foreach允许您修改对象的属性(例如$item->name = 'foo')。这仅仅是因为 PHP 对象总是像引用一样工作。如果您尝试用不同的对象替换整个对象(不太常见的情况),请.map()改用。
  • 如果 Collection 包含非对象,则修改项目:这种情况不太常见,但如果您的 Collection 包含非对象(例如字符串),.each()则无法修改集合项目的值。(闭包的返回值被忽略。).map()改为使用。

那么......我应该使用哪一个?

如果您对性能感到疑惑,我对 Eloquent 项目和字符串集合的大型集合进行了几次测试。在这两种情况下,使用foreach都比.each(). 但我们谈论的是微秒。在大多数现实生活场景中,与访问数据库等所需的时间相比,速度差异并不显着。

这主要取决于您的个人喜好。使用.each()很好,因为您可以将多个操作链接在一起(例如.where(...).each(...))。我倾向于在我自己的代码中使用这两种方法,这取决于每种情况下看起来最干净的情况。

于 2015-06-06T19:15:23.087 回答
4

与其他两个答案所说的相反,从技术上讲,不会Collection::each()改变集合中项目的值。它确实使用,但它不存储该调用的结果。array_map()

如果您想修改集合中的每个项目(例如在对当前接受的答案的评论中将它们作为 Damon 转换为对象),那么您应该使用Collection::map(). 这将基于对array_map().

于 2015-05-27T13:43:17.890 回答
1

使用后者更有利:each().

您可以链接条件并编写更清晰更具表现力的代码,例如:

$example->each()->map()->filter();

这使您更接近声明式编程,您可以在其中告诉计算机要完成什么而不是如何完成。

一些有用的文章:

https://martinfowler.com/articles/collection-pipeline/

https://adamwathan.me/refactoring-to-collections/

于 2017-08-27T06:39:04.630 回答
0

->each()相同foreach(...) 更糟。_

这里的主要区别是变量范围。在经典 foreach中,您可以轻松地操作在foreach. 如果您正在处理闭包,则需要从父范围继承变量use此功能令人困惑,因为当您使用它时,您的功能变得依赖于范围......

您可以->each()与其他函数链接,但由于它不会更改集合中的值,因此它的用例非常有限。而且由于它“很少使用”,因此开发人员在阅读您的代码时并不总是很容易识别它。

没有多少人会读你的代码,珍惜那些会读的人。

于 2021-10-01T05:38:41.793 回答
-3

foreach() 构造不允许您更改被迭代的数组项的值,除非您通过引用传递数组。

foreach ($array as &$value) $value *= $value;

each() 雄辩的方法包装了 PHP array_map() 函数,它允许这样做。

与前面的答案一样,如果您有任何其他动机,则应该使用 foreach()。这是因为 foreach() 的性能比 array_map() 好得多。

http://willem.stuursma.name/2010/11/22/a-detailed-look-into-array_map-and-foreach/

于 2015-03-24T15:51:54.037 回答