带有“ post_title LIKE'something%'”的WP_Query?


44

我需要做一个WP_QueryLIKEpost_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);

输出显示我期望的结果,但是我使用常规<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>显示结果。
那是行不通的$wpdb->get_results()

我怎样才能达到我在这里描述的目的?

Answers:


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 2012年

@kaiser:已经好久了,但是我认为不可能prepare()$wpdb->prepare('LIKE "%s%%"', 'banana')将返回"LIKE ''banana'%'",因此我们必须自己构造查询,并且也要进行转义。
Jan Fabry 2012年

1
@JanFabry很高兴再次见到你!:)聊天吧,嗯?StopPress很高兴见到您。关于那个prepare()。是的,这很棘手,在解决之前,我不得不尝试几次。从我刚做的事情中:$wpdb->prepare( ' AND {$wpdb->posts}.post_title LIKE %s ', esc_sql( '%'.like_escape( trim( $term ) ).'%' ) )。而且我敢肯定,这esc_sql()是不必要的,只是偏执。
kaiser 2012年

看来您无法搜索带有'(撇号)的字符串。我想是因为逃跑了吗?我尚未找到解决方案
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 2013年

2
极大简化
Timo Huovinen 2014年

1
我认为代码是自我解释的,至少对我而言。感谢您分享完整的脚本。
哈桑·达汗

使用'$ 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

想要更新此代码,因为esc_sql()在4.0或更高版本中已弃用,因此您为wordpress 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;
}

其余的东西都是一样的。

我还要指出的是,您可以在WP_Query参数中使用s变量来传递搜索词,我相信也会搜索帖子标题。

像这样:

$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_sql?不是。$wpdb->escape虽然... developer.wordpress.org/reference/functions/esc_sql
Jeremy

请注意,s参数也会搜索帖子内容,这可能不是期望的目标。=)
克里斯汀·库珀

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在参数数组中将其设置为false:

$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参数work中时,它将搜索帖子标题,还将搜索帖子内容。

titleWP 4.4中添加的参数呢?

将搜索字词传递给title参数:

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

是否区分大小写LIKE,而不是%LIKE%。这意味着搜索hello将不会返回标题为Hello World或的帖子Hello


优秀的。我一直在寻找'post_title'作为参数,显然没有找到任何东西。
MastaBaba

7

基于我之前的其他答案,为了在您要搜索包含元字段或帖子标题中包含单词的帖子的情况下提供灵活性,我通过参数“ title_filter_relation”给出该选项。在此实现中,我仅允许使用默认值为“ AND”的“ OR”或“ 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;
}

这是一个非常简单的帖子类型“常见问题”的代码示例,其中问题是帖子标题本身:

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
深入了解,将自定义“查询变量”添加到传递给查询的args WP_Query,以便能够在posts_where过滤器中访问它们。
汤姆·奥格
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.