Field of a referenced, referenced entity - worked example

Last updated on
30 November 2019

Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites

Having read the comments on the link from the Rules UI (the parent to this page), I thought I'd take a moment to document what's taken me three days to work out. I'm no expert and this may not be 100% accurate, but hopefully will help somebody make some neural connections. I'll add some pre-amble, an overview of the solution and then an in depth solution for different levels of Rules expertise.

Use Case

My example is that I have a sports website listing team matches. Each match has a home team and away team. Each team belongs to a club. Each club has an associated "club admin" user.

  • Match references two team nodes - field_home_team (and field_away_team)
  • Team references a single club - field_club
  • Club references a single user account - field_club_admin

On each match page I want to display the home club name and the email for the home club admin as a status message. (Obviously I can do all that with themeing, but my actual use case is more complicated, but as you will have seen from many tutorials already, getting a message to display on screen is the easiest way to ensure you're getting the data you wanted.)

Solution Overview

Rules UI completeThe trigger Event is on view of a match node - easy.

The "final" Action is to display the message and as I need info from the club and club admin account I need to fetch both of those as Actions to make their content available within my message.

The tricky bit is getting from match, through team to club to club admin account and accessing the custom entity fields. Getting standard node elements (e.g. node author) is quite easy, but the Rules UI just points to http://drupal.org/node/1300042, which didn't give me enough info.

The trick is to add "Entity is bundle" and "Entity has field" Conditions that chain the referenced entities together and provide deeper and deeper access to the referenced, referenced, referenced entities' field values.

What I end up with is shown in the attached "Solution Overview" image. That image may be enough for some of you to work out how it's done, but for any others...

Solution Details

Create new rule and Event

Go in to Rules and Add a new rule, with Name "Display Club and Club Admin", React on event "Node: Content is viewed" and Restrict by type "Match". That will fire the Rule every time a match is viewed. If that doesn't make sense, go away and read an intro to Rules.

Actions

We'll set up an initial action to make sure the Rule is firing as expected. Add action and select System: Show a message on the site.

Have a look at the replacement patterns. These are all the tokens that are available to display in your message. At this stage you have tokens from the Site ([site:name], etc) and the viewed content (i.e. your match node, e.g. [node:title]). These patterns are currently limited to standard entity field values; there's no custom field values available.

For the moment set the message value to "Match is [node:title]." hit Save, then go an view a match and you'll see the "Match is match1." (or whatever) in the status message area. It's worth coming back to test what's being shown as you progress through building your Rule, just to make sure you have everything right so far and I'll suggest that as we go.

Our First Condition

We need to let Rules know that we want to traverse our referenced entities, but first of all we need to tell Rules that this node is of type match because that makes the custom fields of the match available to Rules and we need the field_home_team reference.

Add condition, Entities: Entity is of bundle. The data selector needs to contain the thing that we want to check is an entity of certain bundle and this is the current node, i.e. we want to check the current node is a match. Although the event is only on a match, just having that it not enough for Rules to make custom fields available.

In the dropdown, select "node (viewed content)", i.e. the current node, click Continue, select "Match" for the Entity Bundle and then Save.

All that has done is made the custom fields available to Rules.

Check new Condition by updating Action

If you now edit the "Show a message on the site" Action, you'll see an expanded list of replacement patterns, that includes things like [node:field-home-team], which we didn't have before.

Update the message to "Match is [node:title]. Home Team is [node:field-home-team]." and go and view a match. Hopefully, that displays the match title and home team title.

More Conditions

We now start to traverse the entity references to get to the team node of the Home Team, so Add condition, Entities: Entity is bundle (again). This time we want to check the node of the current node's home team, so from the dropdown select node:, node:field-home-team and click Continue, select "Team" and then Save.

The field-home-team custom field on match is a node reference to team, so we're effectively saying "check that the match's field_home_team" is a Team. It also, importantly, makes the custom fields of the team now available to Rules.

We do the same to get to the club of the Home Team, so Add condition, Entities: Entity is bundle (again). This time we want to check the node of the current node's home team's club, so from the dropdown select node:, node:field-home-team:, node:field-home-team:field-club and click Continue, select "Club" and then Save.

We now have 3 "Entity is a bundle" conditions, which hopefully makes the traverse clear.

  1. Current node is a match
  2. Current node's home_team is a team
  3. Current node's home_team's club is a club.

Let's test!

Go back to edit your message. There's a heap of replacement patterns now available. Update the message to "Match is [node:title]. Home Team is [node:field-home-team]. Home Club is [node:field_club]" and reload your match node.

Hmm... that doesn't display the club name even though it was listed as a token. Yes, this is a grrr Drupal moment!! The reason for this is that although Rules knows about the relationship, it doesn't have access to the club data. We can get to the match's (home) team because we have the match loaded and the title for the referenced team is available to Rules. [For programmers... This makes sense when you think that when you load a node and dsm($node), the title for any referenced entities are displayed, but any custom fields for the referenced entities are not.]

What we need to do is load the club so we can access its data.

Add a Load Entity Action

Add action, Entities: Fetch entity by id, Value: Node because we want to load a club node. In the Identifier field, switch to data selection as we need to drill down to find the Node Id of the club node we want to load.

That's at node:, node:field-home-team:, node:field-home-team:field-club, node:field-home-team:field-club:nid.

We can only drill down because of the Entity is of bundle Conditions we've added.

The Provided variables section allows you to rename the details of the entity you've just loaded, which makes it easier to spot in the UI. Change the label to "Fetched Club" and the name to "club_fetched".

Once saved, drag the "Fetch entity by id" above "Show a message on the site" and Save. We need to load the Club entity before using the Club's details in the message.

Let's get the club name displaying

Go back to edit your message. Have a look at the replacement patterns - we have a new group of them for "Fetched Club". Have a browse and you'll see "[club-fetched:title]".

Update the message to "Match is [node:title]. Home Team is [node:field-home-team]. Home Club is [club-fetched:title]" and reload your match node. We can now see the Club name.

We still need to display the club admin account's email address. You'll see it's not available as a replacement pattern yet, so we have more to do.

Another grrr moment

We need access to the club admin account's email address, so it makes sense to load that user entity by id. That won't work (yet). Give it a go and you'll see the Identifier Data selector drop down doesn't contain the custom fields for the Club, so we can't get to the uid of the field_club_admin account.

We need to add another Condition. Note, we already have the club checked as an entity of bundle club, but we need something else.

Add condition, Entities: Entity has field node:, node:field-home-team:, node:field-home-team:field-club:, node:field-home-team:field-club and select field value field_admin_user from the dropdown. This means we're checking that the match's, home team's, club has the field club_admin_user.

This makes the club's custom fields available for the drill down.

Final Action

Add action, Entities: Fetch entity by id, Value: User because we want to load a user account. In the Identifier field, switch to data selection as we need to drill down to find the User Id of the club's admin user account we want to load.

That's at node:, node:field-home-team:, node:field-home-team:field-club:, node:field-home-team:field-club:field-admin-user:, node:field-home-team:field-club:field-admin-user:uid.

Note... you may think you'd need to drill down through the already fetched club, but that's not what you want.

Rename the fetched entity "Fetched Club Admin Account" and "club_admin_account_fetched", Save and re-order to bring the fetch above the message action.

Update the message

Edit the message and once again have a look at the replacement patterns. There's another new section called "Fetched Club Admin Account" and under there you'll see [club-admin-account-fetched:mail].

Change the message to "Match is [node:title]. Home Team is [node:field-home-team]. Home Club is [club-fetched:title]. Home team club email is [club-admin-account-fetched:mail]." and test. Hey presto! All is well with the world.

Conclusion

Rules makes some of the currently viewed entities values available (e.g. titles of referenced entities), but for custom fields you need to poke Rules in to making the connections by adding Entity is of bundle conditions for each reference. That allows you to drill deeper, add more Entity is bundle references until you get to the entity you need within the Rules UI.

Sometimes you need to add an Entity has field condition to get to allow you to have an Action to load that entity.

Feel free to update this page, but my brain will have moved on and I may not be able to add too much more.

Help improve this page

Page status: No known problems

You can: