WP_Query với bài post_title THÍCH 'cái gì đó%'


44

Tôi cần phải làm WP_Queryvới một LIKEtrên post_title.

Tôi bắt đầu với điều này thường xuyên 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
    )
); 

Nhưng những gì tôi thực sự muốn làm trông giống như thế này trong 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);

Đầu ra in kết quả tôi đang trích dẫn, nhưng tôi sử dụng thường xuyên <?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>để hiển thị kết quả.
Và đó không phải là làm việc với $wpdb->get_results().

Làm thế nào tôi có thể đạt được những gì tôi mô tả ở đây?

Câu trả lời:


45

Tôi sẽ giải quyết điều này với một bộ lọc trên WP_Query. Một trong đó phát hiện một biến truy vấn bổ sung và sử dụng đó làm tiền tố của tiêu đề.

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;
}

Bằng cách này bạn vẫn có thể gọi WP_Query, bạn chỉ cần chuyển tiêu đề làm wpse18703_titleđối số (hoặc thay đổi tên thành một cái gì đó ngắn hơn).


Điều này là một cách nào đó thiếu $wpdb->prepare().
kaiser

@kaiser: Đã lâu rồi, nhưng tôi nghĩ điều này là không thể prepare(). $wpdb->prepare('LIKE "%s%%"', 'banana')sẽ trở lại "LIKE ''banana'%'", vì vậy chúng tôi phải tự xây dựng truy vấn và thực hiện thoát.
Jan Fabry

1
@JanFabry Rất vui được gặp bạn agaaaaaaaain! :) Ghé qua trò chuyện một lúc nào đó, hm? StopPress sẽ rất vui khi gặp bạn. Về điều đó prepare(). Vâng, đó là khó khăn và tôi đã phải thử điều đó nhiều lần, trước khi tôi có được nó. Từ một cái gì đó tôi vừa thực hiện : $wpdb->prepare( ' AND {$wpdb->posts}.post_title LIKE %s ', esc_sql( '%'.like_escape( trim( $term ) ).'%' ) ). Và tôi khá chắc chắn rằng điều đó esc_sql()là không cần thiết và chỉ là hoang tưởng.
kaiser

Có vẻ như bạn không thể tìm kiếm một chuỗi có '(dấu nháy đơn) bên trong. Tôi đoán đó là vì trốn thoát? Tôi chưa tìm thấy giải pháp nào
Vincent Decaux

19

Giản thể:

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
Vui lòng bao gồm một lời giải thích cùng với mã của bạn.
s_ha_dum

2
Đơn giản hóa tuyệt vời
Timo Huovinen

1
Mã là tôi nghĩ tự giải thích, ít nhất cho tôi. Cảm ơn đã chia sẻ kịch bản hoàn chỉnh.
Hassan Dad Khan

Sử dụng '$ wpdb-> esc_like (' thay vì 'esc_sql (like_escape ('
fdrv

@fdrv Bạn đúng nhưng theo tài liệu wp $ wpdb-> esc_like vẫn cần esc_sql (). Vì vậy, tôi nghĩ rằng mã chính xác sẽ là esc_sql ($ wpdb-> esc_like ($ search_term))
Waqas Bukhary

16

Muốn cập nhật mã này, các bạn đã làm việc cho wordpress 4.0 trở lên vì esc_sql () không được dùng trong 4.0 cao hơn.

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;
}

Phần còn lại của công cụ là như nhau.

Ngoài ra tôi muốn chỉ ra rằng bạn có thể sử dụng biến s trong các đối số WP_Query để chuyển các cụm từ tìm kiếm, điều này cũng sẽ tìm kiếm tiêu đề bài tôi tin.

Như thế này:

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

Chính xác search_prod_titlelà gì? Tôi có nên thay đổi điều này thành một cái gì đó khác?
Antonios Tsimourtos

Từ khi nào bị esc_sqltrục xuất? Không phải vậy. $wpdb->escapelà mặc dù ... developer.wordpress.org/reference/fifts/esc_sql
Jeremy

Lưu ý rằng tham số s cũng tìm kiếm nội dung bài đăng, có thể không phải là mục tiêu mong muốn. =)
Christine Cooper

10

Với một số giải pháp dễ bị tổn thương được đăng ở đây, tôi đi kèm với một phiên bản đơn giản hóa và vệ sinh.

Đầu tiên, chúng tôi tạo một chức năng cho posts_wherebộ lọc cho phép bạn chỉ hiển thị các bài đăng phù hợp với điều kiện cụ thể:

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;
}

Bây giờ chúng tôi thêm cc_search_post_titlevào các đối số truy vấn của chúng tôi:

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

Và cuối cùng bọc bộ lọc xung quanh truy vấn:

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

Sử dụng get_posts ()

Một số chức năng nhất định truy xuất bài đăng không chạy bộ lọc, vì vậy các chức năng lọc bài viết_where bạn đính kèm sẽ không sửa đổi truy vấn. Nếu bạn dự định sử dụng get_posts()để truy vấn bài đăng của mình, bạn cần đặt suppress_filtersthành false trong mảng đối số:

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

Bây giờ bạn có thể sử dụng 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 );

Còn sthông số thì sao?

Các stham số có sẵn:

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

Trong khi thêm cụm từ tìm kiếm của bạn vào stham số hoạt động và nó sẽ tìm kiếm tiêu đề bài viết, nó cũng sẽ tìm kiếm nội dung bài đăng.

Còn về titletham số được thêm vào với WP 4.4 thì sao?

Truyền một thuật ngữ tìm kiếm vào titletham số:

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

Là trường hợp nhạy cảm và LIKE, không %LIKE%. Điều này có nghĩa là tìm kiếm hellosẽ không trả lại bài với tiêu đề Hello Worldhoặc Hello.


Xuất sắc. Tôi đã tìm kiếm 'post_title' như một tham số và rõ ràng, không tìm thấy gì.
MastaBaba

7

Dựa trên các câu trả lời khác trước tôi, để cung cấp sự linh hoạt trong tình huống bạn muốn tìm kiếm một bài đăng có chứa một từ trong trường meta HOẶC trong tiêu đề của bài đăng, tôi đưa ra tùy chọn đó thông qua đối số "title_filter_relation." Trong triển khai này, tôi chỉ cho phép các đầu vào "HOẶC" hoặc "VÀ" với mặc định là "VÀ".

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;
}

Đây là một ví dụ về mã đang hoạt động cho một loại bài "faq" rất đơn giản trong đó câu hỏi là chính tiêu đề bài viết:

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
Thông tin chi tiết tốt, thêm "vars truy vấn" tùy chỉnh vào đối số truy vấn được truyền WP_Queryvào để có thể truy cập chúng trong posts_wherebộ lọc.
Tom Auger
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.