<p>Ended up using <strong>GraphQL</strong></p>
<p>Let's say we have an entry, and from that entry we need to retrieve the &quot;title&quot;, and the <strong>custom field</strong> &quot;relatedProducts&quot;, which is an <em>entry type</em> field, and from those related entries we need to retrieve the &quot;title&quot;, &quot;url&quot; and an image URL from a <strong>custom field</strong> called &quot;productImage&quot;</p>
<p>That sounds a bit complicated to just do it with twig queries.</p>
<p>So instead of those, I ran the following query:</p>
<pre><code>   {% set relatedProducts = gql('{
          entry (id: &quot;' ~ entry.id ~ '&quot;) {
              ... on productsCategories_productBasic_Entry {
                  title
                  relatedProducts {
                       title
                       url
                       productImage {
                          url
                       }
                  }
               }
         }
}') %}
</code></pre>
<p>After I dump the values (<code>{% dd(relatedProducts) %}</code>), I get:</p>
<pre><code>[
    'data' =&gt; [
        'entry' =&gt; [
            'title' =&gt; 'track - grey'
            'relatedProducts' =&gt; [
                0 =&gt; [
                    'title' =&gt; 'Track - black'
                    'url' =&gt; 'https://mysite.ddev.site/tracks-and-accessories/track-black'
                    'productImage' =&gt; [
                        0 =&gt; [
                            'url' =&gt; 'https://mysite.ddev.site/uploads/280x180.png'
                        ]
                    ]
                ]
                1 =&gt; [
                    'title' =&gt; 'Track - white'
                    'url' =&gt; 'https://mysite.ddev.site/tracks-and-accessories/track-white'
                    'productImage' =&gt; []
                ]
            ]
        ]
    ]
]
</code></pre>
<p>which is what I needed :)</p>

CC BY-SA 4.0
2022-09-29T22:27:02.907Z
Could you elaborate on where this data is being used? In Twig to render HTML, or JSON via AJAX? Hoping to understand the underlying intent to make sure we aren't missing some simpler solution for you!
August Miller
CC BY-SA 4.0
2022-10-02T21:33:47.717Z
Thanks @AugustMiller! 
I need to pass it to a Vue component, which I'm currently sending as JSON
Paloma Martinez
CC BY-SA 4.0
2022-10-03T22:52:12.530Z
Ok, fair enough! This kind of data massage will always be challenging with Twig; GraphQL sounds like a great option. Pulling the data directly from Vue may be even easier, through the [native GraphQL API](https://craftcms.com/docs/4.x/graphql.html)—or by setting up an [Element API](https://github.com/craftcms/element-api) endpoint to do the lookup and transformation in PHP-land. ✌️
August Miller
CC BY-SA 4.0
2022-09-23T04:01:35.880Z
2022-09-23T04:01:35.880Z
Paloma Martinez
<p>❗️ This solution will be <a href="https://github.com/craftcms/cms/pull/11800" rel="nofollow noreferrer">dramatically simplified</a> in Craft 4.3!</p>
<hr />
<p>Unfortunately, the answer differs pretty dramatically for native properties with &quot;stable&quot; column names and for Content, which (as of <a href="https://github.com/craftcms/cms/issues/6922" rel="nofollow noreferrer">Craft 3.7.0</a>) now contain a &quot;suffix&quot; that (in most any other case) is not a concern for developers. More on that in a moment.</p>
<h3>Titles</h3>
<p>For titles, it's as simple as using the <code>.select()</code> method native to the underlying <code>Query</code> class:</p>
<pre class="lang-twig prettyprint-override"><code>{% set titles = craft.entries
    .section('mySection')
    .select(['title'])
    .column() %}

{# -&gt; ['Post A', 'Post B', 'Post C', ...] #}
</code></pre>
<blockquote>
<p>Note the <code>.column()</code> query execution method—this basically means &quot;just return the values in the first selected column&quot;!</p>
</blockquote>
<p>Alternatively, you can select multiple columns, like this:</p>
<pre class="lang-twig prettyprint-override"><code>{% set titles = craft.entries
    .section('mySection')
    .select(['title', 'slug'])
    .asArray()
    .all() %}

{# -&gt; [{ 'title': 'Post A', 'slug': 'post-a' }, ...] #}
</code></pre>
<blockquote>
<p>Note the <code>.asArray()</code> method, which ensures Element models aren't populated with the limited subset of data, after the rows come back!</p>
</blockquote>
<h3>Content</h3>
<blockquote>
<p>Please correct me if I'm wrong about this—my sense is that this <em>feels</em> too complicated, but it's based on how the core ElementQuery maps unpredictable column names! </p>
</blockquote>
<p>This picture is much murkier, and currently only works if you either:</p>
<ol>
<li>…know the field columns' <code>suffix</code> beforehand (which you may, as Project Config and Templates are often versioned + deployed together—and the suffix is easily accessible in the field's <code>yml</code> file);</li>
<li>…can load and call <code>ElementHelper::fieldColumn(…)</code> to generate a column name, on the fly.</li>
</ol>
<p>Suppose you <em>do</em> know the suffix:</p>
<pre class="lang-twig prettyprint-override"><code>{% set minimalDataset = craft.entries
    .select([
        'title',
        'field_myCustomField_otfeztjq as myCustomField'
    ])
    .asArray()
    .all() %}
</code></pre>
<p>Not great, right? The only relief we get here is that the columns can be renamed on-the-fly, using the <code>as</code> keyword.</p>
<p>For the sake of completeness, here's an example in PHP that satisfies #2, above:</p>
<pre class="lang-php prettyprint-override"><code>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()-&gt;asArray();

// Load up our field's definition:
$field = Craft::$app-&gt;getFields()-&gt;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-&gt;select([
    'title',
    &quot;{$fieldColumn} as fieldAlias&quot;,
]);

$query-&gt;all();
</code></pre>
<blockquote>
<p>See @MoritzLost’s answer, below, for a more complete and reusable version of this approach!</p>
</blockquote>

CC BY-SA 4.0
2021-10-14T07:56:38.983Z
Hardcoding the suffix is indeed not great, though it appears to be the simplest way to use custom queries right now. But you can also write a small twig extension to expose the field column helper method to Twig, see my answer below.
MoritzLost
CC BY-SA 4.0
2022-03-10T13:03:51.177Z
Fantastic answer - I learnt some cool stuff there! Thanks!
bhu Boue vidya
CC BY-SA 4.0
2021-10-14T03:04:52.717Z
2022-09-29T22:29:47.690Z
2022-09-29T22:29:47.690Z
August Miller
<h2>Update for Craft 3.7</h2>
<p><a href="https://github.com/craftcms/cms/blob/v3/CHANGELOG.md#370---2021-07-13" rel="nofollow noreferrer">Craft 3.7</a> adds a new <a href="https://docs.craftcms.com/api/v4/craft-base-fieldtrait.html#columnsuffix" rel="nofollow noreferrer">field property <code>columnSuffix</code></a> which is way easier to use than my example code below.</p>
<p>Now you can simply access any field's column suffix in Twig like this:</p>
<pre class="lang-twig prettyprint-override"><code>{% set columnSuffix = craft.app.fields.getFieldByHandle('my_custom_field').columnSuffix %}
</code></pre>
<p>See the old answer below if you're still on Craft &lt; 3.7.</p>
<hr />
<h2>Old answer for Craft &lt; 3.7</h2>
<p>Just to expand on the caveat regarding field suffixes in Craft 3.7+, I <a href="https://github.com/craftcms/cms/issues/6922#issuecomment-906266229" rel="nofollow noreferrer">asked on Github</a> what the recommended way to include field suffixes in a custom query is. Here's <a href="https://github.com/craftcms/cms/issues/6922#issuecomment-908871118" rel="nofollow noreferrer">brandonkelly's response</a>:</p>
<blockquote>
<p>The easiest way to do it would be to just hardcode the column name in your template. It won’t change between environments or anything.</p>
</blockquote>
<p>That said, it does feel kind of wrong to hardcode a field suffix like this. Unfortunately, the <code>ElementHelper::fieldColumnFromField</code> method is not exposed to Twig, so there's no straightforward way to use it. The closest I've come is this code:</p>
<pre><code>{% set body_field = craft.app.fields.getFieldByHandle('body') %}
{% set ElementHelper = create('craft\\helpers\\ElementHelper') %}
{% set body_column = ElementHelper.fieldColumnFromField(body_field) %}

{% set entries = craft.entries().select(['title', body_column]).all() %}
</code></pre>
<p>However, that's still pretty verbose and might not work in the future as per brandonkelly's response:</p>
<blockquote>
<p>@MoritzLost I wouldn’t instantiate an ElementHelper instance in your template; the class should really be marked as absract as it’s not meant to be instantiated.</p>
</blockquote>
<p>I guess the most future-proof way would be to write a Twig extension that adds a utility method to get the field suffix from the field name:</p>
<pre class="lang-php prettyprint-override"><code>&lt;?php

namespace modules\Twig\Extension;

use Craft;
use craft\helpers\ElementHelper;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class QueryHelperExtension extends AbstractExtension
{
    public function getFunctions()
    {
        return [
            new TwigFunction('fieldColumnFromFieldHandle', [self::class, 'fieldColumnFromFieldHandle']),
        ];
    }

    /**
     * Get the database column name for a field to use in custom database queries.
     *
     * @param string $fieldHandle
     * @return string
     */
    public static function fieldColumnFromFieldHandle(string $fieldHandle): string
    {
        $field = Craft::$app-&gt;fields-&gt;getFieldByHandle($fieldHandle);
        return ElementHelper::fieldColumnFromField($field);
    }
}
</code></pre>
<p>Make sure to register the extension:</p>
<pre class="lang-php prettyprint-override"><code>&lt;?php

namespace modules\Twig;

use Craft;
use modules\Twig\Extension\QueryHelperExtension;

class TwigExtensionModule extends \yii\base\Module
{
    public function init()
    {
        Craft::$app-&gt;view-&gt;registerTwigExtension(new QueryHelperExtension);

        parent::init();
    }
}
</code></pre>
<p>Now you can use that in Twig to get field column names more easily:</p>
<pre><code>{% set bodyColumn = fieldColumnFromFieldHandle('body') %}
</code></pre>

CC BY-SA 4.0
2022-03-10T13:05:57.067Z
That is very cool. Thanks!
bhu Boue vidya
CC BY-SA 4.0
2023-02-20T11:16:01.560Z
Thank you for this. It helped me. I had some problems with getting a super table columns' suffix, though.
I had to modify the fieldColumnFromFieldHandle method a bit like so
`$result = Craft::$app->getDb()->createCommand("SELECT columnSuffix FROM fields WHERE handle = :handle;", ['handle' => $fieldHandle])->queryOne();`
Erik Pöhler
CC BY-SA 4.0
2023-02-21T09:56:28.990Z
@ErikPöhler Whate kind of problems? Going through `ElementHelper` should be more robust and shouldn't require an additional database query. Did the module code in my answer throw an error somewhere?
MoritzLost
CC BY-SA 4.0
2023-02-21T10:04:51.530Z
@ErikPöhler By the way, this became way easier in Craft 3.7, I've updated my answer accordingly. If you're working with Craft 3.7 or above, I recommend this simpler approach. Thanks for the nudge!
MoritzLost
CC BY-SA 4.0
2023-02-22T17:53:33.263Z
The problem was that $field was null, but needs to be a FieldInterface. Your code worked for fields with global context, though. (Supposedly one needs to pass some superTable context).

Having said that, the new solution looks way better. I appreciate, you shared it.
Erik Pöhler
CC BY-SA 4.0
2023-02-23T08:52:32.850Z
@ErikPöhler Ah you're right, the original approach wouldn't work for nested fields in Matrix or Super Table blocks. Those are a bit more tedious to get a hold of. But yeah, the new approach is way easier.
MoritzLost
CC BY-SA 4.0
2021-10-14T07:55:17.187Z
2023-02-21T10:01:55.557Z
2023-02-21T10:01:55.557Z
MoritzLost
<p>I know that to get the entries I can do:</p>
<pre><code>craft.entries.all()
</code></pre>
<p>but instead of getting the whole collection of entries, I would like to get an array of titles from those entries (or any other field).</p>
<p>Sort of like <code>craft.entries.all('myCustomField')</code></p>
<p>How is it possible to achieve it?</p>
<p>Thanks</p>

CC BY-SA 4.0
2021-10-14T03:06:34.983Z
Answered for completeness, as the ability to do this changed pretty significantly as of 3.7.0—but if you just need an array of titles to work with and aren't _super_ concerned about the overhead of fetching + loading all the underlying Elements, you can use the `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!
August Miller
<craft3><templating><entries><entry><query>
Get array of titles instead of whole collection of entries' attributes
# Get array of titles instead of whole collection of entries' attributes

(Asked by: username_0 on 2021-10-14)

I know that to get the entries I can do:
craft.entries.all()

but instead of getting the whole collection of entries, I would like to get an array of titles from those entries (or any other field).
Sort of like craft.entries.all('myCustomField')
How is it possible to achieve it?
Thanks

**Tags:** craft3, templating, entries, entry, query

> **Comments:**
> **username_1**: Answered for completeness, as the ability to do this changed pretty significantly as of 3.7.0—but if you just need an array of titles to work with and aren't _super_ concerned about the overhead of fetching + loading all the underlying Elements, you can use the `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!  

---

## 3 answers

### Answer by username_0 on 2022-09-23. Score: 0 | Accepted answer

Ended up using GraphQL
Let's say we have an entry, and from that entry we need to retrieve the "title", and the custom field "relatedProducts", which is an entry type field, and from those related entries we need to retrieve the "title", "url" and an image URL from a custom field called "productImage"
That sounds a bit complicated to just do it with twig queries.
So instead of those, I ran the following query:
   {% set relatedProducts = gql('{
          entry (id: "' ~ entry.id ~ '") {
              ... on productsCategories_productBasic_Entry {
                  title
                  relatedProducts {
                       title
                       url
                       productImage {
                          url
                       }
                  }
               }
         }
}') %}

After I dump the values ({% dd(relatedProducts) %}), I get:
[
    'data' => [
        'entry' => [
            'title' => 'track - grey'
            'relatedProducts' => [
                0 => [
                    'title' => 'Track - black'
                    'url' => 'https://mysite.ddev.site/tracks-and-accessories/track-black'
                    'productImage' => [
                        0 => [
                            'url' => 'https://mysite.ddev.site/uploads/280x180.png'
                        ]
                    ]
                ]
                1 => [
                    'title' => 'Track - white'
                    'url' => 'https://mysite.ddev.site/tracks-and-accessories/track-white'
                    'productImage' => []
                ]
            ]
        ]
    ]
]

which is what I needed :)

> **Comments:**
> **username_1**: Could you elaborate on where this data is being used? In Twig to render HTML, or JSON via AJAX? Hoping to understand the underlying intent to make sure we aren't missing some simpler solution for you!  
> **username_0**: Thanks @AugustMiller!  I need to pass it to a Vue component, which I'm currently sending as JSON  
> **username_1**: Ok, fair enough! This kind of data massage will always be challenging with Twig; GraphQL sounds like a great option. Pulling the data directly from Vue may be even easier, through the [native GraphQL API](https://craftcms.com/docs/4.x/graphql.html)—or by setting up an [Element API](https://github.com/craftcms/element-api) endpoint to do the lookup and transformation in PHP-land. ✌️  

---

### Answer by username_1 on 2021-10-14. Score: 9

❗️ 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 @username_2’s answer, below, for a more complete and reusable version of this approach!

> **Comments:**
> **username_2**: Hardcoding the suffix is indeed not great, though it appears to be the simplest way to use custom queries right now. But you can also write a small twig extension to expose the field column helper method to Twig, see my answer below.  
> **username_3**: Fantastic answer - I learnt some cool stuff there! Thanks!  

---

### Answer by username_2 on 2021-10-14. Score: 7

Update for Craft 3.7
Craft 3.7 adds a new field property columnSuffix which is way easier to use than my example code below.
Now you can simply access any field's column suffix in Twig like this:
{% set columnSuffix = craft.app.fields.getFieldByHandle('my_custom_field').columnSuffix %}

See the old answer below if you're still on Craft < 3.7.

Old answer for Craft < 3.7
Just to expand on the caveat regarding field suffixes in Craft 3.7+, I asked on Github what the recommended way to include field suffixes in a custom query is. Here's brandonkelly's response:

The easiest way to do it would be to just hardcode the column name in your template. It won’t change between environments or anything.

That said, it does feel kind of wrong to hardcode a field suffix like this. Unfortunately, the ElementHelper::fieldColumnFromField method is not exposed to Twig, so there's no straightforward way to use it. The closest I've come is this code:
{% set body_field = craft.app.fields.getFieldByHandle('body') %}
{% set ElementHelper = create('craft\\helpers\\ElementHelper') %}
{% set body_column = ElementHelper.fieldColumnFromField(body_field) %}

{% set entries = craft.entries().select(['title', body_column]).all() %}

However, that's still pretty verbose and might not work in the future as per brandonkelly's response:

@username_2 I wouldn’t instantiate an ElementHelper instance in your template; the class should really be marked as absract as it’s not meant to be instantiated.

I guess the most future-proof way would be to write a Twig extension that adds a utility method to get the field suffix from the field name:
fields->getFieldByHandle($fieldHandle);
        return ElementHelper::fieldColumnFromField($field);
    }
}

Make sure to register the extension:
view->registerTwigExtension(new QueryHelperExtension);

        parent::init();
    }
}

Now you can use that in Twig to get field column names more easily:
{% set bodyColumn = fieldColumnFromFieldHandle('body') %}

> **Comments:**
> **username_3**: That is very cool. Thanks!  
> **username_4**: Thank you for this. It helped me. I had some problems with getting a super table columns' suffix, though. I had to modify the fieldColumnFromFieldHandle method a bit like so `$result = Craft::$app->getDb()->createCommand("SELECT columnSuffix FROM fields WHERE handle = :handle;", ['handle' => $fieldHandle])->queryOne();`  
> **username_2**: @ErikPöhler Whate kind of problems? Going through `ElementHelper` should be more robust and shouldn't require an additional database query. Did the module code in my answer throw an error somewhere?  
> **username_2**: @ErikPöhler By the way, this became way easier in Craft 3.7, I've updated my answer accordingly. If you're working with Craft 3.7 or above, I recommend this simpler approach. Thanks for the nudge!  
> **username_4**: The problem was that $field was null, but needs to be a FieldInterface. Your code worked for fields with global context, though. (Supposedly one needs to pass some superTable context).  Having said that, the new solution looks way better. I appreciate, you shared it.  
> **username_2**: @ErikPöhler Ah you're right, the original approach wouldn't work for nested fields in Matrix or Super Table blocks. Those are a bit more tedious to get a hold of. But yeah, the new approach is way easier.  

---

