WP Query: поиск записей по первой букве заголовка

26 мар. 2018 г., 03:07:44
Просмотры: 15.1K
Голосов: 9

Мне нужно выполнить поиск записей с помощью WP_Query() и выбрать только те записи, которые начинаются с определенной буквы. Я нашел несколько старых постов с фильтрами, которые работали до версии 4.4, но начиная с 4.4 в WP_Query добавили поиск по заголовку.

$q = new WP_Query( array('post_type'=>'post','title'=>'This Song Title') );

Этот код вернет только точные совпадения записей с заголовком "This Song Title".

Мне же нужно получить все записи, которые начинаются, в данном примере, с буквы 'T'.

Я также нашел этот пост, на который так и не дали полноценного ответа. Там есть принятый ответ, но я не понимаю, как он решает вопрос. Как ограничить поиск первой буквой заголовка?

Другие возможности запроса, такие как поиск по комментариям и мета-полям, имеют параметр 'compare' для добавления LIKE% в запросы, но для заголовка такой возможности, похоже, нет.

0
Все ответы на вопрос 1
8
23

Это невозможно сделать напрямую с помощью WP_Query "из коробки", но используя фильтр posts_where для поиска пользовательского аргумента в WP_Query, можно добавить такую функциональность.

Предположим, что starts_with — это имя аргумента, который мы хотим использовать. Мы можем отфильтровать posts_where, чтобы добавить условие WHERE, ограничивающее результаты только теми, которые начинаются с заданного значения, если starts_with был установлен в запросе:

function wpse_298888_posts_where( $where, $query ) {
    global $wpdb;

    $starts_with = esc_sql( $query->get( 'starts_with' ) );

    if ( $starts_with ) {
        $where .= " AND $wpdb->posts.post_title LIKE '$starts_with%'";
    }

    return $where;
}
add_filter( 'posts_where', 'wpse_298888_posts_where', 10, 2 );

После добавления этого фильтра мы можем выполнять запросы следующим образом:

$query = new WP_Query( array(
    'starts_with' => 'M',
) );

Это вернет все записи, начинающиеся с буквы "M".

Если вы хотите фильтровать основной запрос, вы также можете использовать этот аргумент в pre_get_posts:

function wpse_298888_pre_get_posts( $query ) {
    if ( $query->is_main_query() ) {
        $query->set( 'starts_with', 'M' );
    }
}
add_action( 'pre_get_posts', 'wpse_298888_pre_get_posts' );
26 мар. 2018 г. 11:42:50
Комментарии

Это работает идеально, но я внес одно изменение, которое может помочь другим. Я использовал REGEXP вместо LIKE, чтобы можно было объединить заголовки, начинающиеся с цифр 0-9, в одну группу.

$where .= " AND $wpdb->posts.post_title REGEXP '^$starts_with'";
Mark Mark
26 мар. 2018 г. 22:07:54

Можно ли сделать наоборот — выбрать все записи и/или страницы, которые не начинаются с определенной буквы/строки? Я хочу исключить из результатов поиска определенные страницы, чьи заголовки начинаются с одного и того же слова, но хочу оставить это открытым на случай, если таких страниц станет больше, вместо использования статических ID. Это не записи, поэтому у них нет меток или категорий.

Yami Medina Yami Medina
18 дек. 2018 г. 23:19:49

Просто замените LIKE в первом блоке кода на NOT LIKE.

Jacob Peattie Jacob Peattie
19 дек. 2018 г. 01:42:54

Похоже, это не работает. Получаю 'критическую ошибку' в WordPress.

Siyah Siyah
28 апр. 2020 г. 22:57:25

Я дважды проверил и не вижу проблем в коде. Если вы не скопировали этот код точно, скорее всего, у вас где-то синтаксическая ошибка в вашем коде.

Jacob Peattie Jacob Peattie
29 апр. 2020 г. 03:17:39

как также добавить пагинацию?

Vincenzo Piromalli Vincenzo Piromalli
7 мар. 2021 г. 22:10:24

@VincenzoPiromalli Если вы фильтруете основной запрос с помощью метода pre_get_posts, то обычная пагинация будет работать корректно.

Jacob Peattie Jacob Peattie
8 мар. 2021 г. 02:44:40

Просто имейте в виду, что если у вас заголовки на сложном языке с диакритическими знаками, результат может быть неточным. Кодировка базы данных для поля заголовка также играет большую роль. Даже в этом случае результат может быть не идеальным. Кроме того, я бы экранировал строку, которую вы передаёте, с помощью чего-то вроде: mb_substr($starts_with, 0, 1) // для CH и двойных букв, а также $wpdb->esc_like()

2046 2046
4 мар. 2023 г. 20:35:29
Показать остальные 3 комментариев