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 %}
Bill Columbia
  • 896
  • 1
  • 8
  • 18

2 Answers2

3

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.

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 %}
Jamie Pittock
  • 1,511
  • 11
  • 15
  • 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