4

I have structures called Instrument and Person. On the person structure, I have a Matrix field called Roles. Roles has a block called Musician. And That block type has a Relationship Field called Instrument.

This allows someone to be a musician and to be assigned an instrument.

In my template I need to output each Instrument as a section, and all of the musicians that play that instrument.

I think this issue has something to do with the relationship being added in a Matrix block rather than on the entry itself.

Unfortunately there are many roles (block types) that a person can have, each with different fields. I tried to solve this by swapping to Instruments as categories but that doesn't seem to be working either. Here's some sample code I've been playing with:

        {% for instrument in craft.entries.section('instrument') %}
          <h3>{{ instrument.instrumentName }}</h3>
          {% for person in craft.entries.section('person').relatedTo( instrument ) %}
            <p>{{ person.personName }}</p>
          {% endfor %}
        {% endfor %}
  • I should probably elaborate that this code does not work. – Bill Columbia Sep 13 '14 at 0:53
2

I think your first idea of using Matrix rather than Categories makes the most sense as a content model.

I recently added a new method to the plugin lowblocks which should help you. Low has already merged it into the core so go and install it now.

This should work for you hopefully:

{# loop through the instruments #}
{% for instrument in craft.entries.section('instrument') %}

    <h3>{{ instrument.instrumentName }}</h3>

    {# select all our musician blocks related to this instrument #}
    {% set musicians = craft.lowblocks.blocks.type('musiciansBlockHandle').relatedTo(instrument) %}

    {% if musicians | length %}

        {# loop through the results #}
        {% for musician in musicians %}

            {# set a variable to store the person (the entry/owner of this block #}
            {% set person = musician.owner %}

            <p>{{ person.personName }}</p>

        {% endfor %}

    {% endif %}

{% endfor %}
  • 1
    Went ahead and gave it a shot. Works pretty well. Thanks for the tip. Does this mean Craft does not have a native way to query by Matrix field block type in templates? – Bill Columbia Sep 16 '14 at 16:51
2

You were right about the issue being that the relationship is made within a Matrix field. Because of this, you have to explicitly pass the Matrix field's handle to the relatedTo parameter.

{% for instrument in craft.entries.section('instrument') %}
      <h3>{{ instrument.instrumentName }}</h3>
      {% set people = craft.entries.section('person').relatedTo({
         targetElement: instrument,
         field: 'roles.instrument'
      }) %}
      {% if people|length %}
         {% for person in people %}
           <p>{{ person.personName }}</p>
         {% endfor %}
      {% else %}
         <p>Nobody plays {{ instrument.instrumentName }} :(</p>
      {% endif %}
{% endfor %}

Note: Using a dot notation to specify the sub-field is only necessary if you have multiple relational fields within a Matrix, but it can't hurt.

  • Awesome thanks for this tip! – Bill Columbia Nov 3 '14 at 20:49

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.