【问题标题】:Wordpress wp_query: Order by meta_query key & then everything else by date (pinned / sticky)Wordpress wp_query:按 meta_query 键排序,然后按日期排序(固定/粘性)
【发布时间】:2020-06-14 21:57:25
【问题描述】:

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

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

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

我正在尝试获取 按日期排序 的帖子列表,如果 元键 set_as_pinned 设置为 true,则始终将其作为帖子 1 返回,那么其余的可以按日期订购。因此给了我一个“粘性”的壮举。

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

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

);

目前,所有这些返回都是我拥有的 1 个置顶帖子。它缺少 DATE 顺序中的所有其他内容。

【问题讨论】:

    标签: php wordpress meta-query


    【解决方案1】:

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

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

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

    可以在这里找到无注释版本https://github.com/Sandy-Garrido/wordpress-ajax-pagination-sticky-pinned

    Pre-req - 为固定/粘性设置元数据

    我假设您已经(使用 ACF 或其他方式)设置元数据来检索置顶帖子。在我的示例中,我有一个名为 set_as_pinned 的键的布尔字段类型

    第 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
    

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

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

    什么是偏移量?

    get_posts() & wp_query 的参数

    offset (int) – 要替换或越过的帖子数。警告: 设置偏移参数覆盖/忽略分页参数和 打破分页。 'offset' 参数在以下情况下被忽略 'posts_per_page'=>-1(显示所有帖子)被使用。

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

    我希望这对你有帮助..

    【讨论】:

      猜你喜欢
      • 2021-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-29
      • 1970-01-01
      • 2021-09-30
      相关资源
      最近更新 更多