php Eloquent 集合:each 与 foreach
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18592836/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Eloquent collections: each vs foreach
提问by Niklas Modess
Might not be a question specific to Eloquent collections, but it just hit me while working with them. Let's just assume we have a $collection
object which is an instance of Illuminate\Support\Collection
.
可能不是 Eloquent 集合特有的问题,但在使用它们时它只是让我感到震惊。让我们假设我们有一个$collection
对象,它是 的实例Illuminate\Support\Collection
。
Now if we want to iterate over it, what are the pros and cons of using each()
with a closure vs a regular foreach
. Is there any?
现在,如果我们想迭代它,使用each()
闭包与常规foreach
. 有没有?
foreach ($collection as $item) {
// Some code
}
--- VS ---
$collection->each(function ($item) {
// Some code
});
回答by searsaw
A foreach
statement should be used as a sort of a way to cycle through a collection and perform some sort of logic on it. If what is in it effects other things in the program, then use this loop.
一个foreach
声明应作为一种通过收集的方式来循环并在其上执行某种逻辑的。如果其中的内容影响程序中的其他内容,则使用此循环。
The .each
method uses array_map
to cycle through each of the objects in the collection and perform a closure on each one. It then returns the resulting array. That is the key! .each
should be used if you want to change the collection in some way. Maybe it's an array of cars and you want to make the model upper case or lower case. You would just pass a closure to the .each
method that takes the object and calls strtoupper()
on the model of each Car object. It then returns the collection with the changes that have been made.
该.each
方法用于array_map
循环遍历集合中的每个对象并对每个对象执行闭包。然后它返回结果数组。这就是关键!.each
如果您想以某种方式更改集合,则应该使用它。也许它是一系列汽车,而您想要使模型大写或小写。您只需将闭包传递给.each
接受对象并调用strtoupper()
每个 Car 对象模型的方法。然后它返回带有所做更改的集合。
Morale of the story is this: use the .each
method to change each item in the array in some way; use the foreach
loop to use each object to affect some other part of the program (using some logic statement).
故事的精神是这样的:使用.each
方法以某种方式改变数组中的每个项目;使用foreach
循环来使用每个对象来影响程序的其他部分(使用一些逻辑语句)。
UPDATE (June 7, 2015)
更新(2015 年 6 月 7 日)
As stated so Eloquently (see what I did there?) below, the above answer is slightly off. The .each
method using array_map
never actually used the output from the array_map
call. So, the new array created by array_map
would not be saved on the Collection
. To change it, you're better off using the .map
method, which also exists on a Collection
object.
正如下面所说的那样雄辩地(看看我在那里做了什么?),上面的答案有点偏离。.each
使用的方法array_map
从未实际使用过array_map
调用的输出。因此,由创建的新数组array_map
不会保存在Collection
. 要更改它,最好使用.map
方法,该方法也存在于Collection
对象上。
Using a foreach
statement to iterate over each of them makes a bit more sense because you won't be able to access variables outside the Closure unless you make sure to use a use
statement, which seems awkward to me.
使用foreach
语句来迭代它们中的每一个更有意义,因为除非您确保使用use
语句,否则您将无法访问闭包之外的变量,这对我来说似乎很尴尬。
The implementation when the above answer was originally written can be found here.
可以在此处找到最初编写上述答案时的实现。
.each
in Laravel 5.1
.each
在 Laravel 5.1
The new .each
that they are talking about below no longer uses array_map
. It simply iterates through each item in the collection and calls the passed in $callback
, passing it the item and its key in the array. Functionally, it seems to work the same. I believe using a foreach
loop would make more sense when reading the code. However, I see the benefits of using .each
because it allows you to chain methods together if that tickles your fancy. It also allows you to return false from the callback to leave the loop early if your business logic demands you to be able to.
.each
他们在下面谈论的新的不再使用array_map
。它只是遍历集合中的每个项目并调用传入的$callback
,将项目及其在数组中的键传递给它。在功能上,它似乎工作相同。我相信foreach
在阅读代码时使用循环会更有意义。但是,我看到了使用的好处,.each
因为它允许您将方法链接在一起,如果您喜欢的话。如果您的业务逻辑要求您能够这样做,它还允许您从回调中返回 false 以提前离开循环。
For more info on the new implementation, check out the source code.
有关新实现的更多信息,请查看源代码。
回答by orrd
There is a lot of confusing misinformation in the existing answers.
现有答案中有很多令人困惑的错误信息。
The Short Answer
简短的回答
The short answer is: There is no major difference between using .each()
vs. foreach
to iterate over a Laravel collection.Both techniques achieve the same result.
简短的回答是:使用.each()
与foreach
迭代 Laravel 集合之间没有重大区别。这两种技术都达到了相同的结果。
What about modifying items?
修改物品呢?
Whether or not you're modifying items is irrelevant to whether you use .each()
vs. foreach
. They both do (and don't!) allow you to modify items in the collection depending on what type of items we're talking about.
您是否正在修改项目与您是否使用.each()
vs. foreach
. 它们都允许(也不允许!)允许您根据我们正在讨论的项目类型修改集合中的项目。
- Modifying items if the Collection contains objects: If the Collection is a set of PHP objects (such as an Eloquent Collection), either
.each()
orforeach
allow you to modify properties of the objects (such as$item->name = 'foo'
). That's simply because of how PHP objects always act like references. If you're trying to replace the entire object with a different object (a less common scenario), use.map()
instead. - Modifying items if the Collection contains non-objects: This is less common, but if your Collection contains non-objects, such as strings,
.each()
doesn't give you a way to modify the values of the collection items. (The return value of the closure is ignored.) Use.map()
instead.
- 修改项目如果集合包含对象:如果集合是一组PHP对象(如雄辩的集合),要么
.each()
或foreach
让你修改的对象(如性能$item->name = 'foo'
)。这仅仅是因为 PHP 对象总是像引用一样工作。如果您尝试用不同的对象替换整个对象(不太常见的情况),请.map()
改用。 - 如果集合包含非对象,则修改项目:这不太常见,但如果您的集合包含非对象(例如字符串),
.each()
则无法修改集合项目的值。(闭包的返回值被忽略。).map()
改用。
So... which one should I use?
那么……我应该使用哪一种?
In case you're wondering about performance, I did several tests with large collections of both Eloquent items and a collection of strings. In both cases, using foreach
was faster than .each()
. But we're talking about microseconds. In most real-life scenarios the speed difference wouldn't be significant compared to the time it takes to access the database, etc.
如果您想了解性能,我对 Eloquent 项目和字符串集合的大型集合进行了几次测试。在这两种情况下,使用foreach
都比.each()
. 但我们谈论的是微秒。在大多数实际场景中,与访问数据库等所需的时间相比,速度差异不会很大。
It mostly comes down to your personal preference. Using .each()
is nice because you can chain several operations together (for example .where(...).each(...)
). I tend to use both in my own code just depending on what seems the cleanest for each situation.
这主要取决于您的个人喜好。使用.each()
很好,因为您可以将多个操作链接在一起(例如.where(...).each(...)
)。我倾向于在我自己的代码中使用这两种方法,这取决于每种情况下哪种看起来最干净。
回答by Jake S
Contrary to what the two other answers say, Collection::each()
does notchange the values of the items in the Collection, technically speaking. It does use array_map()
, but it doesn't store the result of that call.
相反,其他两个答案说什么,Collection::each()
也不会更改收藏的物品的价值,从技术上讲。它确实使用array_map()
,但它不存储该调用的结果。
If you want to modify each item in a collection (such as to cast them to objects as Damon in a comment to the crrently accepted answer), then you should use Collection::map()
. This will create a new Collection based on the result of the underlying call to array_map()
.
如果您想修改集合中的每个项目(例如在对最新接受的答案的评论中将它们转换为 Damon 的对象),那么您应该使用Collection::map()
. 这将根据底层调用的结果创建一个新的集合array_map()
。
回答by Nik K
It is more beneficial to use the latter: each().
使用后者更有利:each()。
You can chain conditions and write clearer more expressive code, eg:
您可以链接条件并编写更清晰、更具表现力的代码,例如:
$example->each()->map()->filter();
$example->each()->map()->filter();
This takes you closer to Declarative Programming where you tell the computer what to accomplish instead of how to accomplish.
这让你更接近于声明式编程,在那里你告诉计算机要完成什么而不是如何完成。
Some useful articles:
一些有用的文章:
https://martinfowler.com/articles/collection-pipeline/
https://martinfowler.com/articles/collection-pipeline/
回答by Shannon
The foreach() construct does not allow you to change the value of the array item being iterated over, unless you pass the array by reference.
foreach() 构造不允许您更改正在迭代的数组项的值,除非您通过引用传递数组。
foreach ($array as &$value) $value *= $value;
The each() eloquent method wraps the PHP array_map() function, which allows this.
each() eloquent 方法包装了 PHP array_map() 函数,它允许这样做。
Like the previous answer states, you should use foreach() if you have any other motivation. This is because the performance of foreach() is much better than array_map().
就像之前的答案一样,如果您有任何其他动机,应该使用 foreach()。这是因为 foreach() 的性能比 array_map() 好很多。
http://willem.stuursma.name/2010/11/22/a-detailed-look-into-array_map-and-foreach/
http://willem.stuursma.name/2010/11/22/a-detailed-look-into-array_map-and-foreach/