Collections

Collections (opens new window) come from the Laravel (opens new window) ecosystem, and provide a fluid way of working with array-like data.

You can create a Collection anywhere:

{% set list = collect(['Green', 'Teal', 'Blue']) %}

Collections can be used in most situations that an array would be:

<ul>
  {% for color in colors %}
    {# `color` is one of our original three strings: #}
    <li>{{ color }}</li>
  {% endfor %}
</ul>

# Methods

Dozens of convenience methods (opens new window) are available on every collection to simplify cumbersome or error-prone operations.

These methods can be chained together to process data in an elegant way. Take this average review score logic:

{% set recentReviews = craft.entries()
  .section('reviews')
  .relatedTo({
    targetElement: product,
  })
  .postDate(">= #{now|date_modify('-1 month')}")
  .collect() %}

{{ recentReviews.pluck('rating').average() }}

Not all Collection methods return another Collection! In this example, .pluck() (opens new window) does (containing just the rating field values), but .average() (opens new window) doesn’t (instead returning a float (opens new window)). As Collections are intended for working with lists, methods that return scalar values can only be used at the “end” of a chain.

Some common array-manipulation features are already implemented in Craft as Twig filters or functions, but equivalent methods are usually available via Collections. Their supported arguments and signatures may differ slightly, so consult the documentation if you are combining or switching between features.

One common problem, however, is that Twig’s default configuration does not parse anonymous functions or “closures” in every expression context. The nystudio107/craft-closure package (opens new window) provides a shim to work around this limitation.

# Element Queries

Use the .collect() query execution method (in place of .all()) to return elements as a craft\elements\ElementCollection (opens new window). You can also wrap an existing list of elements in a regular Collection with the same collect() function we used, earlier:

{# These produce similar results: #}
{% set posts = craft.entries().section('news').collect() %}
{% set posts = collect(craft.entries().section('news').all()) %}

Eager-loaded elements are also wrapped in an ElementCollection that allows them to behave a bit like an element query, so you can safely call .all() on any relational field without worrying about whether it was eager-loaded or not—or use .with() to eager-load another set of nested elements!