If you're not already familiar with the subject, check out Joel Steidl's intro to Entity References.
Drupal has some powerful tools for creating and managing complex content relationships. Views relationships using Entity References across more than one content type can be used to establish multi-tiered content relationships. The results can be great, but setting up Entity References across content types with Views can be... well, complicated.
We recently added new functionality to a client’s site that involved Entity References to group content and display it dynamically. The project included a sidebar of links to all the related content that spanned three content types. This wasn’t really possible as a menu block because the links needed to contain some of the actual content. I also considered doing all of this in code but that could mean running a number of extra database queries on every page load. With Views, all of that can be easily cached.
When it comes to relationships in Views, creating a relationship from one content type to another, the number of permutations is usually small enough that it only takes a few minutes to try all of them until you get the desired output. When you try to relate content to content to content, the permutations of configuration options in Views gets a little unwieldy. And, I create and/or modify Views with complicated relationships so infrequently that I never remember how to do it. Trying to debug the query built by Views looks even scarier.
Clayton Dewey was able to assist me, and we got relationships working even when needing to chain five different nodes together through their reference fields.
Here’s one portion of the sidebar:
Rather than go through the specific case with our client, I’ve setup a very general one.
Content Type A has an entity reference field to Content Type B. Content Type B has an entity reference field to Content Type C:
Here’s how that content relates.
When trying to set this up in views, relationship descriptions for entity reference fields don’t help. Is it A bridge to the Content entity that is referencing Content via field_other_content
or is it A bridge to the Content entity that is referenced via field_content?
A bridge to the Content entity that is referenced via field_content means your entity is referenced by another via an entity reference field. A bridge to the Content entity that is referencing Content via field_other_content means your entity has the reference field. This will become more clear as we go through our example.
Let’s say we’re on the page for node 4, of Content Type C, and on this page we want to list all the related nodes that are of Content Type C. To do that, you need the B node referencing your C node. Then the A node referencing the B node. Next all the B nodes referenced by the A node. Finally, all C nodes referenced by the B nodes. Phew!
To do this with Views, we start with a contextual filter of the current node.
Next we setup the layers of relationships. First from that C node to the B node. Thus we’re using an entity reference relationship called A bridge to the Content entity that is referencing Content via field_c.
Each B node has an entity reference field to its C nodes. To make things easier to read we’re setting the Identifier and the Administrative title.
To get the A node we need another relationship for the entity reference field in A nodes I’ve named field_b. A bridge to the Content entity that is referencing Content via field_b. Again, the content this relationship gives you is doing the referencing. And we’re connecting it to the previous relationship.
Now we want to go back down the chain and get all B nodes. So, now we’ve got content that is referenced. So, we use A bridge to the Content entity that is referenced via field_b. Again, include the previous relationship.
To get all C nodes it’s done the same way.
Finally, to output the titles of all those C nodes, we use the correct relationship for that field. For this Views preview we use the nid of C 4, and get the following output of node titles:
You’ll want to turn on caching for the database queries and if possible, for the rendered HTML in query settings.
See, that wasn’t so hard, was it?