5

I am brand new to Craft so excuse me if the question seems a little simple. Is this the best way to return the contents of a 'singles' section. Does everything end up in a for loop even if you are only returning a single entry.

{% for entry in craft.entries.section('sectionHandle').limit(1).find() %}
  {{ entry.title }}
{% endfor %}

Also I am curious if 'entry' in the for loop actually means anything or is just a good symantic name to use for example could you say

{% for oranges in ...%}{% oranges.title %}{% endfor %}
5

It's not a simple question, but a fundamental one.

Whenever you query one of Craft's Element API services (such as craft.entries, craft.assets and craft.categories) or a relational field (such as an Entries or Assets field, i.e. entry.myAssetsField) you'll get back an ElementCriteriaModel instance.

The ElementCriteriaModel is basically a fancy wrapper for your query, which you can call methods on (such as .find(), .ids(), .first() and .last()), in order to actually pull elements based on your criteria (e.g. .section('sectionHandle')). Some methods – such as .find() – will return an array of elements (Craft actually calls .find() implicitly unless you use one of the other methods), while others will return a single element (.first(), .last()). There are also methods that can do different things entirely, such as returning an array of matching element IDs (.ids()).

In your example, you're using .find() – which means Craft will return an array of elements (even if there's only one). In such cases, it usually makes more sense to use .first(), to make Craft return a single element and avoid the for loop:

{% set entry = craft.entries.section('sectionHandle').first() %}

However, since the query may not always return any matching elements, it's usually a good idea to wrap the result in a conditional:

{% set entry = craft.entries.section('sectionHandle').first() %}
{% if entry %}
    ...
{% endif %}

The above will of course also be true for any relational fields – consider an Assets field for a "featured image"; even if you limit the field to a single image, simply accessing the field in a template will always return an ElementCriteriaModel, unless you use .first():

{# Returns an ElementCriteriaModel #}
{% set featuredImage = entry.someAssetsField %}

{# Returns an array of elements #}
{% set featuredImage = entry.someAssetsField.find() %}

{# Returns a single Asset #}
{% set featuredImage = entry.someAssetsField.first() %}

Also I am curious if 'entry' in the for loop actually means anything or is just a good symantic name to use

It's just a semantic name – the result variable for your query can be named whatever you want:

{% set myAwesomeSingleEntry = craft.entries.section('sectionHandle').first() %}

However, a good thing to know about is that whenever Craft matches the current URL request to an element – e.g. your Single entry – it'll automatically populate your template with an entry variable. In other words, if the current page is the actual URL for your Single entry, you won't need to do any craft.entries query at all (this is true for all Entries and Categories that have URLs enabled).

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.