我需要用WP_Query上的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);


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

我如何实现在此描述的内容?

#1 楼

我会用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年11月6日15:46

@kaiser:已经很长时间了,但是我认为使用prepare()无法实现。 $ wpdb-> prepare('LIKE“%s %%”','banana')将返回“ LIKE” banana'%'“,因此我们必须自己构造查询,并进行转义。

– Jan Fabry
2012年11月6日19:36

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

– kaiser
2012年11月7日10:35



看来您无法搜索带有'(撇号)的字符串。我想是因为逃跑了吗?我尚未找到解决方案

– Vincent Decaux
18年8月30日在15:10

#2 楼

简体:
function title_filter( $where, &$wp_query )
{
    global $wpdb;
    // 2. pull the custom query in here:
    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,
    // 1. define a custom query var here to pass your term through:
    '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 );
return $wp_query;


评论


请在代码中附上说明。

– s_ha_dum
13年4月19日在13:49

大大简化

–提莫·霍维宁(Timo Huovinen)
2014年11月10日19:52

我认为代码是自我解释的,对我来说至少。感谢您分享完整的脚本。

–哈桑·达汗(Hassan Dad Khan)
17年8月8日在6:55

使用'$ wpdb-> esc_like('代替'esc_sql(like_escape('

–fdrv
18年2月19日在17:16

remove_filter仅使用3个参数,最后一个可以删除。

–斯卡托克斯
20年6月24日在15:03

#3 楼

想要更新此代码,因为esc_sql()在4.0或更高版本中已弃用,因此您在wordpress 4.0及更高版本上使用的代码。

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

像这样:

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


评论


究竟search_prod_title是什么?我应该将其更改为其他内容吗?

– Antonios Tsimourtos
17 Mar 24 '17 at 20:20

从什么时候开始esc_sql的描述?不是。 $ wpdb->转义是... developer.wordpress.org/reference/functions/esc_sql

–杰里米
18年2月2日在17:36

注意,s参数也搜索帖子内容,这可能不是期望的目标。 =)

–克里斯汀·库珀♦
18年4月19日在10:43

不推荐使用like_escape 4.0.0使用wpdb :: esc_like

–空脑
20 Mar 14'6:40



#4 楼

在这里发布了一些易受攻击的解决方案后,我提供了一些简化和净化的版本。

首先,我们为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参数中时,它将搜索帖子标题,还将搜索帖子内容。

与WP 4.4一起添加的title参数呢?

将搜索项传递到title参数:

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


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

评论


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

– MastaBaba
19/09/13在15:55

我在wp查询或获取帖子时遇到错误:“ E_WARNING文件»class-wp-hook.php«在第288行出错:cc_post_title_filter()的参数2应该是参考,给定值

– Elkrat
20 Mar 3 '20 at 17:28

@Elkrat从cc_post_title_filter的&$ wp_query中删除&。

–战斗者
20-5-5在21:04

#5 楼

基于我之前的其他答案,为了在您要搜索包含元字段或帖子标题中包含单词的帖子的情况下提供灵活性,我通过参数“ 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;
}


评论


深入了解,将自定义“查询变量”添加到传递给WP_Query的查询args中,以便能够在posts_where过滤器中访问它们。

–汤姆·俄格(Tom Auger)
17年2月4日在21:32