1

I am developing a Drupal 8 website where I have a block view displayed for certain content types that shows related information from other content types. I need to dynamically limit query results based on the moderation state of the node being visited (as opposed to the content in the view). My plan was to grab the node's moderation state from the page context and use that to limit the results of the view. However, the setLimit function seems to have no effect on query results:

function myModule_views_pre_execute(ViewExecutable $view) {
  // Only for my_view view.
  if ($view->id() == 'my_view') {
    $list_node = Drupal::request()->attributes->get('node');
    if($list_node->moderation_state->value == "approved"){

    }else{
      dpm("node is not approved, setting limit to 0");
      $view->query->setLimit(0);
    }   
  }

UPDATE

I played around with trying different things in different hooks, inspecting the actual query generated via the view editing interface, as this exposes the "LIMIT #" expression. I learned 2 main things from that process:

  1. Things can and will edit the query in other hooks. I found that putting the setLimit in hook_views_query_alter got overridden by some other module, and by the time hook_views_pre_execute came around, it would be changed from what I set it to earlier. However setting it in pre_execute is working fine.
  2. Amazingly, calling setLimit(0) removes the LIMIT expression from the query entirely! However, any other value seems to work fine.

Is this expected behavior? Does Drupal prohibit setting the limit for a query to 0? Or should I be logging an issue somewhere?

  • Might "pre_execute" be too late in the process? I wouldn't think so myself, but have you tried putting your code into a hook_views_query_alter instead? – beltouche Sep 11 at 1:56
  • I started out trying hook_views_query_alter, eventually moving to hook_views_pre_execute as I thought maybe something else was editing the query after me. However this did not work either. The only way I've found to mask the results is by doing $view->result = [] in hook_views_post_execute, however I would like to avoid this option as the query may be expensive and there is no need to run it if it is being masked. – unanswerableQuestions Sep 11 at 4:05
0

No idea why setLimit(0) doesn't work as expected, but an alternative is to act as though you had limited the results to 0. When you add a contextual filter to a view, one of the options for When the filter value is NOT available is to Display contents of "No results found". This seems to be handled by ArgumentPluginBase::defaultEmpty(), which looks like

public function defaultEmpty() {
  // We return with no query; this will force the empty text.
  $this->view->built = TRUE;
  $this->view->executed = TRUE;
  $this->view->result = [];
  return FALSE;
}

If you drop this snippet into hook_views_query_alter() it appears to work exactly the same! I'd wager that you could drop it into any of the views hooks, actually, and it would have the same effect.

EDIT: Whoops, forgot to say you'd want to replace $this->view with $view if you're inside of the hooks.

| improve this answer | |
  • I tried to mark this as the answer (I cannot as I don't have enough reputation) but this seems to work! Also I am hoping this means the query is not being executed at all since it is in query_alter (in my Sept 11 comment on my question I am setting results = [] as a workaround, but in post_execute meaning the query had already run). Still odd that setLimit(0) behaves like it does. AFAIK this is a very common way to efficiently mask a query as DBMS's like mysql will optimize this away and not run the query, and it seems odd that a limit of 0 yields full results. – unanswerableQuestions Sep 14 at 17:49
  • Maybe a mod will drop in and save the day on marking as the answer, haha. If this is added in query_alter() I don't think the query would run, but to be sure you could drop it into pre_view() or something else earlier in the pipeline. Agreed that the setLimit() issue is odd. I tried to dig in a bit but couldn't work out exactly how the views query is actually built/run. This very well might be a bug and would be worth opening a ticket in the core issue queue for. – Mrweiner Sep 14 at 18:10

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.