Как выполнить поиск только по заголовкам постов?

Ссылка скопирована
1 ответ

Есть скрипт, который ищет записи содержащие определенное слово.
Как доработать скрипт, чтобы поиск был только по заголовкам записей?
Текущий скрипт:

$args = array(   'posts_per_page' => -1,   'post_type'      => array( 'jobs', 'services' ),   's'              => 'инже', );  $search = new WP_Query( $args );

$args = array( 'posts_per_page' => -1, 'post_type' => array( 'jobs', 'services' ), 's' => 'инже', ); $search = new WP_Query( $args );

Результат, который мне нужен SQL запросом:
SELECT * FROM posts WHERE post_title LIKE '%инже%'

Дополнительно:

https://wordpress.stackexchange.com/questions/1870...
https://stackoverflow.com/questions/62350261/how-t...

Решение:
Спасибо Dymok за наводку)

1. Добавляем в functions.php темы

// find_posts_by_title_part — название функции, можно заменить на любое свое название // title_part — название нового параметра для WP_Query() function find_posts_by_title_part( $where, &$wp_query ){     global $wpdb;      if ( $title_part = $wp_query->get( 'title_part' ) ) {         $param = esc_sql( $wpdb->esc_like( $title_part ) );         $sql .= " AND " . $wpdb->posts . ".post_title LIKE '%" . $param . "%'";     }      return $sql; } add_filter( 'posts_where', 'find_posts_by_title_part', 10, 2 );

// find_posts_by_title_part — название функции, можно заменить на любое свое название // title_part — название нового параметра для WP_Query() function find_posts_by_title_part( $where, &$wp_query ){ global $wpdb; if ( $title_part = $wp_query->get( 'title_part' ) ) { $param = esc_sql( $wpdb->esc_like( $title_part ) ); $sql .= " AND " . $wpdb->posts . ".post_title LIKE '%" . $param . "%'"; } return $sql; } add_filter( 'posts_where', 'find_posts_by_title_part', 10, 2 );

2. Пишем запрос к базе данных через WP_Query()

$args = array(   'posts_per_page' => -1,   'post_type'      => array('projects', 'jobs', 'services'),   'order'          => 'ASC',   'title_part'     => 'инже', );  $query = new WP_Query( $args );

$args = array( 'posts_per_page' => -1, 'post_type' => array('projects', 'jobs', 'services'), 'order' => 'ASC', 'title_part' => 'инже', ); $query = new WP_Query( $args );

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Павел Админов Ответ

Чтобы поиск WordPress искал только по заголовкам, нужно изменить SQL-условие поиска через фильтр posts_search. Стандартный поиск ищет по post_title, post_excerpt и post_content, поэтому простого параметра в WP_Query для «только заголовки» нет.

Пример для основного поиска на фронтенде:

add_filter('posts_search', function ($search, WP_Query $query) {
    global $wpdb;
 
    if (is_admin() || ! $query->is_main_query() || ! $query->is_search()) {
        return $search;
    }
 
    $search_term = $query->get('s');
 
    if ($search_term === '') {
        return $search;
    }
 
    $like = '%' . $wpdb->esc_like($search_term) . '%';
 
    return $wpdb->prepare(" AND {$wpdb->posts}.post_title LIKE %s ", $like);
}, 10, 2);

add_filter('posts_search', function ($search, WP_Query $query) { global $wpdb; if (is_admin() || ! $query->is_main_query() || ! $query->is_search()) { return $search; } $search_term = $query->get('s'); if ($search_term === '') { return $search; } $like = '%' . $wpdb->esc_like($search_term) . '%'; return $wpdb->prepare(" AND {$wpdb->posts}.post_title LIKE %s ", $like); }, 10, 2);

Если поиск должен работать только для конкретного типа записи, добавьте условие по post_type:

add_action('pre_get_posts', function (WP_Query $query) {
    if (! is_admin() && $query->is_main_query() && $query->is_search()) {
        $query->set('post_type', ['post']);
    }
});

add_action('pre_get_posts', function (WP_Query $query) { if (! is_admin() && $query->is_main_query() && $query->is_search()) { $query->set('post_type', ['post']); } });

Для точного совпадения заголовка вместо LIKE можно использовать =, но тогда частичные запросы перестанут находить записи. Код лучше держать в дочерней теме или mu-plugin. После внедрения проверьте поиск по слову, которое есть только в контенте: такая запись больше не должна появляться в результатах.

Глобально такой фильтр лучше подключать только на время конкретного запроса, иначе вы измените поиск на всём сайте: в админке, виджетах, REST API и других местах. Поэтому безопаснее сделать отдельный параметр, например title_part, и реагировать только на него.

add_filter('posts_where', function ($where, WP_Query $query) {
    global $wpdb;
 
    $title_part = $query->get('title_part');
    if ($title_part === '') {
        return $where;
    }
 
    $where .= $wpdb->prepare(
        " AND {$wpdb->posts}.post_title LIKE %s",
        '%' . $wpdb->esc_like($title_part) . '%'
    );
 
    return $where;
}, 10, 2);
 
$search = new WP_Query([
    'post_type'      => ['jobs', 'services'],
    'posts_per_page' => -1,
    'title_part'     => 'инже',
]);

add_filter('posts_where', function ($where, WP_Query $query) { global $wpdb; $title_part = $query->get('title_part'); if ($title_part === '') { return $where; } $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_title LIKE %s", '%' . $wpdb->esc_like($title_part) . '%' ); return $where; }, 10, 2); $search = new WP_Query([ 'post_type' => ['jobs', 'services'], 'posts_per_page' => -1, 'title_part' => 'инже', ]);

Параметр s здесь лучше не использовать, потому что WordPress ищет не только по заголовку, но и по контенту. Если записей много, не ставьте posts_per_page => -1: добавьте пагинацию или лимит. Для точного поиска по началу заголовка замените шаблон на $wpdb->esc_like($title_part) . '%'.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно