Вопрос или проблема
Мне нужно изменить или создать WP_Query, который будет искать поисковый термин как в заголовке поста, так и в пользовательском поле (называемом ‘my_field’).
Я читал и пытался несколько часов, но возвращаюсь к этому коду (ниже), который, увы, только ищет в ‘my_field’ и не учитывает заголовок поста.
function my_pre_get_posts_2( $query ) {
if ( is_admin() && $query->is_main_query() && $query->query['post_type'] === 'post' && isset($query->query['s']) ) {
$search_word = $query->query['s'];
$args = array(
//'s' => $search_word, //Если я включаю эту строку, WP запрос, похоже, выполняет поиск по заголовку поста и my_field. Если я закомментирую эту строку, WP запрос ищет только в my_field
'post_type' => 'post',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'my_field',
'value' => $search_word,
'compare' => 'IN'
),
array(
'key' => 'post_title',
'value' => $search_word,
'compare' => 'IN',
)
)
);
//$query = new WP_Query( $args ); //Нужно изменить существующий WP_Query
$query->init();
$query->parse_query($args);
}
}
add_action( 'pre_get_posts', 'my_pre_get_posts_2' );
Причина, по которой мне нужно это сделать, заключается в том, что мне нужно изменить поведение кнопки ‘Поиск постов’ на странице ‘Все посты’ (админка), чтобы независимо от того, что ищет администратор, возвращались посты, которые имеют совпадающий заголовок поста или значение my_field.
Чтобы выполнить поиск с логическим оператором ИЛИ, я пытался объединить результаты WP_Query, как показано здесь – Могу ли я объединить 2 новых WP_Query($variable)? – в ответе guidod. Однако это не было хорошим решением и привело к непредсказуемому поведению.
Правильное решение, которое я нашел, заключалось в том, чтобы изменить запрос с помощью пользовательского запроса WP, как показано в коде (который требует некоторых изменений) здесь – http://codex.wordpress.org/Custom_Queries ..
Чтобы искать как в заголовке поста, так и в пользовательском поле, используя wp_query
, вы не можете напрямую искать в поле post_title
, поскольку это не пользовательское поле. Вместо этого вы можете использовать комбинацию параметров meta_query
и post_title
для достижения желаемых результатов.
function my_pre_get_posts_2( $query ) {
if ( is_admin() && $query->is_main_query() && $query->query['post_type'] === 'post' && isset($query->query['s']) ) {
$search_word = $query->query['s'];
$args = array(
'post_type' => 'post',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'my_field',
'value' => $search_word,
'compare' => 'LIKE' // Используйте LIKE для сопоставления частичных строк в пользовательских полях
)
),
's' => $search_word, // Поиск по заголовку поста
'posts_per_page' => -1 // Отобразить все соответствующие посты
);
$query->set( 'meta_query', $args['meta_query'] ); // Установить meta_query
$query->set( 's', $args['s'] ); // Установить поисковый термин для заголовка поста
}
}
add_action( 'pre_get_posts', 'my_pre_get_posts_2' );
Ответ или решение
Чтобы создать или изменить WP_Query
для поиска как в заголовках записей, так и в пользовательском поле (в нашем случае — это поле с именем 'my_field'
), вам потребуется скорректировать вашу текущую функцию, чтобы включить обоих источника поиска.
Шаг 1: Обновление мета-запроса
Для поиска, включающего данные как из заголовка записи, так и из пользовательского поля, вы можете использовать параметр meta_query
для выполнения запроса к метаданным и параметр 's'
для поиска по заголовкам. Ключевой момент — необходимо задать корректное использование оператора сравнения и установить правильные параметры в запросе.
Шаг 2: Использование функции pre_get_posts
Ниже приведен пример кода, который нужно реализовать. Этот код будет модифицировать основной запрос в админке WordPress, чтобы он искал как в заголовках, так и в пользовательских полях:
function my_pre_get_posts_2( $query ) {
// Проверка, что это админка и основной запрос
if ( is_admin() && $query->is_main_query() && $query->query['post_type'] === 'post' && isset($query->query['s']) ) {
$search_word = $query->query['s'];
$meta_query = array(
'relation' => 'OR',
array(
'key' => 'my_field',
'value' => $search_word,
'compare' => 'LIKE' // Используем LIKE для поиска подстроки
),
array(
'key' => 'post_title',
'value' => $search_word,
'compare' => 'LIKE' // Используем LIKE для поиска подстроки в заголовке
)
);
// Настраиваем запрос
$query->set( 'meta_query', $meta_query ); // Устанавливаем мета-запрос
$query->set( 's', '' ); // Очищаем стандартный поиск, чтобы избежать конфликтов
}
}
add_action( 'pre_get_posts', 'my_pre_get_posts_2' );
Пояснение кода:
-
Проверка условий: Мы проверяем, что функция вызывается в админке, это основной запрос и что запрашиваемый тип записей —
'post'
. -
Создание
meta_query
: Создается массивmeta_query
, который включает два условия:- Поиск по полю
my_field
с использованием оператораLIKE
для поиска подстроки. - Поиск по заголовку поста с тем же оператором.
- Поиск по полю
-
Настройка запроса:
- С помощью
$query->set()
мы устанавливаем новый массивmeta_query
для выполнения пользовательского запроса. - Очищаем стандартный параметр поиска (
's'
), чтобы избежать конфликтов и неправомерных совмещения условий поиска.
- С помощью
Результат
Этот подход обеспечивает адекватный ответ на запрос от администратора в разделе «Все записи», возвращая все посты, которые соответствуют критериям как по заголовку, так и по пользовательскому полю. Подобное использование WordPress Query API позволяет вам адаптировать поведение системы под специфические задачи без лишних усилий.
Рекомендации по оптимизации
- Оптимизация поиска: Следите за производительностью, если ваша база данных содержит большое число записей. Рассмотрите возможность применения индексов для метаполей, с которыми вы часто работаете.
- Проверка на правильность: Убедитесь, что вводимые данные корректны и проводите валидацию для предотвращения SQL-инъекций и других уязвимостей.
Таким образом, с помощью данного кода и подхода вы сможете создавать эффективные и оптимизированные запросы к данным в WordPress, что значительно упростит управление контентом в административной панели.