雄辩的收藏:每个与foreach

时间:2013-09-03 12:52:57

标签: php laravel eloquent

可能不是特定于Eloquent系列的问题,但它只是在与他们合作时打击了我。我们假设我们有一个$collection对象,它是Illuminate\Support\Collection的一个实例。

现在,如果我们想要迭代它,那么使用each()和闭包与常规foreach的利弊是什么。有没有?

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

--- VS ---

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

5 个答案:

答案 0 :(得分:49)

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

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

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

更新(2015年6月7日)

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

使用Collection语句迭代每个语句会更有意义,因为除非确保使用foreach语句,否则无法访问Closure外的变量对我来说似乎很尴尬。

最初编写上述答案时的实施可以是found here

Laravel 5.1中的

use

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

有关新实施的更多信息,请查看the source code

答案 1 :(得分:13)

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

简答

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

修改项目怎么样?

您是否正在修改项目与您是否使用.each()foreach无关。他们都(并且不会!)允许您根据我们所谈论的项目类型修改集合中的项目。

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

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

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

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

答案 2 :(得分:3)

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

如果你想修改一个集合中的每个项目(比如将它们作为Damon投射到对象中的一个评论中,那么你应该使用array_map()。这将根据对Collection::map()的基础调用的结果创建一个新的集合。

答案 3 :(得分:0)

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

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

$示例 - >将() - >地图() - >过滤器();

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

一些有用的文章:

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

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

答案 4 :(得分:-2)

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

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

each()eloquent方法包装PHP array_map()函数,允许这样做。

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

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