简体   繁体   English

Wordpress wp_query:按 meta_query 键排序,然后按日期排序(固定/粘性)

[英]Wordpress wp_query: Order by meta_query key & then everything else by date (pinned / sticky)

I've been racking my brain over this for hours and now it's time to take it to Stack overflow.我已经为此绞尽脑汁好几个小时了,现在是时候把它带到 Stack Overflow 上。

I'm aware there's no easy way to do this and probably there is not a way to do this at all.我知道没有简单的方法可以做到这一点,而且可能根本没有办法做到这一点。

Using Wordpress, I'm trying to query posts but order them in a particular way whilst keeping pagination (as it's done via AJAX so a two query solution wouldn't work in my case - to my knowledge).使用 Wordpress,我正在尝试查询帖子,但以特定方式对它们进行排序,同时保持分页(因为它是通过 AJAX 完成的,所以在我的情况下,两个查询解决方案不起作用 - 据我所知)。

I'm trying to get an ordered by date list of posts where if the meta key set_as_pinned is set to true return this as post 1 always, then the rest can be ordered by date.我正在尝试获取按日期排序的帖子列表,如果元键set_as_pinned设置为true ,则始终将此作为帖子 1 返回,则 rest 可以按日期排序。 Thus giving me a "Sticky" feat.从而给了我一个“粘性”的壮举。

After playing about with many different solutions, I'm at the following query, which在玩了许多不同的解决方案之后,我在以下查询中,

$args = array(
    'post_type'         => $post_type,
    'posts_per_page'    => $post_type,
    'post_status'       => 'publish',
    'search_prod_title' => $s_query,
    'orderby'           => array(
        'pinned', 'not_pinned'
    ),
    'paged'             => $paged,
    'tax_query'         => $tax_query,
    'meta_query'      => array(
        'relation'    => 'or',
        'pinned' => array(
            'key'     => 'set_as_pinned',
            'value'   => true,
            'compare' => '=',
            'orderby' => 'date',
            'order' => 'DESC'
        ),
        'not_pinned' =>  array(
            'key'     => 'set_as_pinned',
            'value'    => true,
            'compare' => '!=',
            'orderby' => 'date',
            'order' => 'DESC'
        ),
    )

);

Currently, all this returns is the 1 pinned post that I have.目前,所有这些返回都是我拥有的 1 个置顶帖子。 It's missing everything else in DATE order.它缺少 DATE 顺序中的所有其他内容。

I have managed to achieve this not by using the meta query method but actually by using 2 queries, which I didn't think was possible.我设法通过使用元查询方法而不是通过使用 2 个查询来实现这一点,我认为这是不可能的。 I'll do my best to explain for others who may be having the same issue.我会尽力为可能遇到相同问题的其他人解释。

This solution will help people trying to solve这个解决方案将帮助人们试图解决

  • AJAX Pagination with pinned or sticky posts AJAX 带有固定或粘性帖子的分页
  • Sticky Posts with custom post types具有自定义帖子类型的置顶帖子

A comment-less version can be found here https://github.com/Sandy-Garrido/wordpress-ajax-pagination-sticky-pinned可以在此处找到无注释版本https://github.com/Sandy-Garrido/wordpress-ajax-pagination-sticky-pinned

Pre-req - Setting meta data for pinned / sticky Pre-req - 为固定/粘性设置元数据

I will presume that you have already (with ACF or other means) set meta data to retrieve pinned posts.我假设您已经(使用 ACF 或其他方式)设置元数据来检索置顶帖子。 In my example, I have a field type of Boolean for a Key named set_as_pinned在我的示例中,对于名为 set_as_pinned 的键,我的字段类型为set_as_pinned

Step 1 - Get your pinned/stick posts第 1 步 - 获取您的固定/粘贴帖子

$paged = $_POST['pageRequested'];
// declare an empty array for your pinned posts
// (this helps us exclude it from our query when we need to get all the other posts)
$pinned_post_arr = array(); 

// Define your args for pinned or sticky posts
$pinned_args = array(
    'post_type' => 'insight',
    'posts_per_page' => -1,
    'meta_key' => 'set_as_pinned',
    'meta_value' => true
); 

// Query list of pinned posts using wp_query or get_posts()
$pinned_posts = new \WP_Query($pinned_args);


    while ($pinned_posts->have_posts()){
        $pinned_posts->the_post();

//Send this post ID to array so we don't duplicate this in our list
        array_push( $pinned_post_arr,  get_the_ID()); 

        $Posts = new Posts;

        //add each post to the query response data
        if($paged == 1){

           // DO STUFF WITH YOUR PINNED POSTS HERE.
           // Generate HTML or cards, whatever you need
           // My use case was to generate HTML and pass it back via AJAX

// this is relative to my project, so copying won't work
          query_response['data'] .= $Posts->render_posts(); 

        }
    }
    wp_reset_postdata(); // ensure you include this line

Step 2 - Set variables for the second query第 2 步 - 为第二个查询设置变量

(and calculate an offset for page 2 and up) (并计算第 2 页及以上的偏移量)

What is offset?什么是抵消?

An argument for get_posts() & wp_query get_posts()wp_query的参数

offset (int) – number of post to displace or pass over. offset (int) -- 要替换或通过的帖子数。 Warning: Setting the offset parameter overrides/ignores the paged parameter and breaks pagination.警告:设置偏移参数会覆盖/忽略分页参数并中断分页。 The 'offset' parameter is ignored when 'posts_per_page'=>-1 (show all posts) is used.当使用“posts_per_page”=>-1(显示所有帖子)时,“offset”参数将被忽略。

Take note of the warning Wordpress has given us of the paged and pagination issues.注意警告 Wordpress 给我们的分页和分页问题。

if($paged == 1){

    // if the request from the browser ajax request wants page 1,
    // we need the second query to return the right amount of posts. 
    // This is done by deducting the count of our pinned post array
    $post_per_page = 10 - count($pinned_post_arr);
    $offset = false; // this is not req but I like to add for sanity


} else {

    // If the browser did not request page 1 but requested another page.
    // We need to counter the pinned posts using an offset.
    // This stops page 2 missing items which page 2 thinks is on page 1.


    $post_per_page = 10;

// here, we calculate, based on the page we're on and how many pinned posts there were
// the number 10 is my defined posts per page that I personally wanted.
    $offset = ((10-count($pinned_post_arr) ) + (10 * ($paged - 2)));

}

Step 3 - The second query第 3 步 - 第二个查询

$args = array(
    'post__not_in'      => $pinned_post_arr, // required -exclude already pinned posts
    'post_type'         => $post_type,
    'posts_per_page'    => $post_per_page, // required
    'post_status'       => 'publish',
    'orderby'           => $orderby,
    'order'             =>  $order,
    'offset'            => $offset, // required
    'paged'             => $paged, // required
    'tax_query'         => $tax_query, 
);


$wp_query = new \WP_Query($args);


// I used a library called SimplePagination
// https://github.com/flaviusmatis/simplePagination.js
// This required me to send back the number of items.
// I can query found posts as an int but I MUST add the count from pinned posts too

$query_response['numOfItems'] = $wp_query->found_posts + count($pinned_post_arr);

$query_response['postsPerPage'] = 10;


// Get all found posts (not including pinned) and add it to the data query
while ($wp_query->have_posts()) {

    $wp_query->the_post();
    $Posts = new Posts;

// Here I'm appending more to the AJAX response. Which will follow seamlessly from the pinned posts (if any)
    $query_response['data'] .= $Posts->render_posts();

}
wp_reset_postdata(); // reset for safe measures

I hope this helps you as it did me..我希望这对你有帮助,就像它对我一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM