แบบสอบถามเพื่อเรียงลำดับรายการตามเมตาคีย์ก่อน (ถ้ามี) และแสดงโพสต์ที่เหลือโดยไม่ต้องคีย์เมตาเรียงตามชื่อ


22

ฉันกำลังทำงานกับเทมเพลตหน้าคำศัพท์ taxonomy ที่กำหนดเองซึ่งเราต้องการให้รายการที่เชื่อมโยงกับคำที่เรียงตามวันที่เผยแพร่ (ฟิลด์วันที่กำหนดเอง) - และหากมีหลายรายการในวันเดียวกัน (จัดรูปแบบเช่น YYYY-MM- DD) เพื่อจัดเรียงรายการเหล่านั้นตามชื่อและในที่สุดก็เรียงลำดับตามชื่อเรื่องหากฟิลด์ที่กำหนดเองยังไม่ได้กรอก (รายการเก่า)

ดังนั้นฉันจึงลองใช้วิธีที่แตกต่างกันหลายร้อยวิธีด้วย WP_query และมันส่งคืนผลลัพธ์ส่วนใหญ่ตามที่ฉันต้องการ - แต่ในกรณีนี้มันจะคืนค่ารายการที่มี meta_key ของ publication_date เท่านั้น รายการอื่น ๆ ทั้งหมดจะถูกละเว้นและไม่แสดง ฉันลองใช้ meta_query โดยใช้ความสัมพันธ์ของ "หรือ" และเปรียบเทียบสิ่งพิมพ์_dateว่าเป็น EXISTS และไม่ใช่ EXISTS แต่ได้ผลลัพธ์ 0 รายการกลับมาให้ฉัน

นอกจากนี้ไซต์ยังคงทำงาน 3.5.2 และพวกเขาไม่ต้องการอัพเกรด

นี่คือข้อความค้นหาล่าสุดของฉันที่ทำให้ฉันได้รับโพสต์ที่มีฟิลด์ที่กำหนดเองสิ่งพิมพ์_dateตามลำดับที่ถูกต้อง:

$term = get_queried_object(); // find the term of the taxonomy page we are on
$wp_query = new WP_Query( array(
'post_type' => 'resource',
'tax_query' => array(
    array(
        'taxonomy' => 'resource_types',
        'field' => 'slug',
        'terms' => $term->name,
    )), 

'meta_key' => 'publication_date',
'orderby' => 'meta_value_num',
'order' => 'DESC',
'paged' => $paged,
'posts_per_page' => '10',
));

ฉันยังลองใช้ wpdb และเรียกใช้แบบสอบถาม SQL แต่ฉันไม่แน่ใจว่าจะทำสิ่งที่ฉันต้องการได้อย่างไร หากมีคนช่วยฉันได้นั่นจะยอดเยี่ยม!

ขอบคุณล่วงหน้า.


แปลกใจที่วิธีการ meta_query ไม่ทำงาน แต่แล้วคุณไม่สามารถสั่งซื้อโดยใช้ค่าเมตาด้วย meta_query โดยไม่ต้องตั้งค่า meta_key
sanchothefat

ฉันคิดว่านั่นเป็นปัญหาที่ฉันมี ในที่สุดฉันก็ได้รับเม'meta_query' => array( 'relation' => 'OR', array( //check to see if date has been filled out 'key' => 'publication_date', 'compare' => '!=', 'value' => date('Y-m-d'), ), array( //if no date has been added show these posts too 'key' => 'publication_date', 'value' => date('Y-m-d'), 'compare' => 'NOT EXISTS' ) ),
ตะ

อืมการสั่งซื้อขึ้นอยู่กับ meta_key ที่ถูกตั้งค่าไว้ด้านนอกของ tax_query โชคไม่ดี คำตอบของฉันด้านล่างอาจช่วย
sanchothefat

คำตอบ:


19

ขอบคุณทุกคนสำหรับความช่วยเหลือของคุณ!

ในที่สุดแบบสอบถามด้านล่างทำให้ฉันได้ผลลัพธ์ที่ฉันต้องการ - ซึ่งจะแสดงและจัดเรียงโพสต์โดยฟิลด์ที่กำหนดเองของ "publication_date" ก่อน - เรียงลำดับตามวันที่และถ้ามีหลายวันเดียวกัน (พูด 4 ทำเครื่องหมาย มิถุนายน 2013) มันจะเรียงลำดับตามชื่อ จากนั้นหลังจากที่โพสต์ข้อความทั้งหมดที่มีวันที่เผยแพร่แล้วจะวนซ้ำโพสต์ที่เหลือตามลำดับตัวอักษรอีกครั้ง

นี่ทำให้ฉันได้ผลลัพธ์ที่ตั้งไว้ในแบบสอบถามเดียวกันและรักษาเลขหน้าของฉัน:

$term = get_queried_object();
the_post();
$wp_query = new WP_Query( array(
'post_type' => 'resource',
    'tax_query' => array(
        array(
            'taxonomy' => 'resource_types',
            'field' => 'slug',
            'terms' => $term->name,
        )),
 'meta_query' => array(
       'relation' => 'OR',
        array( //check to see if date has been filled out
                'key' => 'publication_date',
                'compare' => '=',
                'value' => date('Y-m-d')
            ),
          array( //if no date has been added show these posts too
                'key' => 'publication_date',
                'value' => date('Y-m-d'),
                'compare' => 'NOT EXISTS'
            )
        ),
'meta_key' => 'publication_date',
'orderby' => 'meta_value title',
'order' => 'ASC',
'paged' => $paged,
'posts_per_page' => '10',
));

1
ดี ฉันไม่เคยคิดจะรันสองmeta_queryบนคีย์เดียวกัน!
GhostToast

5
สำหรับผม (ใช้ WordPress 4.1.1) ถ้าผมตั้งค่าโดยอัตโนมัติไม่รวมมันแม้จะมีmeta_key NOT EXISTSฉันหวังว่าฉันจะทำอะไรผิด
Ryan Taylor

1
@RyanTaylor เหมือนกันที่นี่ - meta_key ต้องไม่ถูกตั้งค่าในแบบสอบถามเพื่อให้ทำงานได้ แต่ดูเหมือนว่าจะเรียงลำดับอย่างถูกต้องด้วยค่าเมตาแม้ว่าจะไม่ได้ตั้งค่าเมตาคีย์
jammypeach

2
เป็นความคิดเห็นข้างต้นสำหรับ WP 4.1 'meta_key' => 'publication_date',ขึ้นไปลบหรือแสดงความคิดเห็นออกมา
MikeiLL

7

ไม่กี่ปีต่อมารหัสที่โพสต์โดย CSSGirl ไม่ทำงานสำหรับฉันเพราะมีบางโพสต์ที่ไม่มีเมตาคีย์หรือเมตาคีย์ว่างเปล่าดังนั้นนี่คือสิ่งที่ฉันต้องทำเพื่อให้โพสต์ทั้งหมดเรียงตามวันที่ และแสดงรายการที่มีค่าคีย์เมตาแสดงก่อน:

$args          = array(
'post_type'   => $type,
'post_status' => 'publish',
'nopaging'    => TRUE,
'meta_query'  => array(
    'relation' => 'OR',
    array(
        'key'     => $meta_key,
        'compare' => 'NOT EXISTS',
    ),
    array(
        'relation' => 'OR',
        array(
            'key'   => $meta_key,
            'value' => 'on',
        ),
        array(
            'key'     => $meta_key,
            'value'   => 'on',
            'compare' => '!=',
        ),
    ),
),
'orderby'     => array( 'meta_value' => 'DESC', 'date' => 'DESC' ),
);

1

ฉันคิดว่าคุณต้องแยก 2 ลูป คุณสามารถรวบรวมโพสต์ทั้งหมดที่พบในลูปแรกและแยกออกจากลูปรองได้ง่ายพอ:

$found_posts = array();
while($loop->have_posts()): $loop->the_post();
    // loop stuff
    $found_posts[] = get_the_id();
endwhile;

wp_reset_query();

$args = array(
    // other args
    'post__not_in' => $found_posts,
);

จากนั้นรันลูปที่สองของคุณ


ลองทำตอนนี้ขอบคุณ จะแจ้งให้คุณทราบหากใช้งานได้!
CSSgirl

1
สิ่งนี้ได้ผล - แต่มันทำให้หน้าแตก - ความคิดใดว่าจะให้มันทำงานอย่างไร นี่คือสิ่งที่ดูเหมือนตอนนี้:echo paginate_links( array( 'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ), 'format' => '?page=%#%', 'current' => max( 1, get_query_var('paged') ), 'total' => $publication_query->max_num_pages, 'prev_text' => __('Previous |'), 'next_text' => __('| Next'), ) );
CSSgirl

อืมมม ไม่ว่าฉันจะคิด
GhostToast

1

มีเหตุผลใดบ้างที่คุณไม่สามารถบังคับใช้คีย์ meta ของสิ่งพิมพ์_dateที่มีอยู่สำหรับทุกโพสต์ที่มีค่าว่างเปล่า

ดังนั้นในsave_postการกระทำของคุณคุณจะต้องเพิ่ม / อัปเดตเมตาคีย์ว่า$_POSTค่านั้นว่างเปล่าหรือไม่

คุณจะต้องเรียกใช้สคริปต์การอัปเดตเพื่อวนซ้ำโพสต์เก่าของคุณและเพิ่มคีย์ด้วยค่าว่างเช่น:

add_action( 'admin_init', 'update_old_posts' );
function update_old_posts() {
    if ( ! isset( $_GET[ 'update_old_posts' ] ) )
         return;

    foreach( get_posts() as $post ) {
        if ( false === get_post_meta( $post->ID, 'publication_date', true ) ) {
             update_post_meta( $post->ID, 'publication_date', '' );
             echo "Updated {$post->post_title} <br />";
        }
    }

    die;
}

รันโดยไปที่http://example.com/wp-admin/?update_old_posts

จากนั้นคุณสามารถใช้แบบสอบถามเดียวกันกับที่คุณมี คุณอาจต้องการเพิ่มตัวกรองพิเศษเพื่อให้คุณสามารถเรียงลำดับตามคอลัมน์ต่าง ๆ ในทิศทางที่แตกต่างกันฉันจะเรียงลำดับตามวันในลำดับจากมากไปน้อยและชื่อเรื่องจากมากไปหาน้อย

add_filter( 'posts_orderby', 'multicolumn_orderby', 10, 2 );
function multicolumn_orderby( $orderby, $query ) {
    global $wpdb;

    // check it's the right query
    if ( $query->get( 'meta_key' ) == 'publication_date' ) {
         $orderby = "$wpdb->postmeta.meta_value+0 DESC, $wpdb->posts.post_title ASC";
    }

    return $orderby;
}

อืมฉันไม่คิดอย่างนั้น ฉันจะลองดูและดูว่ามันเป็นอย่างไรขอบคุณ!
CSSgirl

0

ฉันสร้างที่กำหนดเองที่ข้อ ฉันทดสอบโดยใช้$wp_query->requestก่อนลูปหลักของฉันฉันไม่รู้ SQL ที่ดี แต่ดูเหมือนว่าจะทำงานได้ดี

add_action('pre_get_posts', 'add_trending_sort', 11, 1);
function add_trending_sort($query){
  if(!$query->is_main_query())
    return;

  //Overwrite query arguments
  $query->set('meta_query', array(
    array(
      'key' => 'TRENDING',
      //'value' => 'asdfasdf',//may need a value for older versions of WordPress
      'compare' => 'NOT EXISTS',
    )
  ));
  $query->set('orderby', 'meta_value_num date');
  $query->set('order', 'DESC');
}

add_filter('posts_where', 'add_trending_where');
function add_trending_where($where = ''){
  global $wpdb, $wp_query;
  if(!$wp_query->is_main_query())//Not sure if this really works.  Should be OK
    return $where;

  $where .= " OR ( $wpdb->postmeta.meta_key = 'TRENDING' )";

  // Don't run this twice
  remove_filter('posts_where', 'add_trending_where');

  return $where;
}

หรือคุณสามารถตั้งค่าcompareเพื่อ'EXISTS'และเปลี่ยนเส้นใน add_trending_where $where .= " OR ($wpdb->postmeta.post_id IS NULL)";ไป จากนั้นคุณจะต้องเปลี่ยนค่าของคีย์ในที่เดียว อีกครั้ง echo $wp_query->requestและเล่นรอบถ้าคุณต้องการเข้าใจสิ่งนี้ดีกว่าหรือบิดมัน

แก้ไข: ฉันเพิ่งสังเกตเห็นว่าไม่ได้ผลหากmeta_keyตั้งค่าไว้ในแบบสอบถาม คุณสามารถใช้$query->set('meta_key', NULL);ถ้าคุณต้อง

แก้ไข 2: ฉันได้ทำงานนี้ด้วยวิธีการข้างต้น ด้วยเหตุผลบางอย่างมันไม่ได้ในตอนแรก (อาจจะตั้ง meta_key ... ฉันไม่รู้)

add_action('pre_get_posts', 'add_trending_sort', 11, 1);
function add_trending_sort($query){
  // Bail if not the main "hidden" query, as opposed to a 'new WP_Query()' call
  if(!$query->is_main_query())
    return;

  // Set meta_query to get shares for orderby, and also get non-shared content.
  $query->set('meta_query', array(
    'relation' => 'OR',
    array(
      'key' => 'TRENDING',
      'compare' => 'NOT EXISTS',
    ),
    array(
      'key' => 'TRENDING',
      'compare' => 'EXISTS',
    )
  ));
  //$query->set('meta_key', NULL);
  $query->set('orderby', array('meta_value_num' => 'DESC', 'date' => 'DESC'));
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.