8

I want to alter contextual filter before executing the sql query of views. Is there any way to get current contextual filter in hook_views_query_alter or hook_views_pre_execute? Or which is the better hook to alter contextual filter for views?

2
  • Do you want to edit the configuration of the contextual filter or the value that is coming in?
    – rooby
    Dec 9, 2014 at 14:13
  • @rooby I want to edit the value of the contextual filter.
    – stevey
    Dec 9, 2014 at 14:15

3 Answers 3

12

The contextual filters are in $view->args.

$view->args is an array of arguments (contextual filters).

So you can do things like this:

/**
 * Implements hook_views_pre_execute().
 */
function MODULENAME_views_pre_execute(&$view) {
  // Set the first contextual filter value.
  $view->args[0] = 1;
}
3

Using hook_views_pre_view() may be more reliable than hook_views_pre_execute(). Based on https://www.drupal.org/node/2438623, hook_views_pre_execute() is too late in the query build processs. In contrast, https://codedrop.com.au/blog/programatically-altering-contextual-filters-views-drupal-7 provides an example of hook_views_pre_view().

For my own situation, the below code works:

/**
 * Implements hook_views_pre_view().
 */
function mymodule_views_pre_view(&$view, &$display_id, &$args) {
  if ($view->name == 'VIEWNAME' && $view->current_display == 'DISPLAYNAME') {
    $url = arg();
    if (isset($url[1])) {
      // YOU MIGHT HAVE TO ADJUST $url[1] TO MATCH YOUR URL ALIAS.
      if ($normal_path = drupal_get_normal_path($url[1])) {
        $path_args = explode('/', $normal_path);
      }
    }
    if (isset($path_args[1])) {
      $view->args[0] = $path_args[1];
    }
  }
}
2
  • 1
    Note that the above code determines the contextual filter arguments from the URL because hook_views_pre_view() is too early to find them in $args or $view->args as usual. You can however fill $view->args as demonstrated, and Drupal will not overwrite it later.
    – tanius
    Jan 10, 2017 at 15:19
  • I don't know that using hook_views_pre_view() is a better choice - see the views API at api.drupal.org/api/views/views.api.php/function/… "Allows altering a view at the very beginning of processing a preview. This hook is only triggered when the one of the following are invoked: $view->execute_display() $view->preview() ... Likely, hook_views_pre_build() or hook_views_pre_execute() are much better choices for most use cases since they are always invoked, not just when previewing a display."
    – kbrinner
    Jan 10, 2019 at 17:09
0

I think the best option is use hook_views_pre_execute

Below I share a code that alters the contextual filter by a field that comes from a node:

function hooks_views_pre_build(\Drupal\views\ViewExecutable $view) {
  // Get the node entity by the URL parameter
  $node = \Drupal::routeMatch()->getParameter('node');

  if ($view->id() == 'ViewName' && $view->getDisplay()->display['id'] == 'DisplayName') {
    $filterValue = $node->get('field')->first()->get('entity')->getTarget()->getValue();
    $view->args[0] = $filterValue;
  }
}

And that's it!

Your Answer

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

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