I have written a query to select all categories for a certain entry. In this case, the category is called "Key Stage" and each one is written "Key Stage 1", "Key Stage 2" etc. What I'd like to happen is that if more than one category is selected for the entry, the duplicated words "Key Stage" could be stripped out, leaving "Key Stage 1 & 2", instead of "Key Stage 1 & Key Stage 2".

Below is the code I have thus far, which is just the query and looping out the results, adding an ampersand for subsequent items in the loop after the first:

{% set eventKeyStage = event.keyStage.all() %}
<p class="stage">
  {% for stage in eventKeyStage %}
  {% if not loop.first %}&amp; {% endif %}
  {{ stage.title }}
  {% endfor %}

Any advice is greatly appreciated!

1 Answer 1


You might want to rethink your approach – any solution you build for this will break as soon as someone adds a new category that doesn't exactly match the naming pattern. In general, try to avoid redundancies. If the whole category is called Stages or Key Stages, calling each category Key Stage 1, Key Stage 2 etc is redundant. If you instead call your categories only 1, 2, and so on, you avoid the problem altogether. Given that naming, the code becomes nice and easy:

{% set eventKeyStages = event.keyStage.all() %}
{{ 'Key Stage ' ~ (eventKeyStages|join(', '))

Another advantages of this approach is that it's easy to translate if you ever need more than one langugage:

{% set eventKeyStages = event.keyStage.all() %}
{{ 'Key Stage {stages}'|t({ stages: eventKeyStages|column('title')|join(' & ') }) }}

If you absolutely want to go with your approach, here's a simple solution:

{% set eventKeyStages = event.keyStage.all() %}
{{ 'Key Stage ' ~ (eventKeyStages
    |map(stage => stage|replace({ 'Key Stage ': ''}))
    |join(' & ')
) }}

Some additional thoughts addressing the comments and further questions.

Filtering out categories without "Key Stage" in the name.

If there are other categories that don't follow that schema, you can adjust your query to only find categories that do:

{% set eventKeyStages = event.keyStage.title('Key Stage*').all() %}
{{ 'Key Stage ' ~ (eventKeyStages|join(', '))

Of course, you can also get all categories and then split them into to groups (key stage categories and other categories) to display them separately.

Sorting in ascending orders

If you're worried that the key stages might be selected in the wrong order, you can order the query by title to make sure they're in the right order:

{% set eventKeyStages = event.keyStage.title('Key Stage*').orderBy('title ASC').all() %}
  • 1
    Thank you for all your help on this! I was able to merge my accounts and have accepted your answer :)
    – Grace
    Commented Nov 14, 2021 at 14:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.