Вопрос или проблема
Возможно ли искать пользовательский тип записи product
по _sku
или другому пользовательскому метаполю с помощью текстового поля ввода?
Я не хочу использовать плагины, мне нужна пользовательская функция WP.
Я нашел это решение для поиска только по заголовку:
function __search_by_title_only($search, &$wp_query)
{
global $wpdb;
if (empty($search))
return $search; // пропустить обработку - нет поискового запроса
$q = $wp_query->query_vars;
$n = !empty($q['exact']) ? '' : '%';
$search =
$searchand = '';
foreach ((array) $q['search_terms'] as $term) {
$term = esc_sql(like_escape($term));
$search .= "{$searchand}($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
$searchand = ' AND ';
}
if (!empty($search)) {
$search = " AND ({$search}) ";
if (!is_user_logged_in())
$search .= " AND ($wpdb->posts.post_password = '') ";
}
return $search;
}
add_filter('posts_search', '__search_by_title_only', 500, 2);
… но мне нужна похожая функция для метаполей (_sku
и _author
).
Спасибо!
Это может сработать, хотя не тестировалось.
Сначала добавьте это, чтобы присоединить таблицу postmeta:
add_filter( 'posts_join', 'search_filters_join', 501, 2 );
function search_filters_join( $join, $query ) {
global $wpdb;
if ( empty( $query->query_vars[ 'post_type' ] ) || $query->query_vars[ 'post_type' ] !== 'product' ) {
return $join; // пропустить обработку
}
if ( ($this->is_ajax_search() || $this->is_search_page()) && !is_admin() ) {
$join .= " INNER JOIN $wpdb->postmeta AS customsearch ON ( $wpdb->posts.ID = customsearch.post_id )";
}
return $join;
}
Затем измените переменную $search
в цикле foreach, чтобы включить следующее (в этом примере показан _sku
, просто добавьте _author
в другой раздел OR
, если хотите искать и это):
$search .= "{$searchand} (($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR (customsearch.meta_key='_sku' AND customsearch.meta_value LIKE '{$n}{$term}{$n}'))";
Ответ или решение
Для реализации поиска записей пользовательского типа product
по мета полям, например, _sku
и _author
, мы можем создать собственную функцию в WordPress без использования плагинов. В данном случае вы хотите разрабатывать решение, которое будет встраиваться в ваш код, и для выполнения этой задачи нам нужно внести изменения в SQL-запросы WordPress.
Теория
WordPress хранит мета-данные в таблице wp_postmeta
, и для поиска по этим мета-данным нам необходимо изменить SQL-запросы, чтобы присоединить эту таблицу и искать в ней по конкретным ключам. Для этого мы можем использовать два фильтра: posts_join
, чтобы правильно объединить таблицу wp_postmeta
, и posts_search
, чтобы добавить условия поиска по мета-данным.
Пример
Вот последовательность шагов, которые помогут вам добиться желаемого результата:
- Добавьте фильтр для соединения с таблицей мета-данных
wp_postmeta
:
add_filter('posts_join', 'custom_search_join', 10, 2);
function custom_search_join($join, $query) {
global $wpdb;
if ( !is_admin() && $query->is_main_query() && !empty($query->query_vars['s']) && $query->query_vars['post_type'] == 'product' ) {
$join .= " INNER JOIN {$wpdb->postmeta} AS custom_meta ON ({$wpdb->posts}.ID = custom_meta.post_id)";
}
return $join;
}
- Фильтруйте условие поиска, чтобы включать поиск по мета-полям
_sku
и_author
:
add_filter('posts_search', 'custom_search_where', 10, 2);
function custom_search_where($where, $query) {
global $wpdb;
if ( !is_admin() && $query->is_main_query() && !empty($query->query_vars['s']) && $query->query_vars['post_type'] == 'product' ) {
$query = esc_sql(like_escape($query->query_vars['s']));
$where .= " AND (
({$wpdb->posts}.post_title LIKE '%{$query}%')
OR (custom_meta.meta_key='_sku' AND custom_meta.meta_value LIKE '%{$query}%')
OR (custom_meta.meta_key='_author' AND custom_meta.meta_value LIKE '%{$query}%')
)";
}
return $where;
}
Применение
Этот подход предоставляет гибкость в поисковом запросе, позволяя искать конкретные продукты по полям _sku
и _author
. Разработанное решение можно легко встраивать в тему WordPress или в файл функций, если вы создаете собственное решение. Такой подход минимизирует зависимость от плагинов и позволяет сэкономить ресурсы, сохраняя при этом высокую кастомизацию кода.
Кроме того, стоит учитывать производительность: операция поиска по мета-данным потенциально может быть более затратной, чем по стандартным полям, поэтому важно тестировать и мониторить производительность на средах с большим количеством данных.
Заключение
При реализации вышеописанной логики вы получаете возможность запрашивать пользовательские типы записей на основе определенных мета-данных, что может быть особенно полезным для разнообразных проектов, где стандартные функции WordPress не позволяют реализовать необходимую функциональность без углубленного взаимодействия с базой данных. Рекомендую всегда тестировать такие изменения на тестовых средах прежде, чем внедрять их на продуктивные. тон.