介绍STR_TO_DATE
MySQL具有
STR_TO_DATE
您可以为范围利用的功能。
要使用它,您需要过滤WHERE
a条款WP_Query
, 可能使用posts_where
滤器
该函数允许使用特定格式将列值格式化为日期。
默认情况下,WordPress使用CAST
MySQL函数,该函数期望值的格式为Y-m-d H:i:s
(根据PHPdate
参数)。
STR_TO_DATE
, 相反,允许传递特定格式。“占位符”格式与PHP使用的格式不同,您可以在此处看到支持的MySQL格式占位符:https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-format.
工作流
作为工作流,我可以建议:
创建WP_Query
对象使用posts_where
添加WHERE
使用的子句STR_TO_DATE
移除筛选器运行查询,以避免影响任何其他查询请注意STR_TO_DATE
也可用于排序值。如果您想这样做,您需要使用posts_orderby
滤器
过滤类
这里有一个类(PHP 7+)包装了上述工作流,以便于重用:
class DateFieldQueryFilter {
const COMPARE_TYPES = [ \'<\', \'>\', \'=\', \'<=\', \'>=\' ];
private $date_key;
private $date_value;
private $format;
private $compare = \'=\';
private $order_by_meta = \'\';
public function __construct(
string $date_key,
string $date_value,
string $mysql_format,
string $compare = \'=\'
) {
$this->date_key = $date_key;
$this->date_value = $date_value;
$this->format = $mysql_format;
in_array($compare, self::COMPARE_TYPES, TRUE) and $this->compare = $compare;
}
public function orderByMeta(string $direction = \'DESC\'): DateFieldQueryFilter {
if (in_array(strtoupper($direction), [\'ASC\', \'DESC\'], TRUE)) {
$this->order_by_meta = $direction;
}
return $this;
}
public function createWpQuery(array $args = []): \\WP_Query {
$args[\'meta_key\'] = $this->date_key;
$this->whereFilter(\'add\');
$this->order_by_meta and $this->orderByFilter(\'add\');
$query = new \\WP_Query($args);
$this->whereFilter(\'remove\');
$this->order_by_meta and $this->orderByFilter(\'remove\');
return $query;
}
private function whereFilter(string $action) {
static $filter;
if (! $filter && $action === \'add\') {
$filter = function ($where) {
global $wpdb;
$where and $where .= \' AND \';
$sql = "STR_TO_DATE({$wpdb->postmeta}.meta_value, %s) ";
$sql .= "{$this->compare} %s";
return $where . $wpdb->prepare($sql, $this->format, $this->date_value);
};
}
$action === \'add\'
? add_filter(\'posts_where\', $filter)
: remove_filter(\'posts_where\', $filter);
}
private function orderByFilter(string $action) {
static $filter;
if (! $filter && $action === \'add\') {
$filter = function () {
global $wpdb;
$sql = "STR_TO_DATE({$wpdb->postmeta}.meta_value, %s) ";
$sql .= $this->order_by_meta;
return $wpdb->prepare($sql, $this->format);
};
}
$action === \'add\'
? add_filter(\'posts_orderby\', $filter)
: remove_filter(\'posts_orderby\', $filter);
}
}
抱歉,如果这里没有太多注释或解释,那么很难在这里编写代码。
在“神奇”发生的地方,类的“核心”是添加到posts_where
在查询运行之前,然后删除。它是:
function ($where) {
global $wpdb;
$where and $where .= \' AND \';
// something like: STR_TO_DATE(wp_postmeta.meta_value,\'%b %e, %Y\') < \'Feb 1, 2017\'
$sql = "STR_TO_DATE({$wpdb->postmeta}.meta_value, %s) {$this->compare} %s";
return $where . $wpdb->prepare($sql, $this->format, $this->date_value);
};
你可以在这里看到我们是如何告诉WordPress查询帖子的。请注意
STR_TO_DATE
是一种并非免费的计算,如果有数千(或数百万)行,计算量将相当大(尤其是CPU)。
如何使用它顺便提一下,这个类可以这样使用:
$query_filter = new DateFieldQueryFilter (
\'expiration_date\', // meta key
date(\'M j, Y\'), // meta value
\'%b %e, %Y\', // date format using MySQL placeholders
\'<\' // comparison to use
);
$query = $query_filter->createWpQuery([\'posts_per_page\' => - 1]);
while($query->have_posts()) {
$query->the_post();
// rest of the loop here
}
如果您想按标准WordPress字段排序,例如,发布日期、发布标题。。。,你可以简单地通过相关的
order
和
orderby
的查询参数
DateFieldQueryFilter::createWpQuery()
方法
如果您想使用相同的元值进行订购,该类将提供DateFieldQueryFilter::orderByMeta()
对于范围。
E、 g.在最后一段代码中,您将创建如下查询:
$query = $query_filter
->orderByMeta(\'DESC\')
->createWpQuery([\'posts_per_page\' => - 1]);
结论即使这样做有效,在可能的情况下,日期也应该使用MySQL格式或时间戳保存在数据库中,因为这大大简化了任何过滤或排序操作。
事实上,从数据库中检索日期后,以所需格式将日期转换为输出要容易得多。
即使以任何一种方式进行计算,在返回的记录之后进行计算,但让MySQL执行它需要对**所有*记录执行的计算,需要做更多的工作。
如果以MySQL格式存储日期,WordPress提供了一个函数,mysql2date()
, 它可以用于将它们转换为所需的格式,并且还支持区域设置。