当设置了‘Date_Query’参数时,为什么WP_QUERY::IS_DATE()返回FALSE?

时间:2014-03-23 作者:gmazzap

WordPress 3.7简介\'date_query\' argument for WP_Query.

这非常有用,允许非常复杂的基于日期的查询,但是使用WP_Query 使用该参数的查询上的条件方法。

示例:

$args = array(

  \'tax_query\'=> array(
    \'relation\' => \'AND\',
    array(
      \'taxonomy\' => \'category\',
      \'field\'    => \'slug\',
      \'terms\'    => \'uncategorized\'
    ),
    array(
      \'taxonomy\' => \'post_tag\',
      \'field\'    => \'slug\',
      \'terms\'    => array(\'foo\', \'bar\')
    )
  ),

  \'date_query\' => array(
     array(
       \'year\'  => $today["year"],
       \'month\' => $today["mon"],
       \'day\'   => $today["mday"],
     )
  )

);

$query = new WP_Query( $args );
该查询应返回今天发布的帖子,并具有“未分类”类别或“foo”和“bar”标记。确实如此,到目前为止还不错。

现在考虑以下条件方法:

$query->is_archive();  // returns true, as guessable
$query->is_category(); // returns true, as guessable
$query->is_tag();      // returns true, as guessable
但是

$query->is_date();  // returns false
$query->is_day();   // returns false
$query->is_month(); // returns false
$query->is_year();  // returns false
我认为问题可能是因为我混合了“tax\\u query”和“date\\u query”,但这不是问题所在,证明:

$args = array(
  \'date_query\' => array(
     array(
       \'year\'  => $today["year"],
       \'month\' => $today["mon"],
       \'day\'   => $today["mday"],
     )
  )
);

$query = new WP_Query( $args );

$query->is_date();    // returns false
$query->is_day();     // returns false
$query->is_month();   // returns false
$query->is_year();    // returns false
$query->is_archive(); // returns false this time
这是虫子,还是我遗漏了什么?(我搜索了WP Trac,但没有找到相关内容)。

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

我会试着整理一些顺序,把我所有的想法集中在一个答案上,而不是评论两个好答案@s_ha_dum@kaiser (我两个都投了赞成票)。

首先,我们需要指定WordPress中有两种类型的查询,mainsecondaries.

两者都是同一类的实例,WP_Query 但第一个区别是,主查询对象由WordPress实例化并保存在全局$wp_query 变量,所有辅助查询必须由自定义代码实例化。

但还有另一个很大的区别:为了获得职位,WP_Query 需要接收一些参数:在主查询中,这些参数是from url 在辅助查询中,参数必须显式传递给构造函数或get_posts 方法

前面的一个直接结果是,对于主查询,来自url的查询参数只能是scalar variables: 字符串、整数和布尔值:值为数组的查询参数不能通过URL、infact、,any non scalar variable is strip out from query arguments set via urls.

因此,我们还有两种类型的查询参数,“quot;标量参数“;和;数组参数;。

WordPress使用标量参数设置模板标记,实际上WordPress工作流是:

  1. Setup query arguments using url arguments
  2. Setup conditional template properties (所有is_*) 在全球范围内$wp_query 对象Get the posts based on query arguments
  3. Using those conditional template properties load a specific template
值得注意的是,即使无法使用url设置非标量参数,也可以使用\'pre_get_posts\' 使主查询使用非标量变量的操作挂钩,如tax_query, meta_query, date_query 等等

但是\'pre_get_posts\' 在上述工作流中,在#3到#4之间运行,因此即使可以使用基于数组的查询参数,条件模板属性也已经设置好,因此只需使用tax_query 或内部的任何其他非标量查询参数pre_get_posts don\'t affect the template conditional tags (因此加载了模板),除非显式设置is_* 属性:

add_action( \'pre_get_posts\', function( $query ) {

  if ( $query->is_main_query() && ! is_admin() ) {
      
    $tax_query = array ( array(
      \'taxonomy\' => \'category\', \'field\' => \'slug\', \'terms\' => \'foo\')
    );

    // this will affect query, but will NOT affect the template loaded
    $query->query_vars[\'tax_query\'] = $tax_query; 
    // this will affect the template loaded, instead
    $query->is_category = TRUE; 
  }

} );
也就是说,非标量查询参数\'date_query\'not 用于设置模板标记,所以问题变成了另一个:为什么WordPress解析tax_query 即使他们can\'t 是否影响模板?

即使应该向核心开发人员提出这个问题,我也有一个想法。

Notice: next 2 code snippets are bad, here just for proof of concept: don\'t do at home.

add_action( \'template_redirect\', function() {

  $args = array( \'tax_query\' => array(
    array( \'taxonomy\' => \'category\', \'terms\' => array( 16, 17 )  )
  ) );

  $GLOBALS[\'wp_query\'] = new WP_Query( $args );

} );
在以前的代码中,我替换了全局wp_query 使用另一个使用税务查询的查询。它可能看起来很奇怪,但工作正常,加载的模板是category.php 因为WordPress为\'tax_query\' (事实和$GLOBALS[\'wp_query\']->is_category() 将是true).

如果我使用\'date_query\':

add_action( \'template_redirect\', function() {

  $args = array( \'date_query\' => array(
    array( \'month\' => 3, \'year\' => 2014  )
  ) );

  $GLOBALS[\'wp_query\'] = new WP_Query( $args );

} );
帖子将按预期检索(从2014年3月起),但加载的模板将not date.php$GLOBALS[\'wp_query\']->is_date() 将是false.

因此,我的猜测(也只是猜测)是,在旧代码中,核心开发人员考虑了覆盖全局$wp_query 对象,其中一个使用非标量参数,因此它们需要使模板层次结构在这种情况下工作。但在更为现代的代码中(“date\\u query”只出现在WP 3.7中),核心开发人员并不担心这一点,因为他们可能认为没有理由担心糟糕的做法。。。

本质上,对于核心的工作方式,这并不奇怪date_query 不设置模板条件属性,但奇怪的是tax_query

只有两个附加注释。

正在查看template hierarchy, 一些条件模板标记对其没有影响,例如。is_time and much others 对模板选择没有影响。

那么,不影响模板选择的条件模板标记的有用性是什么?

如果我们回答:“;无“;,然后,我们必须承认,它们只是出于某些历史原因或错误原因而存在,否则,如果条件标记有用,即使不影响模板选择,那么我们必须承认,如果WP将为所有非标量参数设置条件属性,而不仅仅是\'tax_query\'.

此外,有时在我的代码中,我使用创建自己的类来扩展WP_Query (and I\'m not the only one). 即使在大多数情况下WP_Query 类是用于辅助查询的,可能还想将其用于主查询(这远非不可能,因为这只是覆盖一个全局变量的问题)。

当然是一种很糟糕的做法覆盖$wp_query 在它已经查询了帖子之后,但是如果一个人使用了一个早期的钩子,比如\'setup_theme\', 那里,全球$wp_query 只是一个空对象,可以无任何问题地重写。但自定义mainWP_Query 对象,可以为主查询使用非标量参数,并允许在设置条件模板属性之前设置它们。那样的话就没用了WP_Query 是否会解析所有非标量参数并相应地正确设置条件模板属性?

在我看来,是的,这将是有用的,但直到核心将强烈基于核心WP_Query 类(这是永远的),核心可能没有意义。

如果有人出于任何原因想要解析\'date_query\' 并设置条件模板标记,则可以使用以下代码:

add_action( \'parse_query\', function ( \\WP_Query $q ) {
  $cond = array(
    \'hour\' => \'is_time\', \'minute\' => \'is_time\', \'second\' => \'is_time\',
    \'year\' => \'is_year\', \'month\' => \'is_month\', \'day\' => \'is_day\',
    \'dayofweek\' => \'is_day\',
    \'week\' => \'is_date\', \'before\' => \'is_date\', \'after\' => \'is_date\'
  );
  $date_query = isset( $q->query_vars[\'date_query\'] )
    ? $q->query_vars[\'date_query\']
    : FALSE;
  if ( empty( $date_query ) ) return;
  $found = 0;
  foreach ( $date_query as $i => $query ) {
    if ( ! is_array( $query ) ) continue;
    foreach ( $query as $key => $val) {
      if ( is_numeric($key) || ! isset( $cond[$key] ) ) continue;
      if ( in_array( $key, array( \'before\', \'after\' ) ) ) {
        $q->is_time = $q->is_year = $q->is_month = $q->is_day = FALSE;
        $q->is_date = $q->is_archive = TRUE;
        return;
      }
      $found++;
      $q->$cond[$key] = TRUE;
    }
  }
  if ( $found <= 0 ) return;
  // a query can\'t be is_time, is_year, is_month and is_day in same time
  $q->is_year = $q->is_year && ! $q->is_time && ! $q->is_month && ! $q->is_day;
  $q->is_month = $q->is_month && ! $q->is_time && ! $q->is_day;
  $q->is_day = $q->is_day && ! $q->is_time;
  $q->is_date = $q->is_archive = TRUE;
  $q->is_home = FALSE;
});

SO网友:s_ha_dum

is_date(), is_day(), 等。方法设置在parse_query 方法,它们似乎真的是用于主查询的,无论是否显式声明(有意)。代码解析public query variables to determine those settings.

我的解释是,这些值实际上并不适用于二次查询,对于二次查询也没有多大意义。您刚刚运行了查询,您知道这是一个日期/税款/任何查询。不需要通过解析查询变量为您确定该部分。

更深入一点,我认为问题源于WP_Query 有点精神分裂。它解析请求以确定应该加载哪个页面,而不仅仅是查询数据库中帖子的工具。它有两个功能,而不是一个,在我看来,这是一个糟糕的设计。我认为独特的代码应该解析请求,然后将参数传递给WP_Query. 也许那只是我。

是虫子吗?我会这样说,至少是“奇怪的设计”。如果WP_Query 如果要同时完成这两项工作,它至少应该一致地设置类变量,或者将类拆分为两个,每个都有一个目的。当然,我不能规范地声明某个东西是不是“bug”:

SO网友:kaiser

注意:这只是对@s\\u ha\\u dum答案的补充(根据以上投票,答案可能在这个答案的北面)

所有的"Conditional Tags"/确定状态的查询方法,例如。

  • is_date
  • is_day
  • is_hour
  • is_nanosecond
&hellip;都老了,所以人们往往会忘记自己的存在。让我们面对现实:他们从来都不是很受欢迎的。您在跨互联网的数字旅行中遇到过多少小时存档?

但有趣且经常需要的是日期范围,它可以被解释为与日期档案完全无关,这就是is_ 条件是。所以我可以想象date_query 零件在基于日期或时间的存档和相应的查询之间完全没有联系。

设想以下情况:

WTF!为什么我的每小时存档模板会起作用,而我想要的只是在头版上按周分页的帖子?

即使很多核心看起来似乎是“意外设计”,但这一个实际上不是tax_query 部分WP_Query::get_posts():

$this->parse_tax_query( $qv );

foreach ( $this->tax_query->queries as $tax_query ) {
    if ( \'NOT IN\' != $tax_query[\'operator\'] ) {
        switch ( $tax_query[\'taxonomy\'] ) {
            case \'category\':
                $this->is_category = true;
                break;
            case \'post_tag\':
                $this->is_tag = true;
                break;
            default:
                $this->is_tax = true;
        }
    }
}
unset( $tax_query );
我想问你两个问题:

上述片段意味着什么

结束

相关推荐

使用新的WP-Query()从循环中过滤后期格式;

嗨,我目前正在为我的博客构建一个主题。下面的代码指向最新的帖子(特色帖子)。因为这将有一个不同的风格比所有其他职位。然而我想过滤掉帖子格式:链接使用我在循环中定义的WP查询,因为它给我带来了更多的灵活性。我该怎么做呢? <?php $featured = new WP_Query(); $featured->query(\'showposts=1\'); ?> <?php while ($featured->have_post