Where should the .all() be placed in Craft 3 I'm confused, I have ended up with 2 similar queries in a template after converting them from Craft 2.

{% set events = craft.entries()
    .section('events')
    .eventDate('&gt;' ~ now|date('Y-m-d H:i:s'))
    .limit(3)
    .orderby('eventDate')
    .all()
%}
{% for entry in events %}
...
{% endfor %}


and

{% set entries = craft.entries()
    .section('news')
    .orderBy('postDate desc')
    .limit('4')
    .with(['imageGallery'])
%}
{% for entry in entries.all() %}
...
{% endfor %}


Both work without any errors reported but which one is better or correct?
Both approaches are valid. In your first example, you could have moved .all() into the for-loop; and in the second example, you could have moved .all() out of the for-loop, and into the {% set entries = ... %} statement.

Until you call .all(), you are working with an entry query, and after you call .all(), you’re working with an array of the actual entries (the query results).

So which approach is better depends on what else you’re doing in your template.

For example, if you need to output the total number of entries, you could do this:



{% set entryQuery = craft.entries()
    .section('news')
%}

{% for entry in entryQuery.all() %}
    ...
{% endfor %}

Total: {{ entryQuery.count() }}


But it would result in two database queries getting executed – once to get the entries for the for-loop, and a second query to get the total matching entries.

If you know you’re going to need that info, then it would be better to just fetch the entries ahead of time, and check the length of the array instead:

{% set entries = craft.entries()
    .section('news')
    .all()
%}

{% for entry in entries %}
    ...
{% endfor %}

Total: {{ entries|length }}


Regardless of the approach you decide to go with, you might want to make sure you are using semantec variable names. In your two examples you have events (an array of actual event entries) and entries (an entry query).

I would say that if you are not going to call .all() when defining your entries variable, then you might want to rename that to either entryQuery or query, just so it’s easier to remember what sort of variable you’re working with later on in the template.

{% set entryQuery = craft.entries()
    .section('news')
    .orderBy('postDate desc')
    .limit('4')
    .with(['imageGallery'])
%}

{% for entry in entryQuery.all() %}
    ...
{% endfor %}