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

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

我已经为此绞尽脑汁好几个小时了,现在是时候把它带到 Stack overflow 了。

我知道没有简单的方法可以做到这一点,而且可能根本没有办法做到这一点。

使用 Wordpress,我正在尝试查询 posts,但在保持分页的同时以特定方式对它们进行排序(因为它是通过 AJAX 完成的,所以两个查询解决方案在我的情况 - 据我所知)。

我正在尝试获取 按日期排序 的 post 列表,其中如果 元键 set_as_pinned 设置为 true return 这总是 post 1,然后其余的可以按日期排序。因此给了我一个"Sticky"壮举。

在尝试了许多不同的解决方案之后,我遇到了以下查询,

$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'
        ),
    )

);

目前,所有这些 return 都是我拥有的 1 个固定 post。它缺少 DATE 顺序中的所有其他内容。

我不是通过使用元查询方法而是通过使用 2 个查询设法实现了这一点,我认为这是不可能的。我会尽力为可能遇到相同问题的其他人解释。

此解决方案将帮助人们尝试解决

  • AJAX 固定或粘性分页 posts
  • 具有自定义 post 类型的置顶帖子

可以在此处找到无评论版本https://github.com/Sandy-Garrido/wordpress-ajax-pagination-sticky-pinned

先决条件 - 设置固定/置顶的元数据

我假设您已经(使用 ACF 或其他方式)设置元数据以检索固定的 posts。在我的示例中,我有一个名为 set_as_pinned

的键的字段类型 Boolean

第 1 步 - 获取您的 pinned/stick posts

$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

第 2 步 - 为第二个查询设置变量

(并计算第 2 页及以上页的偏移量)

什么是偏移量?

get_posts() & wp_query

的论点

offset (int) – number of post to displace or pass over. 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.

注意 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)));

}

第 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

我希望这对你有所帮助,就像对我一样..