【问题标题】:How can I limit a query's results to 0 in Drupal 8's hook_views_pre_execute?如何在 Drupal 8 的 hook_views_pre_execute 中将查询结果限制为 0?
【发布时间】:2020-12-29 12:00:31
【问题描述】:

我正在开发一个 Drupal 8 网站,在该网站上,我为某些内容类型显示了一个块视图,其中显示了来自其他内容类型的相关信息。我需要根据正在访问的节点的审核状态(而不是视图中的内容)动态限制查询结果。我的计划是从页面上下文中获取节点的审核状态,并使用它来限制视图的结果。但是,setLimit 函数似乎对查询结果没有影响:

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);
    }   
  }

几年前我见过similar questions,但答案似乎指向改变寻呼机而不是查询......这似乎很奇怪,寻呼机会以某种方式直接绑定到 sql 查询本身并且不仅仅是结果的显示或编组。 setLimit 函数不是简单地编辑最终 sql 查询的“LIMIT”部分吗?还是在我的代码运行后寻呼机实际上改变了限制?非常感谢!

2020 年 11 月 9 日更新

我尝试在不同的钩子中尝试不同的东西,检查通过视图编辑界面生成的实际查询,因为这会暴露“LIMIT #”表达式。我从这个过程中学到了两个主要的东西:

  1. 可以并且将会在其他挂钩中编辑查询。我发现将 setLimit 放入 hook_views_query_alter 会被其他模块覆盖,而当 hook_views_pre_execute 出现时,它会与我之前设置的有所不同。但是将其设置为 pre_execute 可以正常工作。
  2. 令人惊讶的是,调用 setLimit(0)从查询中完全删除了 LIMIT 表达式!但是,任何其他值似乎都可以正常工作。

这是预期的行为吗? Drupal 是否禁止将查询的限制设置为 0?还是我应该在某处记录问题?

【问题讨论】:

    标签: php drupal-8 drupal-modules drupal-views


    【解决方案1】:

    您应该改用hook_views_query_alter

    function myModule_views_pre_execute(ViewExecutable $view, QueryPluginBase $query) {
      // 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");
          $query->setLimit(0);
        }   
      }
    
    

    【讨论】:

    • 我开始尝试 hook_views_query_alter,最终转到hook_views_pre_execute,因为我认为可能有其他东西在我之后编辑查询。然而,这也不起作用。我发现屏蔽结果的唯一方法是在hook_views_post_execute 中执行$view->result = [],但是我想避免使用此选项,因为查询可能很昂贵,如果它被屏蔽则不需要运行它
    • 您应该首先尝试Configure Views for debugging 并显示实际的SQL 查询。这样你最好检查结果查询。
    • 如果确实有其他模块在你之后修改了视图查询,请尝试通过setting a larger module weight延迟你的钩子。
    • 啊,好主意。事实证明,是的,在我的 query_alter 被调用后,有些东西正在编辑查询。但是,如果我将 setLimit 放入 pre_execute 中,似乎发生了变化,但是发生了一些非常有趣的事情 - 当我执行 setLimit(0) 时,它会从查询中完全删除“LIMIT”表达式!但是,如果我执行setLimit(1),我可以在查询中看到“LIMIT 1”表达式,它会限制结果。这是一个错误,还是预期的行为?实际上,我希望查询根本不运行,有没有更好的方法来实现这一点?
    • 这可能是设计使然。我找不到关于它的适当文档,但我猜QueryInterface::range() 使用正确的实现将 0 视为 NULL。这是可以理解的,因为如果人们想要 0 个项目,他们最好根本不进行查询。也许您可以添加一个始终为 FALSE 的条件,而不是 setLimit()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多