Приветствую!
В нашей предыдущей статье мы рассмотрели возможность построения get-запроса к базе данных Worpress и рассмотрели варианты использования этой возможности для формирования фильтра записей, страниц и тд. Как вы помните в прошлой статье нам удалось избежать процесса создания скрипта-обработчика данных с формы и мы целиком возложили этот процесс на сам WordPress, ограничившись только построением правильного запроса через форму фильтра. Но как мы выяснили, этот способ имеет один существенный недостаток - невозможность поиска по произвольным полям этих страниц или записей.
Сегодня мы попробуем пойти другим путем и научимся формировать фильтры с использованием произвольных полей.
Скажу сразу, чтобы хотя мы и будем полагаться на функциональные возможности WordPress по выборке и поиску у нас все же не получиться обойтись без необходимости написания своего скрипта обрабатывающего запрос с формы фильтра для получения нужного результата.
Итак, начнем подготовку к реализации нашего фильтра.
Для начала подготовим шаблон страницы, где и будет происходить вывод результатов выборки.
Для этого в админке нашего сайта создадим новую пустую страницу, назовем ее "Результаты поиска" и назначим ей URL "customsearch"
Далее связываемся с нашим сервером с помощью FTP-клиента, находим файл page.php, делаем с него копию и переименовываем в page-customsearch.php. Таким образом, мы сообщаем, что все обращения к нашей созданной в админке странице будут обрабатываться именно в этом файле, не затрагивая другие, а обращаться мы к ней будем через наш фильтр записей.
После этого, мы можем приступать к формированию HTML-кода нашего фильтра. Основные принципы построения фильтра описаны в предыдущей статье, поэтому я приведу пример формы фильтра, описав подробно только моменты связанные с использованием произвольных полей в этой форме:
<form action="/customsearch/" method="get"> //выборка по отдельному слову <p><label>Поисковый запрос</label><br /> <input type="text" name="word" value=""></p> //выборка по терминам определенной таксономии, в нашем случае prodcat <p><label>Укажите товарную категорию:</label><br /> <select name="prodcat"> <option value="">--------</option> <option value="148">Плагины WordPress</option> <option value="199">Изображения</option> </select> </p> //Выборка по значениям цены, которые указаны произвольными полями <p><label>Диапазон цены</label><br /> от <input type="text" name="min-price" size="3" value=""> до <input type="text" name="max-price" size="3" value=""></p> //Указание сортировки результатов выборки //Тут мы можем отсортировать и по значению цены, заданного //произвольным полем <p><label>Сортировка по</label><br /> <select name="orderby"> <option value="date">дате добавления</option> <option value="title">заголовку</option> <option value="meta_value_num">цене</option> </select> </p> //Указание направление результатов сортировки <p><label>Направление сортировки:</label><br /> <input type="radio" name="order" value="DESC"> по убыванию<br /> <input type="radio" name="order" value="ASC"> по возрастанию </p> //Указание количества записей на одну страницу <p><label>Получить:</label><br /> <select name="num"> <option value="-1">Все товары</option> <option value="2">2 товара</option> <option value="4">4 товара</option> <option value="6">6 товаров</option> </select> </p> <p><input type="submit" value="Получить товары"></p> //так как мы можем производить сортировку и по произвольным полям, то //в запросе следует указывать ключ этого поля. //В нашем случае это цена товара "price-products" <input type="hidden" name="meta_key" value="price-products"> </form>
Обратите внимание на атрибут action тега form, в нем мы указываем адрес именно той страницы, которую создали в админке и для которой мы создали отдельный шаблон на сервере. Метод передачи данных мы можем использовать любой, POST или GET.
Собственно, когда мы имеем на руках код формы мы можем переходить к этапу обработки данных, передаваемых этой формой. Здесь следует отметить, что нам не придется писать какой то большой скрипт, мы лишь будем максимально использовать возможности WordPress по обоработке переданных с формы данных. Поэтому мы ограничимся лишь построением массива данных, который затем передадим в цикл WordPress для вывода результата.
Обратимся к стандартной функции query_posts(), именно в эту функцию мы и должны передать сформированный нами массив. Эта функция распологается перед началом цикла записей и влияет на него, заставляя его выводить именно те записи, которые нам нужны и в том порядке который мы указали, лишь получив сформированный массив.
Как же формировать этот массив? Для этого мы можем обратиться к обширному описанию этой функции в кодексе Worpress. Это описание я дублировать тут не буду, но постараюсь подробно описать логику построения массива данных именно для нашей формы.
Итак, перейдем к построению массива данных для функции query_posts(). Для этого мы должны открыть для редактирования созданный нами ранее файл page-customsearch.php, где и будет происходить обработка и вывод результатов обработки нашего запроса.
Находим в нем начало цикла, которое выглядит примерно так:
if (have_posts()) : while (have_posts()) : the_post();
и ставим перед этой строкой функцию query_posts() и заготовку для нашего массива. Должно получиться примерно следующее:
<?php $args = array( ); query_posts( $args ); ?> <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
Теперь основываясь на описание функции query_posts в кодексе, данные которые форма передает и метод передачи этих данных начинаем наполнение массива. Смотрим на нашу форму и идем по порядку:
$args = array( //Для начала укажем тип записей по которым осуществляем поиск //В нашем случае это products 'post_type' => 'products', //Передадим поисковый запрос из первого текстового поля 's' => $_GET['word'], //Тут передаем ключ произвольного поля по которому осуществляем //сортировку, если сортировка идет по произвольному полю 'meta_key' => $_GET['meta_key'], //Здесь передаем количество записей выводимых на одной странице 'posts_per_page' => $_GET['num'], // "-1" - получаем все //Эти данные нужны для правильной работы постраничной навигации //в результатах поиска 'paged' => get_query_var( 'paged' ), //Тут передаем направление сортировки, указанное пользователем 'order' => $_GET['order'], //DESC,ASC //Здесь указываем по чему именно производим сортировку 'orderby' => $_GET['orderby'], //title, ID, author, name, date, meta_value //В этом параметре передаем идентификатор термина таксономии prodcat, в котором ищем //записи. Ограничиваем область поиска в пределах одного пользовательского термина 'tax_query' => array( array( 'taxonomy' => 'prodcat', 'field' => 'id', 'terms' => array($_GET['prodcat']) ) ), //Здесь передаем минимальную и максимальную цены в диапазоне которых производим поиск. //т.е. осуществляем поиск в пределах значений определенного произвольного поля. //В нашем случае 'price-products' 'meta_query' => array( array( 'key' => 'price-products', 'value' => array( $_GET['min-price'], $_GET['max-price'] ), 'type' => 'numeric', 'compare' => 'BETWEEN' ) ) );
Остановлюсь более подробно на указании значений произвольного поля в этом массиве. В нашем случае, мы указали диапазон значений цены "от и до", поэтому значение параметра compare мы установили, согласно документации к функции, как BETWEEN, что означает, что выборку будем делать в диапазоне значений. Но поиск по произвольным полям может быть очень разнообразным и в зависимости от нужного нам результата будет менять и порядок формирования этих значений в массиве функции query_posts.
Например, для поиска записей только по определенному значению произвольных полей или ключу произвольного поля, достаточно будет указать в массиве:
//Ищем по ключу произвольного поля 'meta_key'=>'color' //или только по значению 'meta_value'=>'green' //Если ищем и по значению и по ключу, то выглядит так 'meta_key'=>'color', 'meta_value'=>'green'
А для поиска уже нескольким произвольным полям придется использовать параметр meta_query, который мы использовали в нашем примере
'meta_query' => array( //здесь мы указали что производим поиск по произвольным полям //с ключом color, значения которых не равны blue array( 'key' => 'color', 'value' => 'blue', 'compare' => 'NOT LIKE' ), //тут мы указали диапазон значений произвольного поля price, //в котором производим поиск //type - параметр уточняющий тип передаваемых данных array( 'key' => 'price', 'value' => array( 20, 100 ), 'type' => 'numeric', 'compare' => 'BETWEEN' ) )
Следует отметить, что параметр compare - определяет сравнение и может быть: =, !=, >, >=, <, <=, LIKE, NOT LIKE, IN, NOT IN, BETWEEN, NOT BETWEEN. По умолчанию =;
Итак, после более подробного экскурса в принципы построения массива при использовании в них произвольных полей, вернемся к нашему примеру формы фильтра.
Разместив код сформированного массива в наш файл page-customsearch.php, мы получаем примерно такой конечный код:
<?php /*Выше распологается какой то код*/ /*********************************/ $args = array( 'post_type' => 'products', 's' => $_GET['word'], 'meta_key' => $_GET['meta_key'], 'posts_per_page' => $_GET['num'], 'paged' => get_query_var( 'paged' ), 'order' => $_GET['order'], 'orderby' => $_GET['orderby'], 'tax_query' => array( array( 'taxonomy' => 'prodcat', 'field' => 'id', 'terms' => array($_GET['prodcat']) ) ), 'meta_query' => array( array( 'key' => 'price-products', 'value' => array( (int)$_GET['min-price'], (int)$_GET['max-price'] ), 'type' => 'numeric', 'compare' => 'BETWEEN' ) ) ); query_posts( $args ); ?> <?php if (have_posts()) : while (have_posts()) : the_post(); ?> /*********************************/ /*Ниже распологается какой то код*/
Получилось очень коротко и понятнее, чем если бы вам кто то писал функцию обработчик данных с вашей формы не используя возможности функции query_posts.
И теперь отправив запрос из нашей формы в этот файл, мы получим результат в виде списка записей который подходят под условия выборки указанные в фильтры.
Нам осталось лишь облагородить нашу форму с помощью CSS и разместить ее в любом месте нашего шаблона.
#customsearch{ width:250px; margin:15px auto; border:1px solid #ccc; border-radius:10px; padding:10px; } #customsearch label{ font-weight:bold; display:block; } #customsearch input[type="text"], #customsearch input[type="submit"], #customsearch select{ padding:5px; border:1px solid #ccc; border-radius:5px; }
А если закрепить за ней какой то шорткод, то использовать ее станет еще проще.
Фактически в результате мы получили форму поиска по этому сайту по товарам.
Рабочий пример распологаю прямо тут:
Подобным образом можно создавать разнообразные формы своими руками без всякого лишнего и левого кода, полагаясь только на функционал WordPress, просто грамотно используя лишь одну функцию.
А что делать если у меня произвольное поле это массив?
Вот мое произвольное поле, это выпадающий список. Как его определять в select?
Здравствуйте, возможно ли такой фильтр поиска завязать под метакеи созданных нами произвольных полей? И затем выводить не из постов а выводить пользователей?
статья о поиске по публикациям, но похожим образом можно строить фильтр и для пользователей
Добрый день! пасибо за отличную статью! скрипт актуален в новейших версиях WP? можно ли разшарить рабочий пхп файл? спасибо
Добрый день, мануал вполне актуален, шарить файл смысла не вижу, все что нужно для работы есть в описании
использую wp-postratings/ плагин рейтингов. в нем есть описание как использовать в такой же конструкции:
как лучше всего дополнительно к имеющемуся значению в вашем скрипте meta_key его использовать? как это красиво обыграть?
как поступить, если помимо категорий, я хочу добавить множественные значения тегов например через чекбоксы?
Просто передавайте данные чекбоксов в массив "tax_query", как это сделано в примере выше
и последний вопрос, есть ли такая опция - отобразить все записи не используя главную материнскую категорию? и можно ли назначить для индексов массива значения по умолчанию с последующим изменением их через форму?
вы можете создать какой то дефолтный массив значений по которому будет производиться выборка, по поводу материнской (родительской скорее) категории тоже все зависит от того по каким данным вы будете производить поиск, массив вы создаете, главное его сформировать так как вам надо
Добрый день! Андрей, не подскажите как удалить пустые значения формы из запроса?