We use cookies to make your viewing experience better. By accepting you consent, you agree to our Cookie policy

Accept
Improve your Craft CMS skills

Understanding Entry Loops In Craft CMS

10 min read
Shape April 2022 HR 202

Looping over entries is a cornerstone of Craft CMS development. But bottlenecks, complex queries, and pagination bugs can quickly frustrate. This guide provides pro tips for smooth, optimized entry loops. Learn how these iterations work under the hood, streamline performance, output templates fast, and troubleshoot paginated archives, product listings, and more. Everything you need to master entry loops in Craft.

Entry loops iterate over Craft entries to output content. Core features include template syntax like {% for %} tags, eager loading to optimize queries, and integration with pagination and caching. Loops enable displaying entries on indexes, archives, calendars, and product pages. Techniques like nested loops and custom filters enhance capabilities. Entry loops are tailored for Section entries versus categories, assets, and other elements.

Understanding How Entry Loops Work in Craft CMS

Entry Loop Basics

Entry loops are a powerful element in Craft CMS that allow you to iterate through collections of entries and output them in templates. At their core, entry loops work by defining a loop that will cycle through a set of entries, usually defined by an entry query.

Within the loop, you can output fields from each entry in the collection using Twig syntax like entry.title and entry.body. This makes it easy to create lists of blog posts, projects, team members etc. The key difference from other types of loops is that entry loops work specifically with entries from Sections in Craft.

Compared to looping over a simple array or list, entry loops provide more structure and features for working with groups of entries. For example, you can eager load related elements to avoid extra queries. And entry models give you access to helpful methods for outputting data, links, and more. Overall, entry loops are optimized for the type of collections, structures and outputs you commonly need when working with entries in Craft CMS.

Craft CMS Template Syntax

The primary Twig syntax used for entry loops is the {% for %} tag. This defines the iteration and lets you set variables like entry to reference each item in the loop:

{% for entry in entries %}

{{ entry.title }}

{% endfor %}

The entries variable would normally come from an entry query, which selects which entries should be looped through. Additional Twig filters can be chained to the query to further manipulate the entries.

Inside the loop, dot notation like entry.title accesses fields on the entry models. Entry models provide various display methods to output content in templates, like entry.summary(), entry.getLink(), and entry.postDate.format('F Y') for formatting dates.

For optimal performance, eager loading can be used to reduce database queries, by eager loading any related elements upfront:

{% set entries = craft.entries()

.with(['relatedEntries'])

.all() %}

This avoids N+1 query issues in large entry loops. Overall the Twig template syntax provides a robust way to iterate over entry collections in Craft CMS.

Comparison to Other Loop Types

While entry loops share some similarities with other loop types, there are a few key differences that set them apart:

Category Loops

  • Category loops output a structure of categories and sub-categories. Entry loops work with flat collections of entries.

Asset Loops

  • Asset loops iterate over files and images. Entry loops work with Section entries that contain content across multiple fields.

Global Loops

  • Global loops output fields from global sets. Entry loops pull content from structured entry models.

Element Queries

  • Element queries can loop over multiple element types. Entry loops focus just on entries from Sections.

The specific focus of entry loops on Collections and Section entries makes them optimized for powering common templates like blog indexes, team pages, case study listings, and similar entry-focused templates in Craft CMS.

Using Entry Loops to Display Content

Basic Entry Loop Usage

The most common way to use entry loops is to display content from a Section. The loop iterates over the entries, allowing you to output fields, titles, images and more.

To start, you create an entries query for the Section, usually filtered by criteria like entry type, status, order etc. Common filters are section, type, status, and order:

{% set entries = craft.entries()

.section('news')

.type('article')

.status(true)

.orderBy('postDate desc')

.all() %}

The query can then be looped through using a for tag:

{% for entry in entries %}

<h2>{{ entry.title }}</h2>

{{ entry.summary }}

{% endfor %}

Inside the loop entry will be set to each entry model, allowing you to output fields using dot notation like entry.title.

Pagination can be added by limiting and offsetting the query results. And caching can optimize performance for large entry collections.

Overall, it provides a straightforward way to display content from multiple entries.

Advanced Entry Loop Techniques

For more complex templates, advanced entry loop techniques open up further possibilities:

Nested Loops

Loops can be nested to output hierarchical or related data. For example, looping over categories to output entries within each category.

Mixed Element Loops

Entry loops can be combined with loops over categories, assets or other elements to create mixed output.

Eager Loading

Eager loading improves performance by reducing database queries for related elements.

Custom Filters/Modifiers

New Twig filters can transform or customize entry output within loops.

Debugging Loops

Debugging tools like dump(), source() and debug bars help diagnose loop issues.

These approaches unlock more powerful use cases when working with entry collections.

Displaying Entry Content

Within an entry loop, Twig gives you full access to display content from each entry:

Titles

Entry titles can be output using {{ entry.title }}.

Summaries

The entry.summary() method outputs a summary from the full body content.

Body Content

{{ entry.body }} outputs the full body content field.

Images

Images can be output using {% set image = entry.image.one() %} and {{ image.url }}

Dates

Dates are accessible via entry.postDate and can be formatted using Twig's date() filter.

Links

entry.getLink() generates a URL to the entry page.

Combined together, these allow you to fully output SEO-friendly templates optimized to display entry content.

Optimizing Entry Loop Performance

Improving Loop Speed

There are various techniques that can optimize entry loop speed:

Eager Loading

Eager loading related elements avoids N+1 query issues:

{% set entries = entries.with(['relatedEntries']) %}

.find() vs .all()

.find() iterates without loading all entries, .all() loads all upfront.

Avoiding N+1 Queries

Fetch related data upfront with eager loading.

Caching

Cache full entry query results for repeated loops.

Deferred Filtering

Filter early to narrow down results.

Pagination

Paginate long lists into smaller chunks.

Minify Templates

Minify Twig templates to reduce parse time.

Following these best practices will improve entry loop speed.

Diagnosing Issues

To diagnose entry loop problems:

Enable Debugging

Craft's debugger bar shows execution time and queries.

Profile Pages

Browser profiling tools pinpoint slow sections.

Log Statements

Log statements can time portions of a loop.

Examine Queries

Check for N+1 queries using eager loading.

Identify Bottlenecks

Find where time is spent - DB, code, cache etc.

Simulate Traffic

Test under simulated production traffic.

Targeted diagnostics make it possible to pinpoint and fix entry loop issues.

Caching and Pagination

Caching and pagination help optimize long entry loops:

Full Page Caching

Cache the full HTML to avoid running queries.

Fragment Caching

Cache just the entry loop HTML fragment.

Invalidate Selectively

Invalidate strategically on entry changes.

Pagination

Break long lists into smaller pages.

Limit Offset

Paginate by limiting and offsetting the entry query.

Page Caching

Cache each paginated page separately.

For maximal optimization, combine caching strategies with pagination to improve performance.

Careful cache invalidation avoids stale data.

Together, these approaches help ensure fast, efficient entry loops - even for large, complex queries across thousands of entries. By following performance best practices, diagnosing issues, and leveraging caching and pagination, entry loops can deliver lightning-fast experiences for Craft CMS sites.

Troubleshooting Common Entry Loop Issues

Debugging Techniques

Debugging entry loops employs several helpful techniques:

Log Statements

Logging variables shows their values during execution.

var_dump()

Dumps structured information about a variable for debugging.

Debugger Toolbar

Craft's debug toolbar provides execution times, queries, and profiling.

Error Messages

Read error messages carefully to pinpoint causes.

Common Problems

Check for undefined variables, indexing issues, cache interference etc.

Targeted debugging provides visibility into common entry loop problems.

Missing Relations and Eager Loading

A common issue is missing data from related elements. This happens when lazy loading related elements:

{% for entry in entries %}

{# Bad - lazy loads categories #}

{{ entry.categories.title }}

{% endfor %}

This results in N+1 queries to load the related categories each iteration.

Eager loading solves this:


{% set entries = entries.with(['categories']) %}


{% for entry in entries %}

{# Good - eager loaded categories #}

{{ entry.categories.first().title }}

{% endfor %}

Now categories are queried just once upfront. Always eager load related elements that are output in loops.

Pagination and Caching Problems

More complex entry loops often involve pagination and caching:

Pagination Inconsistencies

Debug unexpected page counts, item numbers etc.

Expired Cache

Check for expired cache causing empty, stale data.

Cache Key Issues

Validate cache keys are unique for each query.

Complex Query Problems

Isolate issues with complex criteria, custom fields etc.

N+1 Queries

Eager load all relations needed for paginated loops.

A systematic approach helps uncover the source of pagination and caching bugs.

Careful debugging provides the insights needed to fix frustrating entry loop issues. Tracking down problems like N+1 queries, caching, pagination, and eager loading relations allows you to optimize entry loop performance and stability. With the right techniques, you can troubleshoot and resolve even subtle, intermittent entry loop bugs.

Example Entry Loop Use Cases

Blog Index and Archives

Entry loops are perfect for powering blog templates:

Blog Index

Loop through blog post entries, sorted by date. Output titles, summaries and thumbnails.

Category/Tag Archives

Filter by categories or tags to show filtered archive lists.

Recent Posts

Limit to show just the 10 most recent posted blog entries.

Post Sidebars

Loop over 4 related entries to show in a blog post sidebar.

Paginated Indexes

Paginate the index into multiple pages using .limit() and .offset()

Post Excerpts

Output post excerpt text from the entry.excerpt field in summary views.

For blogs, entry loops provide the flexibility to show posts in all required ways.

Events Listings and Calendars

Entry loops are useful for events:

Upcoming Events

Limit to show upcoming event entries sorted by date.

Event Listings

Loop over all published event entries.

Grouped by Date

Group event entries by date into daily/weekly/monthly layouts.

Filtered Events

Allow filtering events by category, date period, location etc.

Event Calendars

Output events into a calendar view by mapping dates to days.

Featured Events

Limit to highlight featured event entries specifically.

Related Events

Show related event entries at the bottom of each event.

The structure of entries makes them fit naturally for displaying events.

Product/Service Pages

Product and service templates can also leverage entry loops:

New Arrivals

Limit to show the latest products by release date.

Category Pages

Loop over products within a certain category.

Sale Items

Filter products on sale using custom sale field criteria.

Featured Products

Limit products marked as featured.

Recommendations

Create a related/recommended product block using a loop.

Comparison Tables

Loop over products to populate a comparison table.

Product Carousels

Cycle product entries in a carousel component.

Entry loops provide the query power needed for robust product/service templates.

The structured content model of entries lends itself well to looping over blogs, events, products, and many other types of content in Craft CMS.

When Not to Use Entry Loops

Alternate Approaches

While entry loops are very useful, there are some cases where alternate approaches may be better:

Single Entries

No need to loop if displaying just a single entry. Retrieve it directly instead.

Global Queries

For global content, use global sets instead of single entry Sections.

Entry Queries

For simple lists, an entry query may suffice without a full loop.

Eager-Loaded Entries

If entries are already eager loaded, iterate them directly.

Non-Display Usage

For background tasks, avoid looping when not displaying data.

Simpler Data

For non-structured data, arrays or objects may suffice.

Evaluating the specific use case can reveal if a simpler approach is more optimal.

Non-Entry Content

Entry loops specifically target entry collections. For other elements, different approaches are needed:

Categories

Use craft.categories to fetch category models directly.

Assets

Loop over assets using craft.assets and asset queries.

Users

Retrieve users with craft.users and user queries.

Matrix Blocks

Fetch matrix blocks using entry.matrixFieldHandle on entries.

Tags

Loop over tags using entry.tags rather than standalone queries.

Custom Tables

For custom tables, use custom services and models.So while entry loops are specialized for entries, they don't apply universally to all content types.The goal is to always match the loop type to the models and data structures you are outputting.

Entry loops are optimized for Section entries, but aren't necessarily the best solution for categories, users, and other non-entry element types.

Considering the specific elements needed for a template can help identify when to reach for alternate query and loop techniques instead of traditional entry loops in Craft CMS.

Shape April 2022 HR 202
Andy Golpys
- Author

Andy has scaled multiple businesses and is a big believer in Craft CMS as a tool that benefits both Designer, Developer and Client. 

Share
Feedback
Show us some love
Email Us
We usually reply within 72 hours
Agency Directory
Submit your agency
Affiliate Partners
Let's chat