Performantly fetching URI's in Craft

1 month ago
#craftcms

Every website has some static links to pages within Craft that are never linked to within the entry you're displaying. Some footer links to your contact page, privacy policy or that big cta button your client wanted on the homepage.

What we tend to do is hard code them. That contact uri will never change, right? A better way is to load them only once for all pages in your base layout template, or on top of the current template if it's page specific.

{% set preFetchedUris = craft.entries
  .id([1,2])
  .select('uri')
  .distinct(1)
  .column() %}

It's important to group all these static uri's in a single query. Because we only really need the uri, make sure you only query for that one field. Using yii's column() method we're only returning the first column of our result. In our case there only is one column, so uri will be returned.

Make sure you run the uri's through Craft's url function.

<a href="{{ url(preFetchedUris[0]) }}">{{ 'Privacy Policy'|t }}</a>

This will result in a query that is much more performant than simply calling craft.entries.id([7,21]).all().

Alternate use case

This technique is also useful when you need an array of some data out of Craft. Let's say you have a section of entries containing zip codes. You could extract a list of unique zip codes:

{% set zipCodes = craft.entries
  .select('field_zip')
  .section('locations')
  .orderBy('field_zip')
  .zip(':notempty:')
  .distinct(true)
  .column() %}

There you have it, when you only need 1 field out of Craft, be it a uri or any other form of data, don't result to the usual way of querying using Crafts .all() method. Rather use yii's built in functions of only querying for the data you need, and nothing more.