❗️ This solution will be dramatically simplified in Craft 4.3!
Unfortunately, the answer differs pretty dramatically for native properties with "stable" column names and for Content, which (as of Craft 3.7.0) now contain a "suffix" that (in most any other case) is not a concern for developers. More on that in a moment.
Titles
For titles, it's as simple as using the .select()
method native to the underlying Query
class:
{% set titles = craft.entries
.section('mySection')
.select(['title'])
.column() %}
{# -> ['Post A', 'Post B', 'Post C', ...] #}
Note the .column()
query execution method—this basically means "just return the values in the first selected column"!
Alternatively, you can select multiple columns, like this:
{% set titles = craft.entries
.section('mySection')
.select(['title', 'slug'])
.asArray()
.all() %}
{# -> [{ 'title': 'Post A', 'slug': 'post-a' }, ...] #}
Note the .asArray()
method, which ensures Element models aren't populated with the limited subset of data, after the rows come back!
Content
Please correct me if I'm wrong about this—my sense is that this feels too complicated, but it's based on how the core ElementQuery maps unpredictable column names! 🤷
This picture is much murkier, and currently only works if you either:
- …know the field columns'
suffix
beforehand (which you may, as Project Config and Templates are often versioned + deployed together—and the suffix is easily accessible in the field's yml
file);
- …can load and call
ElementHelper::fieldColumn(…)
to generate a column name, on the fly.
Suppose you do know the suffix:
{% set minimalDataset = craft.entries
.select([
'title',
'field_myCustomField_otfeztjq as myCustomField'
])
.asArray()
.all() %}
Not great, right? The only relief we get here is that the columns can be renamed on-the-fly, using the as
keyword.
For the sake of completeness, here's an example in PHP that satisfies #2, above:
use Craft;
use craft\elements\Entry;
use craft\helpers\ElementHelper;
// Initialize a query, and ensure results are returned as a plain array:
$query = Entry::find()->asArray();
// Load up our field's definition:
$field = Craft::$app->getFields()->getFieldByHandle('myFieldHandle');
// Be aware that the Date field (as well as some plugin-provided fields) may actually return *multiple* column names, and would need to be merged, rather than declared as part of this Select statement!
$fieldColumn = ElementHelper::fieldColumnFromField($field);
$query->select([
'title',
"{$fieldColumn} as fieldAlias",
]);
$query->all();
See @MoritzLost’s answer, below, for a more complete and reusable version of this approach!
column()
filter:{% titles = entries | column('title') %}
. This will also work with any field handle (or method) that is available on the collection you're working with!