Search code examples
phplaraveleloquentlaravel-collection

Eloquent collections: each vs foreach


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.

Now if we want to iterate over it, what are the pros and cons of using each() with a closure versus a regular foreach. Are there any?

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

versus

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

Solution

  • 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.

    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.

    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).

    UPDATE (June 7, 2015)

    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.

    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.

    The implementation when the above answer was originally written can be found here.

    .each in 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.

    For more info on the new implementation, check out the source code.