5

I try to implement hook_views_query_alter() in Drupal 8. I found a hint, that it has to be in my_module.views_execution.inc. I tried it, but the hook never gets called.

function mymodulename_views_query_alter(&$view, &$query)
{
    var_dump('foo');die;
}

Do I have to register the *.inc file anywhere? Do you have a documentation source on this topic?

4 Answers 4

4

Hooks need to be implemented in the .module file.

Just move the hook to your .module file, rebuild the cache, and Drupal will pick it up.

You could of course require a file that contains your hooks, as long as when that file is parsed, the hook functions are available in it.

You can read a bit more about hooks in the docs.

6
  • I tried that before and it didn't work. This comment pointed me to the *.inc file
    – tobyte
    Commented May 24, 2016 at 14:42
  • Always works for me - make sure your module is enabled, everything's named correctly, etc
    – Clive
    Commented May 24, 2016 at 14:43
  • The link in my initial post points to the Drupal 8 API, so this hook should work in 8 or am I wrong?
    – tobyte
    Commented May 24, 2016 at 14:48
  • Yeah sorry, my google habits need to change now that views hooks are out of contrib. The hook does exist, and it'll be invoked if it's implemented correctly, otherwise this core test would fail
    – Clive
    Commented May 24, 2016 at 14:50
  • Ok, it works now with the hook in the *.module file. I did set the hook parameter as reference, which is wrong in drupal 8. Thanks a lot!
    – tobyte
    Commented May 24, 2016 at 14:59
8

In Drupal 8, best practice is to use hook_views_query_alter() in MYMODULE.views_execution.inc file. If instead it is placed in MYMODULE.views.inc, it will be executed only when rebuilding the views cache, causing your view to function properly once and then not subsequently.

MYMODULE.views_execution.inc file should have this structure...

use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\query\QueryPluginBase;

/**
 * Implements hook_views_query_alter().
 */
function MYMODULE_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {

  // Only for my_view view.
  if ($view->id() == 'my_view') {
    // some action
  }

}

Ref: views_test_data.views_execution.inc

1
  • That final reference is applied to their core tests, it doesn't mean we need to create that specific file for our module. That hook should be placed in MY_MODULE.module file
    – DarkteK
    Commented Feb 11, 2021 at 15:37
3

creating hook_views_query_alter in d8 is not same as d7, ofcourse.. after many try, i managed to get this one.. hope this helps.. its for different GET parameter ..

function MYMODULE_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
if ( ($view->id() ==  'MY_VIEW' && $view->current_display == 'page_1')) {
  $allowed_filters = ['language'=>['table'=>'node__field_v_language','condition_field'=>'field_v_language_value','operator'=>'IN'],
    'country'=>['table'=>'node__field_v_country','condition_field'=>'field_v_country_value','operator'=>'IN'],
    'city'=>['table'=>'node__field_v_locations','condition_field'=>'field_v_locations_target_id','operator'=>'IN'],
    'theme'=>['table'=>'node__field_v_themes','condition_field'=>'field_v_themes_target_id','operator'=>'IN'],
    'tag'=>['table'=>'node__field_v_tags','condition_field'=>'field_v_tags_target_id','operator'=>'IN'],
    'chId'=>['table'=>'node__field_v_ch_id','condition_field'=>'field_v_ch_id_value','operator'=>'IN'],
    'publishedBefore'=>['table'=>'node__field_v_published','condition_field'=>'field_v_published_value','operator'=>'>'],
    'publishedAfter'=>['table'=>'node__field_v_published','condition_field'=>'field_v_published_value','operator'=>'$record){
      $alias = $q.'_als';
      $condition_field = $alias.'.'.$record['condition_field'];
      $configuration = [
        'type'       => 'LEFT',
        'table'      => $record['table'],
        'field'      => 'entity_id',
        'left_table' => 'node_field_data',
        'left_field' => 'nid',
        'operator'   => '=',
      ];

      $join = \Drupal\views\Views::pluginManager('join')
        ->createInstance('standard', $configuration);
      $rel = $query->addRelationship($alias, $join, 'node_field_data');
      $query->addTable('node__field_v_language', $rel, $join, $alias);
      $query->addWhere('', $condition_field, [$_GET[$q]], $record['operator']);
    }
  }
}
0

The following code searches the standard body field for a string based on a URL Path specified in Views without the Search API module. In my case, the search string was the 5th element in the path. Not sure it's necessary, but it would be good to escape the URL element to prevent SQL injection. Here is a link to the updated Drupal documentation for the hook. You will want to include this in a .module file. The view this function was attached to was a REST export for a node-based content type which included several fields. You will want to replace the text in all caps.

/**
 * Implements hook_views_query_alter().
 */
function MYMODULE_views_query_alter(ViewExecutable $view, Drupal\views\Plugin\views\query\QueryPluginBase $query) {
  if ($view->id() ==  'MY_VIEW_ID') {
    $configuration = [
      'type'       => 'LEFT',
      'table'      => 'node__body',
      'field'      => 'entity_id',
      'left_table' => 'node_field_data',
      'left_field' => 'nid',
      'operator'   => '=',
    ];
    $join = \Drupal\views\Views::pluginManager('join')->createInstance('standard', $configuration);
    $rel = $query->addRelationship('my_alias', $join, 'node__body');
    $query->addTable('node__body', $rel, $join, 'my_alias');
    $current_path = \Drupal::service('path.current')->getPath();
    $path_args = explode('/', $current_path);
    $value = $path_args[5];
    $query->addWhere('0', 'my_alias.body_value', $value, 'REGEXP');
  }
}
1

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.