I have a block display of a View embedded in a Panels page which receives its contextual filters via query parameters to the page. See first screenshot.

Screenshot of contextual filter settings

I also chose to allow multiple values for this contextual filter. And in this case, the filter is in glossary mode (filtering on the first letter of the node title), but that is less important. See the second screenshot.

Screenshot of View contextual filter settings

The first problem I noticed is that while filtering by a single value (?test[0]=0) is working fine, trying to filter by multiple values (?test[0]=0&test[1]=1) was throwing the following exception:

'Placeholders must have a trailing [] if they are to be expanded with an array of values.'

After some digging, I found #2401615, which dictates database placeholders for queries must end in [] if they are for an array of values, as they are in this case since I'm trying to apply an OR condition for multiple values on a filter. Ultimately, I found that the views handler for string arguments was not properly adding [] to the database placeholder if the arguments are an array of values. I was able to resolve this issue and thus eliminate the exception thrown by Drupal. I will attach a patch for this issue in my next comment.

However, even once that issue was resolved, multiple values for the contextual filter are still not working. The replacements for the placeholder are not making it into the final query, resulting in an empty IN condition:

SELECT node_field_data.created AS node_field_data_created, node_field_data.nid AS nid
FROM 
{node_field_data} node_field_data
WHERE (( (SUBSTRING(node_field_data.title, 1, 1) IN()) )AND(( (node_field_data.status = '1') AND (node_field_data.type IN  ('lab_test')) )))
ORDER BY node_field_data_created DESC

If I debug the condition for this query clause from the Condition::compile method, it looks like this:

Screenshot of debugging information for query condition

I dug around more into the core database layer trying to figure this out, but I'm unable to determine if this is the correct structure for this query condition and/or why the replacement values are not making into the final query output. Any advice or pointers would be appreciated.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mrkdboyd created an issue. See original summary.

mrkdboyd’s picture

Issue summary: View changes
mrkdboyd’s picture

Issue summary: View changes
mrkdboyd’s picture

Here is the patch to add [] to the database placeholder when there are multiple query parameters for a contextual filter.

mrkdboyd’s picture

Issue summary: View changes
Lendude’s picture

Status: Active » Needs review

@mrkdboyd thanks for the report and the patch.

View embedded in a Panels page which receives its contextual filters via query parameters to the page

It would really help to get some steps to reproduce with just Drupal core. If this is a bug then we would also need a test to reproduce this.

Setting to needs review to trigger the testbot on the patch.

Lendude’s picture

Version: 8.2.8 » 8.3.x-dev
Status: Needs review » Needs work

Ok that didn't trigger anything :)

Back to needs work for tests.

mrkdboyd’s picture

I can confirm that this is happening with just a Views page display as well, so no Panels involved. If you create a View with a page display matching the configuration in the screenshots above and try to use multiple query parameters ?test[0]=0&test[1]=1 as contextual filters to the view, you should see the Exception I noted above being thrown.

mrkdboyd’s picture

Status: Needs work » Active
Manuel Garcia’s picture

Issue tags: +Needs tests
Manuel Garcia’s picture

The test for the file we are patching is core/modules/views/tests/src/Functional/Handler/ArgumentStringTest.php,

However I can see there is this test which looks to me like it handles this kind of situation for all default arguments:
core/modules/views/tests/src/Unit/Plugin/argument_default/QueryParameterTest.php.

So I'm not sure where we should be expanding the test coverage...

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Pancho’s picture

Status: Active » Needs review

I can confirm following InvalidArgumentException:

"Placeholders must have a trailing [] if they are to be expanded with an array of values."

for both 8.2.8 and 8.7.x in views with:

  • a contextual filter on a string field
  • default value from query parameter
  • "Glossary mode" enabled
  • multiple values allowed
  • multiple values given, either via query parameter (/admin/content?test[0]=T&test[1]=B), or via regular parameter (/admin/content/T+B) or in the View Preview

Patch #4 still applies and correctly fixes this bug. Tests are definitely needed.

TuWebO’s picture

Title: Views - Contextual filter from query parameter not working with multiple values » Views - Contextual filter from query parameter or regular parameter not working with multiple values

As per comment in #15, changing the title to better match the issue.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

diegoluisr’s picture

I solve this issue for my project as a workaround using "hook_views_query_alter()", this is not a solution for everybody but I hope some people find inspiration on it.

I have a view of bars in the city (cocktails related website) because the number of nodes is not a big one I need to group them into 3 characters sets ABC, DEF, GHI, JKL, MNO, PQR, STU, VWX, YZ, and I have a special group for numerical titles NUM, my contextual filter is set to "Content: Title"

Other configuration:
- default value from the query parameter 'ALL'
- "Glossary mode" enabled
- multiple values allowed
- single value is given (not using "+" or ",")

this is my code solution, in a custom module I had added a function that implements "hook_views_query_alter()"

/**
 * Implementation of hook_views_query_alter()
 * @param type $view
 * @param type $query
 */
function mymodule_views_query_alter(ViewExecutable $view, QueryPluginBase &$query) {

  // Checking for the proper view id.
  if(in_array($view->id(), ['bars'])) {

    // getting the argument from a URL path like https://mycoctailwebsite.com/bars/abc
    // trasforming it to uppercase
    $argument = mb_strtoupper($view->args[0]);
    if ($argument != 'ALL') {

      if ($argument == 'NUM') {
        $argument = '1234567890';
      }
      // Splitting the argument string as an array.
      $chars = str_split($argument);
      // forcing OR query
      $query->where[0]['type'] = 'OR';
      $condition = $query->where[0]['conditions'][0];
      // forcing unset over where condition in position "0"
      unset($condition['value'][':node_field_data_title']);

      // Cleaning conditions array.
      $query->where[0]['conditions'] = [];

      // Rebuilding conditions in where clause with each character in the array.
      foreach ($chars as $key => $char) {
        $query->where[0]['conditions'][$key] = $condition;
        $query->where[0]['conditions'][$key]['field'] .= '_' . $key;
        $query->where[0]['conditions'][$key]['value'][':node_field_data_title_' . $key] = $char;
      }
    }
  }
}

I came to this solution by analyzing the where clause. This below block shows a single character query.

array:2 [▼
  1 => array:3 [▼
    "conditions" => array:2 [▼
      0 => array:3 [▼
        "field" => "node_field_data.status"
        "value" => 1
        "operator" => "="
      ]
      1 => array:3 [▼
        "field" => "node_field_data.type"
        "value" => array:1 [▼
          0 => "place"
        ]
        "operator" => "in"
      ]
    ]
    "args" => []
    "type" => "AND"
  ]
  0 => array:3 [▼
    "conditions" => array:1 [▼
      0 => array:3 [▼
        "field" => "SUBSTRING(node_field_data.title, 1, 1) = :node_field_data_title"
        "value" => array:1 [▼
          ":node_field_data_title" => "J"
        ]
        "operator" => "formula"
      ]
    ]
    "args" => []
    "type" => "AND"
  ]
]

This second block shows the query using 3 characters "JKL"

array:2 [▼
  1 => array:3 [▼
    "conditions" => array:2 [▼
      0 => array:3 [▼
        "field" => "node_field_data.status"
        "value" => 1
        "operator" => "="
      ]
      1 => array:3 [▼
        "field" => "node_field_data.type"
        "value" => array:1 [▼
          0 => "place"
        ]
        "operator" => "in"
      ]
    ]
    "args" => []
    "type" => "AND"
  ]
  0 => array:3 [▼
    "conditions" => array:1 [▼
      0 => array:3 [▼
        "field" => "SUBSTRING(node_field_data.title, 1, 1) = :node_field_data_title"
        "value" => array:1 [▼
          ":node_field_data_title" => "JKL"
        ]
        "operator" => "formula"
      ]
    ]
    "args" => []
    "type" => "AND"
  ]
]

This third block shows the view query altered by my code.

array:2 [▼
  1 => array:3 [▼
    "conditions" => array:2 [▼
      0 => array:3 [▼
        "field" => "node_field_data.status"
        "value" => 1
        "operator" => "="
      ]
      1 => array:3 [▼
        "field" => "node_field_data.type"
        "value" => array:1 [▼
          0 => "place"
        ]
        "operator" => "in"
      ]
    ]
    "args" => []
    "type" => "AND"
  ]
  0 => array:3 [▼
    "conditions" => array:3 [▼
      0 => array:3 [▼
        "field" => "SUBSTRING(node_field_data.title, 1, 1) = :node_field_data_title_0"
        "value" => array:1 [▼
          ":node_field_data_title_0" => "M"
        ]
        "operator" => "formula"
      ]
      1 => array:3 [▼
        "field" => "SUBSTRING(node_field_data.title, 1, 1) = :node_field_data_title_1"
        "value" => array:1 [▼
          ":node_field_data_title_1" => "N"
        ]
        "operator" => "formula"
      ]
      2 => array:3 [▼
        "field" => "SUBSTRING(node_field_data.title, 1, 1) = :node_field_data_title_2"
        "value" => array:1 [▼
          ":node_field_data_title_2" => "O"
        ]
        "operator" => "formula"
      ]
    ]
    "args" => []
    "type" => "OR"
  ]
]

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev
kristiaanvandeneynde’s picture

I can confirm this bug is still present. A very easy way to test this is to write a ViewsArgumentDefault plugin that returns multiple values. Set up any view that takes a contextual filter on a string value, then feed it a dummy ViewsArgumentDefault that returns "foo,bar,baz" and see the crash in all its glory :)

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

thomasmurphy’s picture

Status: Needs review » Needs work

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.