0

We are using the Basic Page content type and it has an Entity Reference field (field_document) that points to the Document (Media bundle), which has a field_document_tag (taxonomy term field). The field_document is not a reference to the taxonomy term, but the Media bundle itself. On the Basic Page we add a Related Documents View at the bottom of the page.

Setup

  • Illustration of relationship

relationship example

Example

example entities

Goal

  • Based on the current page's Linked Document, fetch it's field_document_tag values and return other Basic Pages that have a Linked Document who's Linked Document->field_document_tags match.

How would we use the field value from the current page's field_document to pull other related Basic Pages with a similar Linked Document->field_document_tag values?

Basic Page Fields

  • Linked Document (Entity reference - Media - Document bundle, single value, machine name field_document)

Media - Document Bundle fields

  • Document Tags (taxonomy term - vocabulary = tags, machine name = field_document_tags)
  • Name (text field)
  • File

Here are the view settings we tried, but it does not return other related Basic Pages even when we add any field under Contextual Filters and Relationship:

Format

  • Unformatted list
  • Show: Content | Teaser

Filter Criteria

  • Content: Published = Yes
  • Content: Content type = Basic Page
  • (field_document_tags: media) Media: Document Tags

Contextual Filters

  • content: id -> When the filter value is not available ->provide default value-> content id from url & more -> exclude = enabled
  • Relationships -> field_document: media

Additional relationships added under contextual filters

  • Taxonomy term referenced from field_document_tag: relationship -> field_document: media
  • content using field_document: relationship -> field_document: media

Expected results

  • when i am on page 1, i expect to see none return
  • when on page 2, I expected to see page 4 is returned since the linked document->field_document_tags are the same

Current results

  • All pages are returned
1

The combination of Relationships and Contextual filters to make it work isn't random, it actually follows your requirements just as you've written them, you only need to add them to your Views configuration the way you describe.

How Views types work

You want a list of nodes, that is why you create a Content Views Display. Content Views display information that is stored on nodes. When a node has an Entity reference field, that field stores only the information about what entity that is, usually the entity ID. For example, when referencing files what is stored in the Entity file reference field is the FID. The node (the node's table in the database) doesn't store anything more about that field.

The entity that is being referenced may have fields of its own. These fields are stored with the entity data (in the database they are stored in the related "entity table"). Simply put; nodes have their own tables of data, other entities have their own separate tables of data. The connections between nodes and other entities can be done through small "bridges" that are Entity reference fields that store only the connection between two IDs.

When you create Views of a certain type, you're basically choosing which entity database table to pull information from. To overly simplify for clarity: If you want to list nodes, views set nodes table and you can only show data stored in nodes, if you want to list documents, views set files table and you can only show data stored in files.

How to show referenced data in Views

But what if you want to show more information about the related entities, like in your case? You need to add Relationships towards the related entities. Relationships make other database tables data available into your Views!

Once you add some related entity Relationship to your Views you will see new options appear under Fields and Filters, options related to the referenced entity, options you didn't have before you added the Relationship.

And that is what you need to do to your Content Views. Your content references some Files and you want files data to be available in your content views. If you wanted to list content that shares the same file reference you would then add another Relationship, the "backwards" Relationship pointing towards the content that uses the file field we added the Relationship to, and add a Contextual filter that uses that second "backwards" Relationship.

How to show data that is referenced by referenced data

But in your case, there is one extra layer of connection, and you need to add 2 more Relationships. You're not matching the referenced files, you're matching the taxonomy terms that are referenced from files that are referenced from content:

Page > File > Term < Other Files < Other Pages

Here are the steps for your case:

  1. Create Content Views Block Display listing Page nodes
  2. Add Relationship towards your "Linked Document" field, you can require it since you won't have nodes with empty document field in the results
  3. Add another Relationship Taxonomy term referenced from field_document, it will use the first Relationship automatically, you can require it since that field won't be empty either, so you won't be excluding any nodes you don't need to if you require it

    So far we've been going in the direction from nodes to their referenced files, to terms referenced from those files.

    Now we have all that information in Views, we can start matching "backwards" to get term siblings and file second cousins.

  4. Add the third Relationship Taxonomy term using field_document_tag and make it use the second Relationship. You can require it
  5. Add the fourth Relationship Content using field_document and make it use the third Relationship, you can require it

    This fourth Relationship is pointing to nodes that reference files that refrence terms that are referenced from files that are referenced from nodes listed in this Views.

  6. Now we can add a Contextual ID filter from Content Category, and configure it:
    Make it use the fourth Relationship (the only one available)
    When the filter value is NOT available
    Provide default value
    Content ID from URL
    When the filter value IS available or a default is provided
    Specify validation criteria
    Content
    Basic Page
    Hide View if the argument doesn't validate, or some other options that makes sense to you.
  7. Place the Block on Basic pages, adjust the Node from URL and other Block options.

Remove the current node from the list

The node you're currently viewing will also be listed. To Exclude it add the second Contextual ID filter:
When the filter value is NOT available
Provide default value
Content ID from URL
More
Exlude

  • is the Contextual ID Filter the node's ID field from Content? – usernameabc Apr 17 at 15:46
  • Yes, it's called ID in Drupal 8 and it's in the Content Category. – prkos Apr 17 at 15:56
  • for some reason, when i try to add the third relationship, when i look at the Relationship and it only allows for field_document: media (first relationship). Any reason why the third relationship would not be able to have a relationship set to the second relationship (as described in your answer)? – usernameabc Apr 17 at 17:55
  • No reason why it wouldn't work unless your structure isn't the way you described, or you didn't follow the steps exactly. Maybe you added the wrong Relationship, the second one or the third one? – prkos Apr 17 at 18:07
  • Although i added the relationship for Linked Document, for step 3 i am not able to find taxonomy term from field_document from the available options – usernameabc Apr 17 at 20:44
0

Although @prkos answer lead to my solution, I wanted to add that i had to modify the where clause because it was still not filtering. In order to alter the where clause I had to create a mymodule custom module that had to call hook_views_query_alter() in the mymodule.views_execution.inc file.

It went something like this.

function mymodule_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  foreach($query->where as &$condition_group) {
    foreach($condition_group['conditions'] as &$conditions) {
      /**
       * my_field_name_value is the Linked Document->media.field_document_tag.target_id (taxonomy term id)
       */
      if($condition['field'] == 'my_field_name') {
        $condition = [
          'field' => 'my_field_name',
          'value' => 'my_field_name_value',
          'operator' => '=',
        ];
      }
    }
  }
}

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.