我可以强制WP_QUERY不返回任何结果吗?

时间:2014-04-08 作者:somebodysomewhere

我正在开发一个具有搜索功能的网站,该功能允许用户通过大量的post meta进行搜索。有一种特定的搜索模式,我想强制不返回任何结果。从技术上讲,WP\\u查询将在数据库中查找结果,但我希望以某种方式覆盖它,以强制它不返回任何结果来触发if( $example->have_posts() ) 失败。

是否有某种类型的参数可以传递给WP\\u Query,如\'force_no_results\' => true 那会迫使它不返回结果吗?

3 个回复
最合适的回答,由SO网友:David Labbe 整理而成

尝试

\'post__in\' => array(0)
简单而中肯。

更新时间:

\'post__in\' => empty( $include ) ? [ 0 ] : $include,

SO网友:Rarst

奇怪的是,没有干净/明确的短路方式WP_Query.

如果是主查询,您可能会解决一些问题WP->parse_request(), 似乎是最近的(3.5)do_parse_request 在那里过滤。

但对于WP_Query 本身的恶意攻击通常是有序的,例如通过添加AND 1=0 通过posts_where 过滤器等。

SO网友:gmazzap

将查询参数设置为不存在值的问题有2个:

查询将运行,因此即使您已经知道不会有结果,也需要付出一些性能代价\'posts_*\' 过滤器挂钩(\'posts_where\', \'post_join\', 等等……)这将对查询起作用,因此您永远无法确保即使设置unexistent param查询也不会返回任何结果,这是一个简单的OR 筛选器返回的子句使返回某物sure 查询不返回结果,也不存在(或非常小的)性能问题。

要触发该例程,您可以使用每个方法,从技术上讲,您可以将任何参数传递给WP_Query, 不存在的事件参数。

如果你喜欢\'force_no_results\' => true, 您可以这样使用它:

$a = new WP_Query( array( \'s\' => \'foo\', \'force_no_results\' => true ) );
并添加在上运行的回调\'pre_get_posts\' 做艰苦的工作:

add_action( \'pre_get_posts\', function( $q ) {
  if (array_key_exists(\'force_no_results\', $q->query) && $q->query[\'force_no_results\']) {
    $q->query = $q->query_vars = array();
    $added = array();
    $filters = array(
      \'where\', \'where_paged\', \'join\', \'join_paged\', \'groupby\', \'orderby\', \'distinct\',
      \'limits\', \'fields\', \'request\', \'clauses\', \'where_request\', \'groupby_request\',
      \'join_request\', \'orderby_request\', \'distinct_request\',\'fields_request\',
      \'limits_request\', \'clauses_request\'
    );
    // remove all possible interfering filter and save for later restore
    foreach ( $filters as $f ) {
      if ( isset($GLOBALS[\'wp_filter\']["posts_{$f}"]) ) {
        $added["posts_{$f}"] = $GLOBALS[\'wp_filter\']["posts_{$f}"];
        unset($GLOBALS[\'wp_filter\']["posts_{$f}"]);
      }
    }
    // be sure filters are not suppressed
    $q->set( \'suppress_filters\', FALSE );
    $done = 0;
    // use a filter to return a non-sense request
    add_filter(\'posts_request\', function( $r ) use( &$done ) {
      if ( $done === 0 ) { $done = 1;
        $r = "SELECT ID FROM {$GLOBALS[\'wpdb\']->posts} WHERE 0 = 1";
      }
      return $r;
    });
    // restore any filter that was added and we removed
    add_filter(\'posts_results\', function( $posts ) use( &$done, $added ) {
      if ( $done === 1 ) { $done = 2;
        foreach ( $added as $hook => $filters ) {
          $GLOBALS[\'wp_filter\'][$hook] = $filters;
        }
      }
      return $posts;
    });
  }
}, PHP_INT_MAX );
此代码的作用是在\'pre_get_posts\' 尽可能晚。如果查询中存在参数“force\\u no\\u results”,则:

首先删除所有可能干扰查询的筛选器,并将其存储在助手数组中。确保已触发筛选器后,添加一个返回此类请求的筛选器:SELECT ID FROM wp_posts WHERE 0 = 1 一旦删除所有筛选器,就不可能更改此查询,而且查询速度非常快,并且没有确定的结果。运行此查询后,立即恢复所有原始筛选器(如果有),并且所有后续查询都将按预期工作

结束

相关推荐

Custom Same Page Search

我已将自定义表单添加到我的一个页面模板中。它屈服于自己$_SERVER[\'REQUEST_URI\'] 希望我能抓住$_GET 值并使用修改我的查询pre_get_posts, 但它却转到了404。因此,为了澄清,我不想使用搜索。php,我希望它发回我的页面模板,并修改我的查询以显示“filterd”结果,而不是404ing。我试过使用pre_get_posts 测试是404还是搜索,但我也不想阻止404的任何其他操作。那么,我如何在同一页面/url/页面模板上使用查询,而无需回复search.php