如何从所有搜索结果中获取年份数组,并使用它按年份过滤分页循环?

时间:2020-07-06 作者:Marks

我希望这不是太愚蠢:尽管我的学习速度可以接受,但我的WP知识仍然存在一些重要的差距。

What do I have:

我的search.php 模板从普通全局$wp_query; $wp_query -> found_posts 正确返回全部结果(例如132),并且$wp_query -> post_count, 对于已分页的循环,返回该页的正确帖子数,最多为posts_per_page (比如说,10)。

What do I need:

我正在尝试按年份设置过滤器<select> 在页面底部;当然,它应该允许用户从所有132个结果中选择年份,而不仅仅是当前页面中的10个。

What does trouble me:

$wp_query -> posts 仅适用于post_count 与当前页面相关的帖子,并非全部132篇。如果我通过pre_get_posts 过滤器,告诉她设置posts_per_page 到-1时is_search(), 当然,我得到了所有的132篇帖子,但我也失去了分页功能。

What did I come up to so far:

我想我需要一个“;“全部”;查询,平行于$wp_query, 保留了所有潜在的结果LIMITed系列。那么,我如何填充这些难以捉摸的年份呢?

只是为了确保从$wp_query, 我分配$wp_query -> request, 但没有LIMIT 子句,转换为变量;那么我$wpdb -> get_results itarray_unique 阵列

Conclusions

我敢肯定,一定会有一个更好、更短、更高效甚至更“的;WP核心;我有办法做到这一点;但到目前为止,我还没有找到答案,也没有在这里或其他地方找到答案。

你们谁能告诉我正确的方向吗?

谢谢

1 个回复
SO网友:Ivan Shatsky

This is really interesting one! I\'ve tried to solve this, and here is what I ended up with.

With a pure SQL, we have an ability to get all distinct years of all our posts with the following SQL request (recipe founded here):

SELECT DISTINCT YEAR(wp_posts.post_date) FROM wp_posts

getting something like this:

mysql> SELECT DISTINCT YEAR(wp_posts.post_date) FROM wp_posts;
+--------------------------+
| YEAR(wp_posts.post_date) |
+--------------------------+
|                     2017 |
|                     2018 |
|                     2019 |
|                     2020 |
+--------------------------+
4 rows in set (0.00 sec)

But how to combine this with our main query, especially taking in account all the search criteria etc? Well, we have a posts_clauses hook where we can get all the request clauses. We need to save this clauses for later use, and we have to make sure we are dealing with the main query clauses. Here is the code (this one goes to the functions.php):

function check_query_clauses( $clauses, $query ) {
    if ( $query->is_main_query() ) {
        global $main_query_clauses;
        $main_query_clauses = $clauses;
    }
    return $clauses;
}
add_filter( \'posts_clauses\', \'check_query_clauses\', 10, 2 );

The $main_query_clauses array would consists of the following fields:

Array (
    [where] => ...
    [groupby] => ...
    [join] => ...
    [orderby] => ...
    [distinct] => ...
    [fields] => wp_posts.*
    [limits] => ...
)

Not all of them will be needed in the future. Next, going to your search.php template, here is the code which we\'ll use:

global $wpdb;
global $main_query_clauses;
$years_query =
    "SELECT DISTINCT YEAR({$wpdb->posts}.post_date) FROM {$wpdb->posts} {$main_query_clauses[\'join\']} WHERE 1=1 {$main_query_clauses[\'where\']}"
    . ( $main_query_clauses[\'groupby\'] ? " GROUP BY {$main_query_clauses[\'groupby\']}" : \'\' )
    . ( $main_query_clauses[\'orderby\'] ? " ORDER BY {$main_query_clauses[\'orderby\']}" : \'\' );
$years_results = $wpdb->get_results( $years_query, \'ARRAY_N\' );

Note that we don\'t use \'limits\' clause here (as well as \'fields\' or \'distinct\' ones). At this step we\'ve got something like

Array (
    [0] => Array (
        [0] => 2020
    )
    [1] => Array (
        [0] => 2019
    )
    [2] => Array (
        [0] => 2018
    )
    [3] => Array (
        [0] => 2017
    )
)

The last piece of code is

$years = wp_list_pluck( $years_results, 0 );

and we are finished up with

Array (
    [0] => 2020
    [1] => 2019
    [2] => 2018
    [3] => 2017
)

Depending on your search criteria the years in array may appear in different order, so you should additionally sort it according to your needs. Voila!

Update

After you select a particular year your query would change and this code would produce an array with only one item. To fix it you\'ll need to remove the year filter part from WHERE SQL clause:

global $wpdb;
global $main_query_clauses;
$pattern = \'/\\sAND\\s*\\(\\s*YEAR\\s*\\(\\s*\' . $wpdb->posts . \'\\.post_date\\s*\\)\\s*=\\s*\\d+\\s*\\)/is\';
$where = preg_replace($pattern, \' \', $main_query_clauses[\'where\']);
$years_query =
    "SELECT DISTINCT YEAR({$wpdb->posts}.post_date) FROM {$wpdb->posts} {$main_query_clauses[\'join\']} WHERE 1=1 $where"
    . ( $main_query_clauses[\'groupby\'] ? " GROUP BY {$main_query_clauses[\'groupby\']}" : \'\' )
    . ( $main_query_clauses[\'orderby\'] ? " ORDER BY {$main_query_clauses[\'orderby\']}" : \'\' );
$years_results = $wpdb->get_results( $years_query, \'ARRAY_N\' );

相关推荐

如果(!$loop->Have_Posts())条件不起作用-WP_QUERY

所以我几乎可以肯定的是,我让它工作得很好,然后不知从哪里出来,它似乎没有工作。我到处修补,让它把一切都隐藏起来,然后什么也不隐藏。想知道是否有人发现我做错了什么?下面的代码基本上可以扫描我的所有产品-simple & variable - 看看是否有IN STOCK 产品有sale 它们的价格。如果没有IN STOCK 具有的产品sale 价格,隐藏某个CSS ID。否则,什么也不做。不知道我错过了什么。。。// -----------------------------------------&