WP_Query ด้วย“ post_title LIKE 'something%'” หรือไม่


44

ฉันต้องทำWP_Queryด้วย a LIKEบนpost_title.

ฉันเริ่มต้นด้วยปกตินี้WP_Query:

$wp_query = new WP_Query( 
    array (
        'post_type'        => 'wp_exposants',
        'posts_per_page'   => '1',
        'post_status'      => 'publish',
        'orderby'          => 'title', 
        'order'            => 'ASC',
        'paged'            => $paged
    )
); 

แต่สิ่งที่ฉันต้องการทำจริง ๆ มีลักษณะเช่นนี้ใน SQL:

$query = "
        SELECT      *
        FROM        $wpdb->posts
        WHERE       $wpdb->posts.post_title LIKE '$param2%'
        AND         $wpdb->posts.post_type = 'wp_exposants'
        ORDER BY    $wpdb->posts.post_title
";
$wpdb->get_results($query);

เอาท์พุทพิมพ์ผลลัพธ์ฉัน excpecting แต่ฉันใช้ปกติ<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>เพื่อแสดงผลลัพธ์ และไม่ได้มีการทำงานร่วมกับ
$wpdb->get_results()

ฉันจะบรรลุสิ่งที่ฉันอธิบายไว้ที่นี่ได้อย่างไร

คำตอบ:


45

WP_Queryฉันจะแก้ปัญหานี้ด้วยตัวกรอง หนึ่งรายการที่ตรวจพบตัวแปรเคียวรีพิเศษและใช้เป็นคำนำหน้าของชื่อเรื่อง

add_filter( 'posts_where', 'wpse18703_posts_where', 10, 2 );
function wpse18703_posts_where( $where, &$wp_query )
{
    global $wpdb;
    if ( $wpse18703_title = $wp_query->get( 'wpse18703_title' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'' . esc_sql( $wpdb->esc_like( $wpse18703_title ) ) . '%\'';
    }
    return $where;
}

วิธีนี้คุณยังสามารถโทรหาWP_Queryคุณเพียงแค่ส่งชื่อเรื่องเป็นwpse18703_titleอาร์กิวเมนต์ (หรือเปลี่ยนชื่อให้สั้นลง)


$wpdb->prepare()หนึ่งนี้เป็นอย่างใดที่ขาดหายไป
ไกเซอร์

@kaiser: มันเป็นเวลานาน prepare()แต่ฉันคิดว่านี่เป็นไปไม่ได้ด้วย $wpdb->prepare('LIKE "%s%%"', 'banana')จะกลับมา"LIKE ''banana'%'"ดังนั้นเราต้องสร้างแบบสอบถามด้วยตัวเองและทำการหลบหนีด้วย
Jan Fabry

1
@JanFabry มีความสุขที่ได้เห็นคุณ agaaaaaaaain! :) แวะมาคุยกันซักครั้งอืม? StopPress ยินดีที่ได้พบคุณ prepare()เกี่ยวกับว่า ใช่มันเป็นเรื่องยุ่งยากและฉันต้องลองหลายครั้งก่อนที่ฉันจะไปถึงได้ จากสิ่งที่ฉันเพิ่งทำ: $wpdb->prepare( ' AND {$wpdb->posts}.post_title LIKE %s ', esc_sql( '%'.like_escape( trim( $term ) ).'%' ) ). และฉันค่อนข้างแน่ใจว่าesc_sql()มันไม่จำเป็นและแค่หวาดระแวง
ไกเซอร์

ดูเหมือนว่าคุณไม่สามารถค้นหาสตริงด้วย'(apostrophe) ภายใน ฉันเดาว่ามันเป็นเพราะการหลบหนี? ฉันยังไม่พบวิธีแก้ปัญหา
Vincent Decaux

19

ย่อ:

function title_filter( $where, &$wp_query )
{
    global $wpdb;
    if ( $search_term = $wp_query->get( 'search_prod_title' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql( like_escape( $search_term ) ) . '%\'';
    }
    return $where;
}

$args = array(
    'post_type' => 'product',
    'posts_per_page' => $page_size,
    'paged' => $page,
    'search_prod_title' => $search_term,
    'post_status' => 'publish',
    'orderby'     => 'title', 
    'order'       => 'ASC'
);

add_filter( 'posts_where', 'title_filter', 10, 2 );
$wp_query = new WP_Query($args);
remove_filter( 'posts_where', 'title_filter', 10, 2 );
return $wp_query;

13
โปรดระบุคำอธิบายพร้อมกับรหัสของคุณ
s_ha_dum

2
การทำให้เข้าใจง่ายมาก
Timo Huovinen

1
รหัสคือฉันคิดว่าตนเองอธิบายอย่างน้อยสำหรับฉัน ขอบคุณที่แบ่งปันสคริปต์ที่สมบูรณ์
Hassan Dad Khan

ใช้ '$ wpdb-> esc_like (' แทน 'esc_sql (like_escape ('
fdrv

@fdrv คุณถูกต้อง แต่ตามเอกสาร wp $ wpdb-> esc_like ยังคงต้องการ esc_sql () ดังนั้นฉันคิดว่ารหัสที่ถูกต้องน่าจะเป็น esc_sql ($ wpdb-> esc_like ($ search_term))
Waqas Bukhary

16

ต้องการอัปเดตรหัสนี้คุณใช้สำหรับ wordpress 4.0 ขึ้นไปเนื่องจาก esc_sql () เลิกใช้แล้วใน 4.0 ที่สูงกว่า

function title_filter($where, &$wp_query){
    global $wpdb;

    if($search_term = $wp_query->get( 'search_prod_title' )){
        /*using the esc_like() in here instead of other esc_sql()*/
        $search_term = $wpdb->esc_like($search_term);
        $search_term = ' \'%' . $search_term . '%\'';
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE '.$search_term;
    }

    return $where;
}

สิ่งที่เหลือก็เหมือนกัน

นอกจากนี้ฉันต้องการชี้ให้เห็นว่าคุณสามารถใช้ตัวแปรsภายในอาร์กิวเมนต์ WP_Query เพื่อผ่านคำค้นหาซึ่งจะค้นหาชื่อโพสต์ที่ฉันเชื่อด้วย

แบบนี้:

$args = array(
    'post_type' => 'post',
    's' => $search_term,
    'post_status' => 'publish',
    'orderby'     => 'title', 
    'order'       => 'ASC'        
);
$wp_query = new WP_Query($args);

ว่าอะไรsearch_prod_titleคืออะไร? ฉันควรเปลี่ยนสิ่งนี้เป็นอย่างอื่นหรือไม่?
Antonios Tsimourtos

ตั้งแต่เมื่อถูกesc_sqldepricated? มันไม่ใช่. $wpdb->escapeแม้ว่า ... developer.wordpress.org/reference/functions/esc_sql
Jeremy

โปรดทราบว่าพารามิเตอร์ s ค้นหาเนื้อหาโพสต์ด้วยซึ่งอาจไม่ใช่เป้าหมายที่ต้องการ =)
Christine Cooper

10

ด้วยโซลูชันที่มีช่องโหว่บางอย่างที่โพสต์ที่นี่ฉันมาพร้อมเวอร์ชันที่เรียบง่ายและถูกสุขลักษณะ

ก่อนอื่นเราสร้างฟังก์ชั่นสำหรับposts_whereตัวกรองที่อนุญาตให้คุณแสดงเฉพาะโพสต์ที่ตรงกับเงื่อนไขเฉพาะ:

function cc_post_title_filter($where, &$wp_query) {
    global $wpdb;
    if ( $search_term = $wp_query->get( 'cc_search_post_title' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . $wpdb->esc_like( $search_term ) . '%\'';
    }
    return $where;
}

ตอนนี้เราเพิ่มcc_search_post_titleลงในอาร์กิวเมนต์การสืบค้นของเรา:

$args = array(
    'cc_search_post_title' => $search_term, // search post title only
    'post_status' => 'publish',
);

และในที่สุดก็ตัดตัวกรองรอบข้อความค้นหา:

add_filter( 'posts_where', 'cc_post_title_filter', 10, 2 );
$query = new WP_Query($args);
remove_filter( 'posts_where', 'cc_post_title_filter', 10 );

ใช้ get_posts ()

ฟังก์ชั่นบางอย่างที่ดึงโพสต์ไม่ได้เรียกใช้ตัวกรองดังนั้นฟังก์ชั่นตัวกรอง posts_where ที่คุณแนบจะไม่แก้ไขแบบสอบถาม หากคุณวางแผนที่จะใช้get_posts()ในการสอบถามการโพสต์ของคุณคุณต้องตั้งค่าsuppress_filtersเป็นเท็จในอาเรย์ของคุณ:

$args = array(
    'cc_search_post_title' => $search_term,
    'suppress_filters' => FALSE,
    'post_status' => 'publish',
);

ตอนนี้คุณสามารถใช้get_posts():

add_filter( 'posts_where', 'cc_post_title_filter', 10, 2 );
$posts = get_posts($args);
remove_filter( 'posts_where', 'cc_post_title_filter', 10 );

sพารามิเตอร์เกี่ยวกับอะไร

sพารามิเตอร์สามารถใช้ได้:

$args = array(
    's' => $search_term,
);

ขณะที่การเพิ่มคำค้นหาของคุณลงในsการทำงานพารามิเตอร์และมันจะค้นหาชื่อโพสต์ก็จะยังค้นหาโพสต์เนื้อหา

สิ่งที่เกี่ยวกับtitleพารามิเตอร์ซึ่งถูกเพิ่มด้วย WP 4.4?

การส่งข้อความค้นหาไปยังtitleพารามิเตอร์:

$args = array(
    'title' => $search_term,
);

เป็นกรณีที่สำคัญและไม่LIKE %LIKE%นี้หมายถึงการค้นหาสำหรับhelloจะไม่กลับมาโพสต์ที่มีชื่อหรือHello WorldHello


ยอดเยี่ยม ฉันกำลังมองหา 'post_title' เป็นพารามิเตอร์และแน่นอนไม่พบอะไรเลย
MastaBaba

7

การสร้างคำตอบอื่น ๆ ก่อนหน้าฉันเพื่อให้มีความยืดหยุ่นในสถานการณ์ที่คุณต้องการค้นหาโพสต์ที่มีคำในฟิลด์เมตาหรือในชื่อเรื่องของโพสต์ฉันให้ตัวเลือกนั้นผ่านอาร์กิวเมนต์ "title_filter_relation" ในการใช้งานนี้ฉันอนุญาตเฉพาะอินพุต "OR" หรือ "AND" ที่มีค่าเริ่มต้นเป็น "AND"

function title_filter($where, &$wp_query){
    global $wpdb;
    if($search_term = $wp_query->get( 'title_filter' )){
        $search_term = $wpdb->esc_like($search_term); //instead of esc_sql()
        $search_term = ' \'%' . $search_term . '%\'';
        $title_filter_relation = (strtoupper($wp_query->get( 'title_filter_relation'))=='OR' ? 'OR' : 'AND');
        $where .= ' '.$title_filter_relation.' ' . $wpdb->posts . '.post_title LIKE '.$search_term;
    }
    return $where;
}

นี่คือตัวอย่างของโค้ดที่ใช้งานจริงสำหรับประเภทโพสต์ที่ง่ายมาก "faq" โดยที่คำถามคือชื่อของโพสต์:

add_filter('posts_where','title_filter',10,2);
$s1 = new WP_Query( array(
    'post_type' => 'faq',
    'posts_per_page' => -1,
    'title_filter' => $q,
    'title_filter_relation' => 'OR',
    'post_status' => 'publish',
    'orderby'     => 'title', 
    'order'       => 'ASC',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key' => 'faq_answer',
            'value' => $q,
            'compare' => 'LIKE'
        )
    )
));
remove_filter('posts_where','title_filter',10,2);

1
ข้อมูลเชิงลึกที่ดีการเพิ่ม "คิวรี่การสืบค้น" แบบกำหนดเองไปยังคิวรีการสืบค้นที่ส่งไปยังWP_Queryเพื่อให้สามารถเข้าถึงได้ภายในposts_whereตัวกรอง
Tom Auger
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.