3

I have been using the ids() method on the ElementCriteriaModel returned by a call to an entries field within a Twig template to return an array of ids for further processing.

Now I wish to eager-load these entries, but the entries are returned as an array with no access to the ids() method.

Is there an efficient way to get this array of ids within Twig, or would I be better moving this to a plugin?

3

You would just loop the entry models to collect the IDs (looks ugly, but it's a simple and efficient for loop). But in case you do not need anything else from the models, I'd actually expect your previous approach using the ids method to have better performance.

{% set ids = [] %}
{% for entry in entry.myEagerLoadedEntries %}
    {% set ids = ids|merge([entry.id]) %}
{% endfor %}
2

You could use the indexBy parameter and the keys filter:

{# Using indexBy updates the results array to be indexed by the Element ID
   instead of a consecutively numbered array #}
{% set entries = craft.entries.section('news').with(['featuredImage']).indexBy('id') %}

{# The keys filter returns an array of all the keys within an array,
   discarding the values #}
{% set entryIds = entries|keys %}

This would give you an array of the Element IDs that were retrieved.

4
  • The indexBy looks handy (never noticed it in the docs), but in this case it won't work, as the OP needs the IDs of the eager loaded elements.
    – carlcs
    Apr 20 '16 at 7:32
  • Can you elaborate on how this doesn't provide the ids in the format necessary in the question? indexBy just updates the ids of the result array to be the Element IDs that are needed, and passing the results through the keys filter creates an array of the ids, just like the loop and merge approach. The eager loaded elements are still available via the entries variable, and an array of ids is available for use via the entryIds variable. Apr 20 '16 at 23:15
  • Hmm.. but thinking about it, it might actually be possible to use that indexBy param within the with param. That might work. But I'm still thinking eager loading isn't worth it at all in this case. An extra query using the ids method is probably performing better as you don't have the (unnecessary) overhead of populating all the models.
    – carlcs
    Apr 20 '16 at 23:35
  • 1
    That does sound possible: with(['featuredImage', { indexBy: 'id' }]) however, I think your right in that it really depends which ids are needed and where on the page. Eager loading is about optimizing the querying of relations, and this question is just about getting an array of IDs. In the case the OP needs both the results and the IDs, I think something like this answer works fine, getting the optimized eager-loaded data, and using keys to distill the IDs. In the case they just need the IDs, there is no real need to add eager-loading to the mix. Apr 21 '16 at 15:05

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.