Поиск по алфавиту и содержимому в WordPress?

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

Добрый день! Вопрос следующего характера! Допустим, есть страница на wordpress на странице есть поиск по алфавиту, но хотелось бы сделать еще поиск по содержимому. Как такое можно реализовать? Понятно, что все идет к wp_query, на вот как сделать так, что-бы возвращалась информация и из таблицы с содержимым?

Заранее благодарен за ответ.

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

Добрый день! Ищем информацию в таблицах!

Поиск по алфавиту и содержимому в Wordpress?

Прилагаю скрин того, что мы ищем!
Есть, алфавитный поиск! Как сделать там, что-бы искало не только по алфавитному но по примеру таблицы, которая на скриншоте?

  • <?php the_title(); ?>

    • А
    • Б
    • В
    • Г
    • Д
    • Е
    • Ж
    • З
    • И
    • К
    • Л
    • М
    • Н
    • О
    • П
    • Р
    • С
    • Т
    • У
    • Ф
    • Х
    • Ц
    • Ч
    • Ш
    • Щ
    • Э
    • Ю
    • Я
    • ВСЕ

    <?php
    function getRaoMemberTemplate( $title, $content ) {
    $result = <<<"END"

    $title
    $content

    END;
    return ( $result );
    }

    $p = isset( $_GET[ 'p' ] ) ? $_GET[ 'p' ] : 'А';

    $like = isset( $_GET[ 'like' ] ) ? $_GET[ 'like' ] : NULL;
    if(is_string($like)) {
    $like = trim(mb_strtolower($like));
    }

    global $wpdb;
    $query = "SELECT p.* FROM $wpdb->posts AS p inner join $wpdb->postmeta AS pm ON pm.post_id = p.id WHERE post_type = 'page' AND pm.meta_key = '_wp_page_template' AND pm.meta_value = 'template/templ-online-reg-psy111.php'";

    if(is_string($like)) {
    $likeValue = '%' . $wpdb->esc_like($like) . '%';
    $likeQuery = " AND LOWER( post_content ) LIKE %s";
    $query .= $wpdb->prepare($likeQuery, $likeValue);
    }

    $rows = $wpdb->get_results( $query );
    foreach($rows as $post){
    echo getRaoMemberTemplate( $post->post_title, $post->post_content );
    }

    if(!$rows) {
    echo "Не найдено: '" . ($like ? $like: $p) . "'";
    }
    ?>

    Вот такой вот код! С ним, поиск по полям работает, но вешается алфавитный, возвращаю назад старый код, работает алфавитный и не работает по полям.

  • Ответы:

    А что ищете то? Есть шикарный плагин Search & Filter - от Code Amp
    https://ru.wordpress.org/plugins/search-filter/
    И более крутой но платный аналог

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

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

    Заказать помощь
    Лучший ответ
    1
    Редакция Security Ответ

    Алфавитный фильтр и поиск по содержимому нужно объединять в одном запросе, а не переключать один код на другой. В вашем примере есть ещё одна опасная деталь: GET-параметр p лучше не использовать, потому что в WordPress p уже занят под ID записи. Из-за этого можно получить странное поведение запроса и конфликт с основным роутингом. Назовите параметр буквы, например letter, а поисковую строку q или like.

    Если страницы выбираются по шаблону, а искать нужно и по заголовку, и по содержимому страницы, и по данным из произвольных полей, можно сделать один SQL-запрос через wpdb. Важно использовать prepare и esc_like, иначе поиск легко превратить в SQL-инъекцию. Ниже пример для ваших страниц с шаблоном template/templ-online-reg-psy111.php.

    global $wpdb;
     
    $letter = isset($_GET['letter']) ? sanitize_text_field(wp_unslash($_GET['letter'])) : '';
    $letter = mb_substr($letter, 0, 1);
    $q = isset($_GET['q']) ? trim(sanitize_text_field(wp_unslash($_GET['q']))) : '';
     
    $joins = ' INNER JOIN ' . $wpdb-&gt;postmeta . ' AS pm_tpl ON pm_tpl.post_id = p.ID ';
    $where = array(
        $wpdb-&gt;prepare('p.post_type = %s', 'page'),
        $wpdb-&gt;prepare('p.post_status = %s', 'publish'),
        $wpdb-&gt;prepare('pm_tpl.meta_key = %s', '_wp_page_template'),
        $wpdb-&gt;prepare('pm_tpl.meta_value = %s', 'template/templ-online-reg-psy111.php'),
    );
     
    if ($letter !== '' &amp;&amp; $letter !== 'Все') {
        $where[] = $wpdb-&gt;prepare('p.post_title LIKE %s', $wpdb-&gt;esc_like($letter) . '%');
    }
     
    if ($q !== '') {
        $joins .= ' LEFT JOIN ' . $wpdb-&gt;postmeta . ' AS pm_search ON pm_search.post_id = p.ID ';
        $like = '%' . $wpdb-&gt;esc_like($q) . '%';
        $where[] = $wpdb-&gt;prepare(
            '(p.post_title LIKE %s OR p.post_content LIKE %s OR pm_search.meta_value LIKE %s)',
            $like,
            $like,
            $like
        );
    }
     
    $sql = 'SELECT DISTINCT p.* FROM ' . $wpdb-&gt;posts . ' AS p ' . $joins . ' WHERE ' . implode(' AND ', $where) . ' ORDER BY p.post_title ASC';
    $rows = $wpdb-&gt;get_results($sql);

    global $wpdb; $letter = isset($_GET['letter']) ? sanitize_text_field(wp_unslash($_GET['letter'])) : ''; $letter = mb_substr($letter, 0, 1); $q = isset($_GET['q']) ? trim(sanitize_text_field(wp_unslash($_GET['q']))) : ''; $joins = ' INNER JOIN ' . $wpdb-&gt;postmeta . ' AS pm_tpl ON pm_tpl.post_id = p.ID '; $where = array( $wpdb-&gt;prepare('p.post_type = %s', 'page'), $wpdb-&gt;prepare('p.post_status = %s', 'publish'), $wpdb-&gt;prepare('pm_tpl.meta_key = %s', '_wp_page_template'), $wpdb-&gt;prepare('pm_tpl.meta_value = %s', 'template/templ-online-reg-psy111.php'), ); if ($letter !== '' &amp;&amp; $letter !== 'Все') { $where[] = $wpdb-&gt;prepare('p.post_title LIKE %s', $wpdb-&gt;esc_like($letter) . '%'); } if ($q !== '') { $joins .= ' LEFT JOIN ' . $wpdb-&gt;postmeta . ' AS pm_search ON pm_search.post_id = p.ID '; $like = '%' . $wpdb-&gt;esc_like($q) . '%'; $where[] = $wpdb-&gt;prepare( '(p.post_title LIKE %s OR p.post_content LIKE %s OR pm_search.meta_value LIKE %s)', $like, $like, $like ); } $sql = 'SELECT DISTINCT p.* FROM ' . $wpdb-&gt;posts . ' AS p ' . $joins . ' WHERE ' . implode(' AND ', $where) . ' ORDER BY p.post_title ASC'; $rows = $wpdb-&gt;get_results($sql);

    Дальше выводите результат тем же шаблоном, который у вас уже есть:

    foreach ($rows as $row) {
        echo getRaoMemberTemplate($row-&gt;post_title, apply_filters('the_content', $row-&gt;post_content));
    }
     
    if (! $rows) {
        echo 'Не найдено: ' . esc_html($q !== '' ? $q : $letter);
    }

    foreach ($rows as $row) { echo getRaoMemberTemplate($row-&gt;post_title, apply_filters('the_content', $row-&gt;post_content)); } if (! $rows) { echo 'Не найдено: ' . esc_html($q !== '' ? $q : $letter); }

    Логика такая: если выбрана буква, добавляется условие post_title LIKE А%. Если введена поисковая фраза, добавляется поиск по заголовку, post_content и meta_value. Если выбрано Все, буквенное условие не добавляется, и поиск идёт по всему набору страниц с нужным шаблоном. DISTINCT нужен потому, что у одной страницы может быть несколько строк postmeta, и без DISTINCT одна и та же страница может повториться.

    • Если таблица находится прямо в контенте страницы, достаточно post_content LIKE.
    • Если данные таблицы лежат в ACF или других произвольных полях, нужен LEFT JOIN по postmeta, как в примере.
    • Если записей много, такой LIKE-поиск будет медленным. Тогда лучше делать отдельный индекс, отдельный тип записи или специализированный поиск.

    Для небольшого справочника на 10-100 страниц этот вариант нормальный. Главное не смешивать параметр p, не собирать SQL из сырых $_GET и не делать два независимых запроса, которые перетирают результат друг друга.

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

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

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

    комментарий

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

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