3

I've been banging my head against a wall trying to understand contextual filters for about 6 months now so I thought I'd give up and finally ask. Most recently I read this article on cofiguring contextual filters, which renewed my confusion and frustration on this topic.

Normally in query or procedural languages when you filter something, you specify 2 or 3 things;

  1. The value to filter (e.g. "blonde")
  2. The place to look for the values (e.g. the "hair color" column)
  3. Optionally, the operator to use.

My understanding is that contextual filters only use the "equal to" operator, so I'll leave out 3.

For example, if I wanted to filter a nodes table on all nodes whose value in the title column is equal to the contents of the my_title variable, then in SQL I'd write something like this;

SELECT * FROM nodes WHERE title = @my_title

There's a left hand side (title) and right hand side (my_title). But in the Contextual views section of the view I can only pick the dynamic value to check against (the equivalent of my_title) but where do I pick what I'm actually filtering on (ie. the title column)?

enter image description here

As far as I can tell this is telling the filter to filter on the ID of the current page. Which is fine, but what am I filtering? What are the left and right hand operators to the filtering operation?

2
  • The field you choose for a contextual filter is the "left side" (column). In your example, you've chosen the "Content: ID" filter so nid is always the left. The value it checks for (the right side) is from the inner configuration.
    – sonfd
    Commented Dec 27, 2020 at 3:39
  • @sonfd what's "the inner configuration"? I can't tell from your comment what the left and right hand sides are and where they come from.
    – quant
    Commented Dec 27, 2020 at 6:05

2 Answers 2

6
+100

Generally speaking, a view is used to show data for a list of entities. View filters are used to select (or filter) which entities are handled by the view; contextual filters are used to select the entities basing on the values passed in the URL.

For example, the Files view that comes with Drupal 8 has two pages: one whose path is /admin/content/files and one whose path is /admin/content/files/usage/%.

screenshot

The second page shows data (the entity label and the entity type for the entity containing a reference to the file; the module managing the file relationship; the number of times the file is used by the entity) for the file whose ID is passed in the view path.

screenshot

When I visit /admin/content/files/usage/3 on the test site I created, the view shows the following data.

screenshot

On /admin/content/files/usage/2, the view shows the following data.

screenshot

Using as another example a default view that is already enabled on /admin/structure/views, the Taxonomy term view has a page shown on /taxonomy/term/% which uses the Content: Has taxonomy term ID contextual filter.

screenshot

It shows all the nodes using the taxonomy term whose ID is passed in the URL. In the test site I am using, /taxonomy/term/1 shows all the nodes using the taxonomy term whose ID is 1 (the test taxonomy term), while /taxonomy/term/2 shows all the nodes using the taxonomy term whose ID is 2 (the view taxonomy term).

screenshot

screenshot

Contextual filters are still filters, as they select (or filter) the entities from which the data is taken. The difference is that their values are passed from the view URL, not from a form like the filters set in the Filter criteria section.

The number of entities from which the data is taken and what entities are handled by the contextual filter is hard-coded in the class implementing the contextual filter: Content: Has taxonomy term ID selects all the nodes using the taxonomy term whose ID is equal to the value passed in the URL, which could be zero or more than one node, while Content: ID selects only the node whose ID is passed in the URL; User: Created selects all the user accounts that have been created at the time passed in the URL. The category of the contextual filter (another value set by the the class implementing the contextual filter), which is shown in the contextual filter name, helps to understand which entities a contextual filter selects: Content: Has taxonomy term ID and Content: ID select nodes, while User: Created selects users.

10
  • How does views know what to filter the entities on though? In your example you've told views that "File ID" is a value it should pull out from the context, but where are you telling views what to do with it? Is it just assumed that the view should show you nodes with IDs matching the context value?
    – quant
    Commented Dec 26, 2020 at 12:46
  • No, the view isn't showing the nodes with an ID matching the passed value. The contextual filter is File: File ID, not Content: ID. A view is always showing data for specific entities; that is not something you need to tell the view. You just tell the view which entities to show, when you select the type of view, and when you add the view filters.
    – avpaderno
    Commented Dec 26, 2020 at 12:56
  • 1
    There are many contextual filters, each of them with a specific functionality. File: File ID is for identifiers of the File entity, Content: ID is for the node identifiers, Content: Has taxonomy term ID is for the nodes using the taxonomy term whose ID is passed on the URL. What appears in a URL is just a string. A view needs to know what that string is; that is why there are different contextual filters.
    – avpaderno
    Commented Dec 27, 2020 at 8:50
  • 1
    The purpose of contextual filters is still to display a subset of all the available entities. If you have a view block shown in node/% which uses a Content: ID contextual filter, that contextual filter is telling the view to show data from a single node, whose ID is passed in the URL; in the default view on /taxonomy/term/%, the Content: Has taxonomy term ID contextual filter it uses is telling the view to show data from all the nodes using the taxonomy term whose ID is passed in the URL.
    – avpaderno
    Commented Dec 27, 2020 at 9:23
  • 1
    How many entities are shown is decided from the contextual filter. As I said, the Content: Has taxonomy term ID contextual filter shows data from one or more nodes, while the Content: ID contextual filter shows data only from a single node. The Content: Authored by contextual filter shows data from all the nodes authored by a user.
    – avpaderno
    Commented Dec 27, 2020 at 9:26
5

In Views, if you go into the Settings (/admin/structure/views/settings), you can check the box Show the SQL query to see the magic.

I made a very simple view of content. Here's the SQL query:

SELECT node_field_data.created AS node_field_data_created, node_field_data.nid AS nid
FROM
{node_field_data} node_field_data
WHERE node_field_data.status = '1'
ORDER BY node_field_data_created DESC
LIMIT 11 OFFSET 0

Next I added a contextual filter for Content: ID and accepted the defaults.

In this case, the SQL query does not change. This is because "Display all results for the specified field" is the default for When the filter value is NOT available in the contextual filter settings.

The query only changes if the contextual filter is provided with a value. (To provide a dummy value for testing purposes, you can input a value in Preview with contextual filters.)

Here, I tested by inputting 1 for Preview with contextual filters, which gave me this query:

SELECT node_field_data.created AS node_field_data_created, node_field_data.nid AS nid
FROM
{node_field_data} node_field_data
WHERE ((node_field_data.nid = '1')) AND (node_field_data.status = '1')
ORDER BY node_field_data_created DESC
LIMIT 11 OFFSET 0

"Contextual filters" is a hard-to-understand name, but back in Drupal 6 (as long as I'm remembering right) this was called "Arguments", which makes more sense to me.

4
  • 2
    That "Show the SQL query" setting is super helpful, thanks! In your example, how does views decide to compare "1" to the value of "nid"? The "Content: ID" filter presumably tells views where to get the context value from (which you've set to 1 manually in your example), but where does it decide to compare it to nid?
    – quant
    Commented Dec 26, 2020 at 12:32
  • how does views decide to compare "1" to the value of "nid"? You configure this in the URL path (of the view, with placeholders %) and in the contextual filter settings for the view. You set this config to match what you want to happen; for an example, look at the core taxonomy terms view: /admin/structure/views/view_taxonomy_term. Commented Dec 26, 2020 at 13:12
  • I understand that the URL provides the value for the ID (in this example 1) but where is it that views knows to compare that value to the node ID for the purpose of filtering? Is that just baked into the filter somehow?
    – quant
    Commented Dec 27, 2020 at 9:13
  • In this case, I added a Content ID filter, which is set to operate on the node ID. That's just how the filter is defined. Of course it's possible to write your own contextual filter plugin if you want to do something more complicated. You can also use multiple placeholders in the URL to use multiple contextual filters. In that case, you have to set the order in the view for which filter is which placeholder. Commented Dec 27, 2020 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.