web-dev-qa-db-fra.com

Collections éloquentes: chacun vs foreach

Ce n'est peut-être pas une question spécifique aux collections Eloquent, mais cela m’a frappé tout en travaillant avec elles. Supposons simplement que nous avons un objet $collection qui est une instance de Illuminate\Support\Collection

Maintenant, si nous voulons parcourir le sujet, quels sont les avantages et les inconvénients d’utiliser each() avec une fermeture par rapport à un foreach régulier. Y a-t-il?

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

--- VS ---

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

Une instruction foreach doit être utilisée comme une sorte de moyen de parcourir une collection et d’exécuter une sorte de logique dessus. Si son contenu affecte d'autres éléments du programme, utilisez cette boucle. 

La méthode .each utilise array_map pour parcourir chacun des objets de la collection et effectuer une fermeture sur chacun d'eux. Il retourne ensuite le tableau résultant. C'est la clé! .each doit être utilisé si vous souhaitez modifier la collection d’une manière ou d’une autre. Peut-être que c'est un éventail de voitures et que vous voulez faire le modèle majuscule ou minuscule. Vous ne feriez que passer une fermeture à la méthode .each qui prend l'objet et appelle strtoupper() sur le modèle de chaque objet Car. Il retourne ensuite la collection avec les modifications apportées. 

Le moral de l'histoire est le suivant: utilisez la méthode .each pour modifier chaque élément du tableau d'une manière ou d'une autre; utilisez la boucle foreach pour utiliser chaque objet afin d'affecter une autre partie du programme (à l'aide d'une instruction logique).

MISE À JOUR (7 juin 2015)

Comme indiqué de manière éloquente (voir ce que j'ai fait ici?) Ci-dessous, la réponse ci-dessus est légèrement erronée. La méthode .each utilisant array_map n'a jamais réellement utilisé la sortie de l'appel array_map. Ainsi, le nouveau tableau créé par array_map ne sera pas enregistré sur la Collection. Pour le changer, il vaut mieux utiliser la méthode .map, qui existe également sur un objet Collection.

Utiliser une instruction foreach pour parcourir chacune d'elles est un peu plus logique car vous ne pourrez pas accéder à des variables en dehors de la fermeture à moins de vous assurer d'utiliser une instruction use, ce qui me semble difficile.

L'implémentation lorsque la réponse ci-dessus a été écrite à l'origine peut être trouvée ici .

.each dans Laravel 5.1

Le nouveau .each dont il est question ci-dessous n’utilise plus array_map. Il itère simplement à travers chaque élément de la collection et appelle le passé dans $callback, en lui passant l'élément et sa clé dans le tableau. Fonctionnellement, cela semble fonctionner de la même manière. Je pense qu’utiliser une boucle foreach donnerait plus de sens à la lecture du code. Cependant, je vois les avantages de l’utilisation de .each car il vous permet d’enchaîner des méthodes si cela chatouille votre fantaisie. Il vous permet également de renvoyer faux à partir du rappel afin de quitter la boucle plus tôt si votre logique d’entreprise vous le demande.

Pour plus d'informations sur la nouvelle implémentation, consultez le code source .

48
searsaw

Il y a beaucoup de désinformation déroutante dans les réponses existantes.

La réponse courte

La réponse courte est la suivante: Il n'y a pas de différence majeure entre l'utilisation de .each() et foreach pour parcourir une collection de Laravel. Les deux techniques donnent le même résultat.

Qu'en est-il de modifier des éléments?

Que vous modifiiez ou non des éléments n'a pas d'importance si vous utilisez .each() contre foreach. Ils permettent (et non!) De modifier les éléments de la collection en fonction du type d’éléments dont nous parlons.

  • Modification d'éléments si la collection contient des objets : si la collection est un ensemble d'objets PHP (tels qu'une collection Eloquent), soit .each() ou foreach vous permet de modifier les propriétés des objets (tels que $item->name = 'foo') . C'est simplement à cause de la façon dont les objets PHP agissent toujours comme des références. Si vous essayez de remplacer l'objet entier par un objet différent (un scénario moins courant), utilisez plutôt .map().
  • Modification des éléments si la collection contient des non-objets : Cela est moins courant, mais si votre collection contient des non-objets, tels que des chaînes, .each() ne vous permet pas de modifier les valeurs des éléments de la collection. (La valeur de retour de la fermeture est ignorée.) Utilisez plutôt .map().

Alors ... lequel devrais-je utiliser?

Au cas où vous vous interrogeriez sur les performances, j'ai fait plusieurs tests avec de grandes collections d'éléments Eloquent et une collection de chaînes. Dans les deux cas, utiliser foreach était plus rapide que .each(). Mais nous parlons de microsecondes. Dans la plupart des scénarios réels, la différence de vitesse ne serait pas significative par rapport au temps nécessaire pour accéder à la base de données, etc.

Cela dépend principalement de vos préférences personnelles. Utiliser .each() est agréable car vous pouvez chaîner plusieurs opérations ensemble (par exemple .where(...).each(...)). J'ai tendance à utiliser les deux dans mon propre code, en fonction de ce qui semble le plus propre pour chaque situation.

13
orrd

Contrairement à ce que disent les deux autres réponses, Collection::each() ne modifie pas pas techniquement les valeurs des éléments de la collection. Il utilise array_map(), mais il ne stocke pas le résultat de cet appel.

Si vous souhaitez modifier chaque élément d'une collection (pour les attribuer à des objets tels que Damon dans un commentaire sur la réponse réellement acceptée), utilisez Collection::map(). Cela créera une nouvelle collection en fonction du résultat de l'appel sous-jacent à array_map().

3
Jake S

Il est plus avantageux d’utiliser ce dernier: each ().

Vous pouvez chaîner des conditions et écrire un code plus clair et plus expressif, par exemple:

$ exemple-> chaque () -> map () -> filter ();

Cela vous rapproche de la programmation déclarative, dans laquelle vous indiquez à l'ordinateur ce qu'il doit accomplir plutôt que comment.

Quelques articles utiles:

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

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

0
Nik K