Hugh's Blog

WordPress 搜索添加自定义字段

 

昨天工作需要修改 WordPress 搜索功能,就是在搜索时把 post_excerpt 也添加到查询当中,用的是 wordpress 自带 pre_get_posts 的 api,添加到 add_action 就行,想要添加其他自定义字段也是类似的。

把代码添加到 functions.php中

/* add excerpt search */
add_action('pre_get_posts', 'jc_woo_search_pre_get_posts');
function jc_woo_search_pre_get_posts($query)
{
    if (is_search()) {
        add_filter('posts_join', 'jc_search_post_join'); // ingore this
        add_filter('posts_where', 'jc_search_post_excerpt');
    }
}

function jc_search_post_excerpt($where = '')
{
    global $wpdb;
    global $wp_the_query;

    if (empty($wp_the_query->query_vars['wc_query']) && empty($wp_the_query->query_vars['s'])) {
        return $where;
    }
 
    $where = preg_replace(
        "/post_title LIKE ('%[^%]+%')/",
        "post_title LIKE $1) OR (" . $wpdb->prefix . "posts.post_excerpt LIKE $1 ",
        $where
    );
    return $where;
}
/* end search */

中途容易出错的是 where 语句,可以先把 where 语句输出来,然后再输出修改后的 where 语句来进行对比,这样容易找出错误,显然 where 语句是用来修改搜索查询时要用来进行对比的字段,类似的还有 posts_join 用法,在查找解决方法过程中找到了另一个类似的插件,作个记录:Search by Product Tag for Woocommerce

2017-06-27

今天有个需求要过滤搜索文章的结果,由于使用了 WooCommerce 插件,要求搜索结果只包含产品,不包含其他任何文章,记录一下。

// pre_get_posts
// 只搜索产品
function my_woocommerce_filter_search($query)
{
    if (!is_admin() && is_search() && $query->is_main_query()) {
        $query->set('post_type', array('product'));
    }
    return $query;
}
add_filter('pre_get_posts', 'my_woocommerce_filter_search');

// wp_post_types
// 去除某个自定义文章类型
function my_remove_custom_type_for_search()
{
    global $wp_post_types;
    if (post_type_exists('custom-type')) {
        $wp_post_types['custom-type']->exclude_from_search = true;
    }
}
add_action('init', 'my_remove_custom_type_for_search', 99);

中途漏了 $query->is_main_query() 这个判断,导致某些内容获取不到,例如头部的菜单显示空白。

2017-06-29

添加 Custom Fields 搜索。

function add_meta_to_search_in_join_function($join)
{
    global $wpdb;
    if (is_search()) {
        $join .= ' LEFT JOIN ' . $wpdb->postmeta . ' ON ' . $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    return $join;
}
add_filter('posts_join', 'add_meta_to_search_in_join_function');

function add_meta_to_search_in_where_function($where)
{
    global $wpdb;
    if (is_search()) {
        $meta_keys = array('m_key_1', 'm_key_2');
        $replace = array();
        foreach ($meta_keys as $key) {
            $replace[] = "(" . $wpdb->postmeta . ".meta_key = '" . $key . "' AND " . $wpdb->postmeta . ".meta_value LIKE $1)";
        }
        $replace = !empty($replace) ? implode(" OR ", $replace) : '';
        $where = preg_replace(
            "/\(\s*" . $wpdb->posts . ".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
            // "(" . $wpdb->posts . ".post_title LIKE $1) OR (" . $wpdb->postmeta . ".meta_value LIKE $1)",
            "(" . $wpdb->posts . ".post_title LIKE $1) OR (" . $replace . ")",
            $where
        );
    }
    return $where;
}
add_filter('posts_where', 'add_meta_to_search_in_where_function');

function add_meta_to_search_in_distinct_function($where)
{
    global $wpdb;
    if (is_search()) {
        return "DISTINCT";
    }
    return $where;
}
add_filter('posts_distinct', 'add_meta_to_search_in_distinct_function');

参考

How to Add custom fields to Woocommerce product search

pre_get_posts

posts_where

posts_join

WordPress Exclude Custom Post Type from Search

Exclude Custom Post Type From Search in WordPress

Search WordPress by Custom Fields without a Plugin