CODYSHOP
темы и плагины для WordpressПоиск по сайту – вещь полезная. Однако, по-умолчанию, WordPress производит его не сильно эффективно.
Первое – система не всегда может найти то, что есть по факту. Например, “товар” и “товары” для неё разные вещи. Поиск также ничего не выдаст, если случайно изменена языковая раскладка клавиатуры. Например, если вместо слова вордпресс
введено djhlghtcc
.
Вторая проблема – вопрос релевантности. Даже если получено много результатов, они могут не всегда удовлетворять ожидания. Это довольно глубокая проблема и во многом связана с тематикой сайта.
Не стоит ожидать от встроенного поиска возможностей полноценной поисковой системы. Впрочем, это не значит, что у нас нет выбора. В этой статье хочу привести несколько полезных сниппетов для решения упомянутых и некоторых других интересных задач.
Сниппеты для фронтэнда
Если у вас простая задача, возможно, вместо очередного плагина, лучше использовать несложный код. Вот несколько полезных.
#1 Добавление поиска в меню
После добавления кода в файл function.php в меню вы увидите, что появился новый пункт – форма поиска. Обратите внимание, что вам необходимо установить свой идентификатор расположения меню $args->theme_location
. Обычно он указывается в функции wp_nav_menu
, параметр theme_location
.
add_filter( 'wp_nav_menu_items', 'cody_add_search_box_to_menu', 10, 2 ); function cody_add_search_box_to_menu( $items, $args ) { if( $args->theme_location == 'top' ) $items .= '<li class="menu-item">' . get_search_form( false ) . '</li>'; return $items; }
#2 Подсветка искомых слов в результатах поиска
Данный сниппет подсветит слова из запроса в заголовках, основном контенте и цитатах.
add_filter( 'the_content', 'cody_search_results_hightlight' ); add_filter( 'the_title', 'cody_search_results_hightlight' ); add_filter( 'the_excerpt', 'cody_search_results_hightlight' ); function cody_search_results_hightlight( $text ){ $colors = array( '', '#ffeb3b', '#CDDC39', '#7fdce8', '#edb5f7' ); if ( ! is_search() || is_admin() ) return $text; $query_terms = get_query_var('search_terms'); if( empty( $query_terms ) ) { $query_terms = (array)get_query_var( 's' ); } if( empty( $query_terms ) ) { return $text; } $n = 0; foreach( $query_terms as $term ){ $n++; $term = preg_quote( $term, '/' ); $text = preg_replace_callback( "/$term/iu", function( $match ) use ( $colors, $n ){ return '<span style="background-color: '. $colors[ $n ] .';">'. $match[0] .'</span>'; }, $text ); } return $text; }
#3 Живой поиск без перезагрузки (на ajax)
Преимущество такого поиска перед традиционным – очевидно, хотя бы по тому, что уменьшается нагрузка на сайт. Инструкция будет не сложной, поэтому, даже читатель с базовыми знаниями легко разберется.
Разобьем нашу работу на несколько этапов:
- Создаем js скрипт, реагирующий на набор текста в поле поиска.
- Создаем в файле function.php событие, отвечающее за вывод результата.
- Выводим результаты в созданном html контейнере.
- Красиво оформляем результат выдачи.
Шаг 1: Подключаем необходимые скрипты
Скрипт определяет, что пользователь вводит какой-то текст в поле поиска. Событие ввода привязано к input с классом search-field
, поэтому не забудьте его поменять тот, который у вас в шаблоне сайта.
jQuery(document).ready(function($){ $('.search-field').keypress(function(eventObject){ var searchTerm = $(this).val(); // проверим, если в поле ввода более 2 символов, запускаем ajax if(searchTerm.length > 2){ $.ajax({ url : '/wp-admin/admin-ajax.php', type: 'POST', data:{ 'action':'codyshop_ajax_search', 'term' :searchTerm }, success:function(result){ $('.codyshop-ajax-search').fadeIn().html(result); } }); } }); });
Не забудьте учесть один важный момент – необходимо подключить последнюю версию библиотеки jQuery. Если она не подключена, используйте код в файле function.php темы:
wp_enqueue_script('jquery');
Шаг 2: Создаем функцию для обработки AJAX запросов
Если вы не знаете, куда вставлять данный код, смело разместите его в файл function.php вашей темы.
// ajax поиск по сайту add_action( 'wp_ajax_nopriv_codyshop_ajax_search', 'codyshop_ajax_search' ); add_action( 'wp_ajax_codyshop_ajax_search', 'codyshop_ajax_search' ); function codyshop_ajax_search(){ $args = array( 'post_type' => 'any', 'post_status' => 'publish', 'order' => 'DESC', 'orderby' => 'date', 's' => $_POST['term'], 'posts_per_page' => 5 ); $query = new WP_Query( $args ); if($query->have_posts()){ while ($query->have_posts()) { $query->the_post();?> <li> <?php if(!empty($codyshop_url)) { the_post_thumbnail('codyshop-mini-thumbnail'); } else{ ?> <span><img src="<?php echo esc_url(get_template_directory_uri().'/assets/images/default-mini.gif'); ?>" alt=""></span> <?php } ?> <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a> <?php the_excerpt();?> </li> <?php } }else{ ?> <li><a href="#">Ничего не найдено, попробуйте другой запрос</a></li> <?php } exit; }
Шаг 3: Создаем контейнер для вывода результатов поиска
Итак, нам необходимо показать результаты поиска. Для этого, разместите сразу же после input формы поиска:
<ul class="codyshop-ajax-search"></ul>
Шаг 4: Оформляем результаты выдачи
Важная особенность данной верстки – при фокусировки курсора на поле ввода, происходит затемнение фона вокруг. Приведенное ниже оформление – лишь заготовка. Скорее всего, потребуется адаптация.
#searchform .search-field:focus{ box-shadow: 0 0 0 99999px rgba(0, 0, 0, 0.65); position: relative; z-index: 1051; } #searchform .search-field:focus ~ #searchsubmit{ position: relative; z-index: 1100; } .codyshop-ajax-search li{ overflow: hidden; line-height: 17px; width: 100%; min-height: 100px; max-height: 100px; display: inline-block; float: left; box-sizing: border-box; border-bottom: 1px solid #eeeeee; padding: 15px 10px; list-style:none; } .codyshop-ajax-search{ position: fixed; box-sizing: border-box; background: #fff; z-index: 1111; border-radius: 3px; border:1px solid #eee; border-top:none; padding: 20px 20px 10px 20px; display: none; max-height: 500px; overflow-y: auto; } .codyshop-ajax-search li:first-child{ padding: 0 10px 15px 10px; } .codyshop-ajax-search li:last-child { padding: 15px 10px 0 10px; border-bottom: none; } .codyshop-ajax-search li a{ color: #7c83a0; } .codyshop-ajax-search span { height: 100%; float: left; min-height: 100px; } .codyshop-ajax-search li p, .codyshop-latest-post li p{ line-height: 14px; font-size: 13px; color: #7c83a0; font-style: italic; background-color: white; } .codyshop-ajax-search li img, .codyshop-latest-post li img{ width: 60px; float: left; border: 2px solid #eeeeee; background-color: #eeeeee; border-radius: 50%; margin-right: 10px; }
#4 Поиск только по точному вхождению фразы
По умолчанию WordPress разбивает поисковую строку на части. Давайте отключим эту функцию и будем производить поиск только по точному совпадению.
add_action( 'pre_get_posts', 'cody_search_filter' ); function cody_search_filter( $query ){ if( ! is_admin() && $query->is_main_query() ){ if( $query->is_search ){ $query->set( 'sentence', 1 ); } } }
#5 Поиск только по подзаголовку
Я не знаю точно, где это может пригодиться. Может быть, если вы делаете поиск в интернет магазине по товарам, где название соответствует артикулу.
add_filter( 'posts_search', 'cody_search_only_in_title', 500, 2 ); function cody_search_only_in_title( $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( $wpdb->esc_like( $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; }
#6 Перенаправление на единственную страницу-результат
Если по поисковой строке найден один результат, автоматически перенаправим пользователя на неё.
add_action( 'template_redirect', 'cody_redirect_single_post' ); function cody_redirect_single_post() { if ( !is_search() ) return; global $wp_query; if ( $wp_query->post_count == 1 ) { wp_redirect( get_permalink( $wp_query->posts['0']->ID ) ); } }
#7 Поиск при неправильной раскладке клавиатуры
Пожалуй, этот сниппет – один из самых интересных, и применимых почти для всех русскоязычных сайтов. Он производит поиск, если пользователь забыл переключиться на русскую раскладку. Например, если он ввёл djhlghtcc
вместо необходимого вордпресс
.
Для реализации этой задачи, давайте напишем свою функцию. Если WordPress не получил ни одного результата, будем считать, что была использована неверная раскладка. Нам необходимо вмешаться в текущий запрос WP_Query
. Для этого вполне подойдёт фильтр posts_results
. В начале мы заменяем латинские символы на подходящие кириллицей.
Так как по старому запросу мы ничего не нашли, снова производим выборку записей через метод $wpdb->get_results
. При этом нам не нужно беспокоиться о составлении SQL запроса. WP фактически уже это сделал за нас, достаточно обратиться к $query->request
. Нам остаётся лишь заменить старый поисковый запрос на новый. Результатом нового SQL запроса станет новый массив, содержащий ID найденных постов.
add_filter( 'posts_results', 'cody_search_cir_lat', 10, 2 ); function cody_search_cir_lat( $posts, $query ) { if ( is_admin() || !$query->is_search ) return $posts; global $wp_query; if ( $wp_query->found_posts == 0 ) { // замена латиницы на кириллицу $letters = array( 'f' => 'а', ',' => 'б', 'd' => 'в', 'u' => 'г', 'l' => 'д', 't' => 'е', '`' => 'ё', ';' => 'ж', 'p' => 'з', 'b' => 'и', 'q' => 'й', 'r' => 'к', 'k' => 'л', 'v' => 'м', 'y' => 'н', 'j' => 'о', 'g' => 'п', 'h' => 'р', 'c' => 'с', 'n' => 'т', 'e' => 'у', 'a' => 'ф', '[' => 'х', 'w' => 'ц', 'x' => 'ч', 'i' => 'ш', 'o' => 'щ', ']' => 'ъ', 's' => 'ы', 'm' => 'ь', '\'' => 'э', '.' => 'ю', 'z' => 'я' ); $cir = array( 'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я', 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я' ); $lat = array( 'f', ',', 'd', 'u', 'l', 't', '`', ';', 'p', 'b', 'q', 'r', 'k', 'v', 'y', 'j', 'g', 'h', 'c', 'n', 'e', 'a', '[', 'w', 'x', 'i', 'o', ']', 's', 'm', '\'', '.', 'z', 'F', ',', 'D', 'U', 'L', 'T', '`', ';', 'P', 'B', 'Q', 'R', 'K', 'V', 'Y', 'J', 'G', 'H', 'C', 'N', 'E', 'A', '[', 'W', 'X', 'I', 'O', ']', 'S', 'M', '\'', '.', 'Z' ); $new_search = str_replace( $lat, $cir, $wp_query->query_vars['s'] ); // производим выборку из базы данных global $wpdb; $request = $wpdb->get_results( str_replace( $wp_query->query_vars['s'], $new_search, $query->request ) ); if ( $request ) { $new_posts = array(); foreach ( $request as $post ) { $new_posts[] = get_post( $post->ID ); } if ( count( $new_posts ) > 0 ) { $posts = $new_posts; } } } // возвращаем массив найденных постов return $posts; }
#8 Поиск по категориям с выпадающим списком
Ещё одна возможность – позволить читателям фильтровать результаты поиска, ориентируясь на определенную категорию. Это можно реализовать с помощью простого раскрывающегося списка, содержащего все названия категорий. Всё, что вам нужно сделать – заменить стандартную форму поиска (обычно он находится в файле searchform.php) на фрагмент ниже:
<form role="search" method="get" id="searchform" action="<?php bloginfo('siteurl'); ?>"> <div> <label class="screen-reader-text" for="s">Search for:</label> <input type="text" value="" name="s" id="s" /> in <?php wp_dropdown_categories( 'show_option_all=All Categories' ); ?> <input type="submit" id="searchsubmit" value="Search" /> </div> </form>
Сниппеты для админки
Но не будем забывать, что в административной панели тоже есть поля поиска. Посмотрим, как можно улучшить и их.
#1 Поиск записей в админке на ajax (без перезагрузки)
add_action( 'admin_print_footer_scripts', 'cody_search_posts_in_admin' ); function cody_search_posts_in_admin() { ?> <script type="text/javascript"> jQuery(document).ready(function($) { function cody_ajax_admin_search_update_search() { s = a.val().replace(' ', '+'); var url = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for (var i = 0; i < url.length; i++) { if (/(^s$)|(\bs=.*\b)|(\bs=)/g.test(url[i]) === true || /http.*/g.test(url[i]) === true) y = i; } if (typeof y === 'undefined') url.unshift('s=' + s); else url[y] = 's=' + s; url = url.join('&'); url = window.location.pathname + '?' + url; $.get(url, {}, function(data) { var r = $('<div />').html(data); var table = r.find(z); var tablenav_top = r.find(tnt); var tablenav_bottom = r.find(tnb); $(z).html(table); $(tnt).html(tablenav_top); $(tnb).html(tablenav_bottom); }, 'html'); $(document).ajaxStop(function() { if (s.length) { history.pushState({}, "after search", url); } else { history.pushState({}, "empty search", url); } }); } $(function() { a = $('input[type="search"]'); t = a.closest('form').find('table'); if (!t.length) t = a.closest('div').find('table'); if (!t.length) return; z = '.' + t.attr('class').replace(/\s/g, '.'); tn = '.top .displaying-num'; bn = '.bottom .displaying-num'; tpl = '.top span.pagination-links'; bpl = '.bottom span.pagination-links'; tnt = '.tablenav.top'; tnb = '.tablenav.bottom'; var timer; a.on('keyup', function(event) { if (timer) clearTimeout(timer); timer = setTimeout(cody_ajax_admin_search_update_search, 300); }); }); }); </script> <?php }
#2 Создание поисковой строки в списках категорий
add_action( 'admin_print_scripts', 'cody_admin_category_filter', 99 ); function cody_admin_category_filter() { $screen = get_current_screen(); if( 'post' !== $screen->base ) return; ?> <script> jQuery( document ).ready( function( $ ){ var $div = $( '.categorydiv' ); $div.prepend( '<input type="search" class="fc-search-field" placeholder="<?php _e( 'Фильтр', 'theme' ); ?>" style="width:100%" />' ); $div.on( 'keyup search', '.fc-search-field', function ( event ) { var searchTerm = event.target.value, $listItems = $( this ).parent().find( '.categorychecklist li' ); if( $.trim( searchTerm ) ){ $listItems.hide().filter( function () { return $( this ).text().toLowerCase().indexOf( searchTerm.toLowerCase() ) !== -1; } ).show(); } else { $listItems.show(); } } ); } ); </script> <?php }
Плагины
Несколько слов о плагинах.
Relevansii (бесплатно)
Отличный плагин, который не использует облачный поисковый сервис, поэтому он может быть немного медленнее в зависимости от вашего хостинга. Но у вас будет максимальный контроль.
После установки плагина сначала необходимо создать индекс. Relevanssi заменяет поиск по умолчанию поиском с частичным совпадением, который сортирует результаты по релевантности. Он также индексирует комментарии и содержимое шорткодов. Есть несколько и других особенностей:
- Поиск по комментариям, меткам, категориям и произвольным полям.
- Предлагаются варианты, а-ля: “Вы имели в виду? …”
- Исключение записей, страниц, тегов или категорий из поиска.
- Поиск по части слова.
Вы можете изменить вес заголовков записей, текста комментариев, меток и категорий в зависимости от того, что считаете наиболее важным.
SearchWP (платно)
SearchWP – это мощный плагин пользовательского поиска для WordPress. Он очень прост в использовании, а результаты поиска более менее точны.
Он позволяет искать ключевое слово в заголовке записи/страницы, основном контенте, слаге, категориях, метках, таксономиях, цитатах и даже комментариях. Вы можете управлять алгоритмом, назначая вес каждому типу контента от 1 до 10, где 10 является самым высоким.
После активации плагин автоматически проиндексирует контент и заменит функцию поиска по умолчанию.
Swiftype Search (платно)
Swiftype – довольно новый поисковый сервис WordPress. Некоторые приятные функции включают:
- Облачный сервис, который не напрягает серверы.
- Очень релевантные результаты поиска.
- Аналитика того, что ищут пользователи.
- Функция автозаполнения.
- Переопределение результатов поиска вручную.
- Поиск приложений.
Плагин работает, отправляя индекс всего вашего контента на серверы разработчиков, поэтому ваш сервер не загромождается. Поскольку Swiftype вообще не использует MySQL, результаты поиска появляются намного быстрее. Для использования плагина необходимо создать учётную запись.
У нас получилась неплохая подборка. Если у вас есть ещё идеи, пишите в комментариях.
Очень интересно. Но, вот что-то не хочет работать этот ajax 🙁
Посмотрите консоль браузера. Не исключён конфликт скриптов. У меня на сайте поиск выполнен именно таким образом, как описано в статье.
У меня выходит вот так: Failed to load resource: the server responded with /wp-admin/admin-ajax.php a status of 404 (Not Found)
Заработало! Пришлось прописать полный путь. Но, хотелось бы, чтоб как у вас ))
Ну и славненько, что заработало. Почему не сработал относительный путь к файлу в вашем случае, … затрудняюсь сказать. Нужно смотреть исходники.
Я разобрался, большое спасибо за великолепное решение. Надо было почему-то убрать слеш (/) перед wp-admin/admin-ajax.php. Изменил немного вывод результатов (миниатюры постов не выводились), работаю над CSS.
А можно как-то загрузчик прикрепить? Этот, который крутится, например, в ожидании результата. Пожалуйста.
Можно. Для этого на странице необходимо разместить gif картинку с крутящимся прелоадером и css стилями. Например, так: img src=”путь к картинке” style=”display: none; position: fixed;” class=”preloader”
Затем, в момент набора текста, в js скрипте после if(searchTerm.length > 2){ прописать ее появление. Что-то вроде $(‘.preloader’).fadeIn(); Ну и в итоге, после успешного выполнения скрипта скроем его: $(‘.preloader’).fadeOut();
Если Вам так и непонятно? :
И вот загрузчик. В моем случае – иконка от FA:
Ян, а у Вас что-то с меню. 🙂 Описание, что ли?
Да, только сегодня добавил.
Подскажите пожалуйста. Ваш код отлично работает, огромное спасибо. Но возникает вопрос, быть может это норма, а может просто я неправильно что-то настроил. Сам поиск работает только на главной странице, подскажите с чем это может быть связанно, и как это можно поправить?
Попробуйте сделать в function.php так:
function search_ajax() { ?>
jQuery(document).ready(function($){
$(‘.search-field’).keypress(function(eventObject){
var searchTerm = $(this).val();
if(searchTerm.length > 2){
$.ajax({
url : ”,
type: ‘POST’,
data:{
‘action’:’codyshop_ajax_search’,
‘term’ :searchTerm
},
success:function(result){
$(‘.codyshop-ajax-search’).fadeIn().html(result);
}
});
}
});
});
<?php }
add_action( 'wp_footer', 'search_ajax' );
Когда-то была аналогичная проблема, и выход из ситуации был таков. Сейчас использую как-то также, но с более нарощенным (под себя) функционалом.
Могу помочь. Не знаю что с ответом, но я уже пытался комментил вас. Все из-за url : ‘/wp-admin/admin-ajax.php’
Благодарю за помощь. Ответ как всегда плавал на поверхности. Решение конечно же, как по мне, не из лучших, будем искать иные методы, а пока еще раз спасибо!
Помогите пожалуйста!
Я не могу разобраться вот с этим пунктом: ПОДКЛЮЧАЕМ НЕОБХОДИМЫЕ СКРИПТЫ.
Объясните пожалуйста. что нужно делать с этим кодом? Куда и как правильно его нужно подключить?
У меня есть дочерняя тема и в ней 3 файла functions.php . style.css и header.php
Добрый день. Вам необходимо создать в дочерней теме javascript файл. Он с расширением .js Затем в этот файл вставить предложенный в статье скрипт. И теперь остаётся только подключить скрипт. Разместите в function.php дочерней темы следующий код:
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_scripts' );
function mytheme_enqueue_scripts() {
wp_enqueue_script( 'my-script', get_stylesheet_directory_uri() . '/ваш-путь-к-скрипту/my-script.js', array( 'jquery' ), true );
}
Так как я точно не знаю, по какому пути будет располагаться ваш файлик, убедитесь самостоятельно, что путь указан верно.
Большое спасибо, а подскажите ещё как создать контейнер для вывода результатов поиска?
Куда нужно поместить данный код?
Обычно, за вывод поиска отвечает файл searchform.php Я так понял что в дочерней теме у вас этого файла нет. Значит просто скопируйте его из родительской. После, разместите контейнер
например, перед закрывающим тегом form.
Подскажите пожалуйста, у меня в ajax все ссылки выводятся , все пути верные, но почему-то они не работают при нажатии, а если кликнуть ПКМ и “открыть в новой вкладке”, то всё ОК. Думал проблемы с видимостью, но hover эффект тогда почему-то срабатывает, пробовал z-index поставить та же проблема. Не хочет он перебрасывать на другую страницу при клике, в чем может быть проблема? Уже голову сломал, всё что в гугле находил по этой теме – не работает(
Проверьте вёрстку и скрипт, возможно на эти элементы навешена отмена стандартных действий через
event.preventDefault()
илиreturn false
.Спасибо большое) Оказывается, бутстрап подвесил на тег обработчик с event.preventDefault(), только не совсем понятно с какой целью))
Добрый день. Спасибо за статью! А подскажите можно сделать поиск только по терминам таксономии. Например у меня у свой тип записи – Продукты. Таксономия – магазины. Ну и термины Магазин -1, Магазин -2 и тп… Вот чтобы поиск осуществляться только по терминам (названию и описанию). То есть пользователь будет вводить в поиске тока название магазина.
Приводится пример формы с выпадающим списком. Как расширить ее добавив в код поиск по определенным двум тегам, при этом один из из них должен отражать поиск неком диапазоне. Поиск осуществляется по принципу от -до.