Создаем свой собственный поиск в WordPress

0 71

Функция поиска в WordPress имеет плохую репутацию, потому существует масса различных плагинов, которые позволяет внести определенные усовершенствования в нее, однако они не всегда предлагают то, что вам требуется, особенно если вы хотите создать дополнительную систему поиска под некоторые фиксированные требования.

В данной статье мы посмотрим на то, как создать свой собственный поиск в WordPress, и заодно раскроем некоторые связанные с этим секреты.

Несмотря на многочисленные плагины, которые позволяют улучшить различные аспекты поиска WordPress, начиная с упорядочивания по релевантности и заканчивая включением произвольных полей в поиск, бывают такие ситуации, когда плагины, причем в любых своих комбинациях, не способны выполнить именно того, что вам требуется, и в итоге вам приходится писать свой собственный код.

Содержание

  1. Улучшаем поиск в WordPress путем добавления расширенной поисковой формы
  2. Поиск по фразе
  3. Поиск точного совпадения
  4. Изменение поисковой формы
  5. Когда произвольной формы недостаточно
  6. Произвольные формы идеальны, когда вы хотите реализовать дополнительный поиск

Улучшаем поиск в WordPress путем добавления расширенной поисковой формы

За поиск WordPress отвечает класс WP_Query. Если вы раньше работали с произвольными циклами, то вы имеете представление о WP_Query.

WP_Query имеет массу возможных параметров, многие из которых могут быть легко определены в поисковой форме (или непосредственно в URL), что изменит поведение поиска.

К примеру, чтобы превратить обычный поиск в поиск по произвольному типу записей с названием product, достаточно ввести следующее:

http://www.yoursite.com/?s=football&post_type=product

В итоге мы получим результаты для записей с типом product, которые содержат в своем заголовке или контенте слово football.

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

Помните, что для поиска важно включать параметр s в URL.

Существует также много дополнительных параметров, с помощью которых можно полностью изменить поведение, но которые, увы, не задокументированы в кодексе.

Поиск по фразе

По умолчанию WordPress совершает поиск по ключевому слову. Это означает, что если в поиск передан запрос «football boots», то WordPress формирует следующий код для условия WHERE:

((wp_posts.post_title LIKE '%football%') OR (wp_posts.post_content LIKE '%football%'))  AND ((wp_posts.post_title LIKE '%boots%') OR (wp_posts.post_content LIKE '%boots%'))

Как вы можете видеть, здесь задан не поиск целой фразы, а поиск отдельных слов — «football» в заголовке или контенте и «boots» в заголовке или контенте. Таким образом, запись, содержащая слово «boot» в заголовке и «football» в контенте не будет, очевидно, соответствовать тому, что хотел получить пользователь, однако именно она будет выдана на экран.

Вы можете, правда, сделать так, чтобы WordPress искал фразы – для этого достаточно добавить sentence=1 в URL, что приведет к изменению условия WHERE:

((wp_posts.post_title LIKE '%football boots%') OR  (wp_posts.post_content LIKE '%football boots%'))

Теперь поиск ведется по фразе, поэтому заголовок или контент материала должен фактически содержать оба слова (не обязательно подряд), чтобы быть найденным и выданным на экран. Попробуйте это сделать на своем собственном сайте. Запустите обычный поиск, после чего добавьте &sentence=1 к URL, и вы увидите, в чем состоит разница.

Поиск точного совпадения

Связанным с sentence, однако более специфичным является параметр exact. Добавление exact=1 к URL приведет к следующим изменениям в условии WHERE:

((wp_posts.post_title LIKE 'football boots') OR  (wp_posts.post_content LIKE 'football boots'))

Вместо того чтобы разыскивать отличия, я сразу скажу вам, что единственная разница между условиях sentence и exact заключается в удалении % вокруг фразы в операторах LIKE. Такое удаление имеет большое значение, поскольку теперь заголовок или контент должен точно соответствовать поисковому запросу, а не просто включать его в себя.

То есть, если ни один продукт не имеет в заголовке фразы «football boots», то никаких результатов выдано не будет. Использовать exact нужно очень осторожно.

Изменение поисковой формы

Стандартная поисковая форма в WordPress довольно проста:

<form role="search" method="get" id="searchform" class="searchform" action="http://www.test.dev/"> <div> <label class="screen-reader-text" for="s">Search for:</label> <input type="text" value="" name="s" id="s" /> <input type="submit" id="searchsubmit" value="Search" /> </div> </form>

Если вы хотите изменить поисковое поведение, то в таком случае вам нужно добавить ваши собственные поля в форму.

<form role="search" method="get" id="searchform" action="http://www.test.dev/"> <div> <label for="s">Search for:</label> <input type="text" value="" name="s" id="s" /> <input type="hidden" value="1" name="sentence" /> <input type="hidden" value="product" name="post_type" /> <input type="submit" id="searchsubmit" value="Search" /> </div> </form>

Эта поисковая форма при отправлении будет генерировать следующий URL:

http://www.test.dev/?s={query}&sentence=1&post_type=product

Она по-прежнему будет вызывать стандартную страницу поисковых результатов, однако эти результаты будут уже для произвольного типа записей product, причем выдаваемые записи должны будут содержать поисковую фразу либо в своем заголовке, либо в контенте.

Самый простой способ создать свою собственную поисковую форму, предполагая, что вы хотите оставить стандартную форму в своем изначальном виде – это создать новый шаблон страницы с поисковой формой, закодированной под ваши требования, и привязать его к определенной странице.

Если же вы хотите обновить дефолтную поисковую форму – чтобы запустить поиск по фразам, к примеру – то в таком случае у вас есть два варианта, как поступить; в данном случае мы будем предполагать, что в вашем шаблоне поисковая форма не является жестко кодированной:

  1. Первый вариант – поместить произвольную поисковую форму в шаблон searchform.php. Всякий раз, когда функция get_search_form() будет вызвана, она в первую очередь будет использовать данный шаблон.
  2. Второй вариант – использовать фильтр get_search_form, что вынудит WordPress обратиться к вашей произвольной форме поиска.

Обе эти техники в деталях описаны в кодексе.

Когда произвольной формы недостаточно

Несмотря на то что с помощью произвольной формы поиска можно сделать очень и очень многое, ее порой бывает недостаточно. Существуют такие случаи, когда вам нужно создать свой WP_Query и обработать результаты самостоятельно – в частности, когда вы добавляете дополнительную функцию поиска.

Конкретный пример

Наш пример будет касаться коммерческого сайта компании, которая продает некую смесь физических и цифровых товаров. Большая часть цифровых товаров – это прошлые номера двух журналов, которые выпускались вместе с буклетами в цифровом и печатном формате.

Компания хотела бы реализовать поиск по библиотеке, который позволит посетителям искать только журналы и буклеты по определенным фразам. На сайте уже был реализован поиск по продуктам, однако результаты были не слишком хорошими:

  • Выводилось слишком много нерелевантных результатов
  • Включались все товары
  • Не было индикации относительно того, какой поисковой терм был найден, результатами поиска были обычные изображения товаров

Чтобы не трогать текущий поиск, была создана новая функция, которая:

  • Принуждала искать по фразе вместо поиска по ключевым словам
  • Ограничивала поиск по категориям журналов и буклетов
  • Выводила на экран и подсвечивала текст, содержащий соответствие поисковой фразе

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

<form role="search" method="get" id="searchform" action="http://www.test.dev/"> <div> <label for="s">Search for:</label> <input type="text" value="" name="s" id="s" /> <input type="hidden" value="1" name="sentence" /> <input type="hidden" value="product" name="post_type" /> <input type="hidden" value="product_cat" name="magazines,books" /> <input type="submit" id="searchsubmit" value="Search" /> </div> </form>

Однако она не смогла бы помочь в случае разметки для поисковых результатов и подсветки поисковых фраз, поэтому был создан новый шаблон страницы, который связывался с отдельной страницей.

Вот основная логика шаблона:

<div id="content" class="col-full">     	 	<section id="main" class="col-left"> 		 	<!-- begin search form -->     	<form action="/library" method="post">     			 		<p> 			<label for="query"><?php _e( 'Search', 'woothemes' ); ?></label> 			<input type="text" name="query" id="query" value="<?php echo esc_attr( $query ); ?>" /> 		</p> 		<p> 			<input type="submit" id="searchsubmit" value="<?php _e( 'Search', 'woothemes' ); ?>" /> 		</p>       	</form>     	<!-- end search form -->   	     	     	<?php      	     	if( !empty( $query ) ) :            	$product_cats = 'books, renew, sanctuary';      		$args = array(   			'posts_per_page' => -1,   			'post_type' => 'product', 			'orderby' => 'date menu_order',  			'order' => 'DESC', 			's' => $query, 			'sentence' => 1, 			'product_cat' => $product_cats, 			 		);             	// perform the search         	$posts = new WP_Query( $args );         		if( ( $posts->have_posts() ) ) :        		       		?>           		<header class="page-header">           			<h1 class="page-title"><?php printf( __( 'Library Search Results for: %s', 'woothemes' ), $query ); ?></h1>         		</header>           		<?php /* The loop */ ?>         		         			<ul style="list-style: none">         		         		<?php           		               		while ( $posts->have_posts() ): $posts->the_post();          		?>           			<li style="display: block; margin-bottom: 50px"> 							 					<div style="float: left; width: 110px;">	 					 						<a href="<?php echo get_permalink(); ?>"> 							<?php echo get_the_post_thumbnail( $post->ID, array( 175, 175 ) ); ?> 						</a> 							 					</div>   					<div style="float:left; margin-left: 20px; width: 500px"> 							 						<h2 style="margin-top: -10px; padding-top: 0px;">		 							<a href="<?php echo get_permalink(); ?>"	 								<?php echo apply_highlight( get_the_title() , $query ) ?> 							</a> 						</h2> 							 						<div><?php echo apply_highlight( get_snippet( get_the_content() , $query ) , $query ) ?></div> 								 					</div> 							 					<div style="clear:both"></div>           				           			</li>           		<?php         		endwhile;          		         		?>         			</ul>         		<?php           		wp_reset_postdata();         		         		?>           		<?php        		       		else :        		       		?> 				 				<h1 class="page-title"><?php printf( __( 'Sorry, no matches found for "' . $query .'"', 'woothemes' )  ); ?></h1>   				<h4>Search Suggestions:</h4> 				<ul> 					<li>Check your spelling</li> 					<li>Try more general words</li> 					<li>Try different words that mean the same thing</li> 				</ul> 					 				<h1 class="page-title">Or, perhaps these might be of interest...</h1> 					 				<?php 								 						echo do_shortcode('[product_category per_page="3" columns="3" orderby="date" order="desc" category="books"]');  													 						echo do_shortcode('[product_category per_page="3" columns="3" orderby="date" order="desc" category="renew"]');    						echo do_shortcode('[product_category per_page="3" columns="3" orderby="date" order="desc" category="sanctuary"]'); 				 				 			endif; // !(empty ( $posts ))   		endif; // !(empty ( $query )) 		 		?>                          </section><!-- /#main -->   </div><!-- /#content -->

Как вы можете видеть, форма поиска напоминает стандартную поисковую форму в WordPress, поскольку все манипуляции с вызовом WP_Query выполняются через код, где:

  • post_type задается как product
  • sentence задается в 1 для инициирования поиска по фразе
  • добавляется параметр таксономии для ограничения поиска по трем выбранным категориям товаров
  • упорядочивание задается по дате, menu_order – по убыванию
  • все записи должны быть возвращены

Важно отметить, что в этом решении отсутствует пагинация. Для произвольного, специфичного поиска пагинация не так нужна, особенно если выполняется поиск по фразе.

Вы можете заметить, что если поисковые результаты будут отсутствовать, то в таком случае на экран будут выведены несколько связанных товаров, чтобы посетитель не покинул страницу.

Вывод результатов требует добавления двух дополнительных функций – одной для получения текста, который содержит поисковую фразу, и другой для подсветки фразы.

function apply_highlight( $the_content , $the_query) {   	return preg_replace( '/' . $the_query . '/i' , '<span style="background-color: #00FF00">$0</span>' , $the_content );   }   function get_snippet( $the_content , $the_query ) {   	preg_match( '/' . $the_query . '/i' , $the_content , $matches, PREG_OFFSET_CAPTURE ); 	 	$snippet = '<ul>'; 	 	foreach ($matches as $match):   		$cutoff = substr( $the_content, 0 , $match[1] ); 		 		$start = strripos( $cutoff, '<li>' ); 		$end = strpos( $the_content, '</li>' , $match[1] ); 		 		$snippet .= substr( $the_content, $start, ( $end - $start ) + 4 ); 		 		//$snippet .= $match[0] . ' - ' . $match[1];   	endforeach;   	$snippet .= '</ul>'; 	 	return $snippet; }

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

Получение текста, содержащего поисковую фразу, оказалось не самым простым действием. Этому сильно поспособствовал тот факт, что контент каждого товара выводится в виде неупорядоченного списка с заголовком и описанием, однако попытка поиска соответствующего регулярного выражения не закончилась ничем, поэтому я решил обратиться к обработке строк.

Результат получился, тем не менее, достаточно хорошим:

Создаем свой собственный поиск в WordPress

Произвольные формы идеальны, когда вы хотите реализовать дополнительный поиск

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

В большинстве случаев вы сможете реализовать то, что вам нужно, путем использования произвольной поисковой формы, которая передает надлежащие параметры во встроенную функцию поиска. Вы можете легко протестировать использование параметров, добавив их к URL поиска.

Стоит заметить, что написание своей собственной функции поиска – не самая сложная задача. Вы можете воспользоваться дополнительными параметрами, чтобы управлять поведением поиска.

Источник: premium.wpmudev.org/blog

Оставьте ответ

Ваш электронный адрес не будет опубликован.