Добавить поиск по собственным полям в WordPress

Пользовательские поля в WordPress очень удобный инструмент для работы с данными, их можно добавить с помощью плагина или в ручную.

Есть одна проблема при использовании кастомных полей, по ним не возможен поиск с помощью стандартного функционала WordPress.

Для исправления этого мы изменим поисковый запрос, добавив в него пользовательские поля.

В этой статье мы добавляем пользовательские поля к товарам на Woocommerce.

В примере ниже мы не будем использовать плагины, а просто добавим определенный код к functions.php. Это решение я подсмотрел у Adam Balée.

Связываем таблицы

Данные пользовательских полей в базе данных храниться в таблице postmeta. Но функция поиска WordPress по умолчанию настроена только на поиск в таблице posts. Нам необходимо включить данные пользовательских полей в поиск, для этого свяжем таблицы posts и postmeta для этого используем фильтр posts_join:

add_filter('posts_join', 'custom_fields_search_join' );

function custom_fields_search_join( $join ) {
    global $wpdb;

    if ( is_search() ) {
        $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }

    return $join;
}

Изменяем поисковый запрос WordPress

Далее, чтобы включить наши собственные поля в поисковый запрос, нам нужно его изменить. Для этого воспользуемся фильтром posts_where который позволяет изменять запросы и создавать свои произвольные условия:

add_filter( 'posts_where', 'custom_fields_search_where' );

function cf_search_where( $where ) {
    global $wpdb;

    if ( is_search() ) {
        $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)", $where );
    }

    return $where;
}

Отсеиваем дубли

И на последок, нам нужно добавить ключевое слово DISTINCT (оно позволяет выбирать только уникальные значения из базы данных) в SQL-запрос, чтобы предотвратить возврат дубликатов. Воспользуемся WordPress фильтром posts_distinct:

add_filter( 'posts_distinct', 'custom_fields_search_distinct' );

function custom_fields_search_distinct( $where ) {
    global $wpdb;

    if ( is_search() ) {
        return "DISTINCT";
    }

    return $where;
}

На этом все, просто добавьте весь код выше в файл functions.php вашей темы и поиск по пользовательским полям заработает  не только в фронтэнд части сайта, но и в админке.

Хостинг для ваших проектов