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

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

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

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

Улучшаем поиск в 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; }

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

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

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

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

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

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

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

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

Источник: oddstyle.ru

Comments (0)
Add Comment