There’s a lot to unpack here. Before I get to the solution, I’ll step through each of your examples, line-by-line. Hopefully that will help explain the behavior you’re seeing.
First Example
{# Get all entries from the section. #}
{% set entries = craft.entries.section('mySection') %}
Your comment is correct – this will fetch all the entries from section mySection
and assign them to a new variable called entries
.
{# Loop through the entries and get the user account associated with each. #}
{% for profiles in entries %}
Start a loop on the entries
variable. Within the loop, each profile entry will be represented by a profiles
variable.
Note: it’s misleading to call your variable “profiles” rather than “profile”, since it will only represent a single profile entry.
{% set users = profiles.userAccount %}
Fetch all of the user accounts related to the current profile (profiles
) via the userAccount
field, and assign them to a new variable called users
.
{% if users|length %}
Only do the following if there were any related users…
{% for year, user in users|group('myYearField') %}
Turn the users (users
) that are related to the current profile (profiles
) into a multi-dimensional array, grouped by their myYearField
field values. Then start a loop on that multi-dimensional array. Within the loop, each myYearField
value will be represented by a year
variable, and the array of grouped user accounts will be represented by a user
variable.
Note: This is where things start really going wrong. You want to group all of your users by year – not just the ones that are related to the current profile. Also, your choice of “user” as a variable name here is misleading since it’s actually an array of grouped users; not a single user.
<h4>{{ year }}</h4> {# 2016 #}
Output the current grouping’s myYearField
value, which was assigned to a year
variable.
<ul class="list-unstyled">
{% for user in users %}
Start a loop on the same users
variable that you’re already in the middle of looping through. users
here refers to the same users
variable that was defined in the 3rd codeblock.
<li><a href="{{ profiles.url }}">{{ user.name }}</a></li>
Output the profile entry’s (profiles
) URL, and the current user’s (user
) name.
{% endfor %}
Close out the loop on the user accounts related to the current profile entry (users
).
</ul>
{% endfor %}
Close out the loop on the multi-dimensional array of year-user groupings based on the user accounts related to the current profile entry (users
).
{% endif %}
Close out the conditional checking if there any users related to the current profile entry.
{% endfor %}
Close out the loop on the profile entries (entries
).
Second Example
{% set allProfiles = craft.entries.section('mySection') %}
Fetch all the entries from section mySection
and assign them to a new variable called allProfiles
.
{% if allProfiles|length %}
Only do the following if there were any profile entries…
{{ allProfiles|length }} {# 3 #}
Output the total number of profile entries.
{% for profiles in allProfiles %}
Start a loop on the allProfiles
variable. Within the loop, each profile entry will be represented by a profiles
variable.
Note: as with the last example, it’s misleading to call your variable “profiles” rather than “profile”, since it will only represent a single profile entry.
{% for profile in profiles.userAccount %}
Fetch all of the user accounts related to the current profile (profiles
) via the userAccount
field. Start a loop on the user accounts. Within the loop, each user account will be represented by a profile
variable.
Note: it’s misleading to call your variable “profile”, since it is actually the user account, not the profile entry.
{% for year, user in profile|group('yearFieldHandle') %}
Turn the current user account (profile
) into a multi-dimensional array, grouped by its properties’ yearFieldHandle
sub-property values (which isn’t a thing). Then start a loop on that multi-dimensional array. Within the loop, each yearFieldHandle
value will be represented by a year
variable, and the array of grouped user account properties will be represented by a user
variable.
Note: Since profile
is a single element (the user account) and not an array of elements, nothing about this is likely doing what you expected it to.
<h1>{{ year }}</h1> {# No output #}
Output the current grouping’s yearFieldHandle
value, which was assigned to a year
variable. (This is the equivalent of doing something like profile.id.yearFieldHandle
. It’s expected that you wouldn’t get any output.)
<h2>{{ profile.firstName }}</h2> {# Bob #}
Output the user account’s first name.
<h3>{{ profile.myYear }}</h3> {# 2016 #}
Output the user account’s myYear
custom field value.
{% endfor %}
Close out the loop on the multi-dimensional array of year-user account property groupings based on the current user account defined by the parent loop.
{% endfor %}
Close out the loop on the user accounts related to the current profile entry.
{% endfor %}
Close out the loop on the profile entries (allProfiles
).
{% endif %}
Close out the conditional checking if there any profile entries.
Solution
To group all of your profiles by their related user accounts’ custom date fields, first let’s load the profiles, eager-loaded with their related user accounts:
{% set profiles = craft.entries({
section: 'userProfiles',
with: ['userAccount']
}) %}
Next let’s group the profiles by the myYear
custom field on their related user accounts:
{% set profilesByYear = profiles|group('userAccount[0].myYear') %}
Now we can loop through the years, and their corresponding user profiles/accounts:
{% for year, yearProfiles in profilesByYear %}
<h1>{{ year }}</h1>
{% for profile in yearProfiles %}
{% set user = profile.userAccount[0] ?? null %}
{% if user %}
<h2>{{ user.firstName }}</h2>
<h3>{{ user.myYear }}</h3>
{% endif %}
{% endfor %}
{% endfor %}
myYearField
a DateTime or PlainText field?myYearField
within the CP.