Приветствую!
В нашей предыдущей статье мы рассмотрели возможность построения 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, просто грамотно используя лишь одну функцию.
Приветствую! Спасибо за пост. У меня ситуация такая - поиск осуществляется только по обычным постам, все везде заменил и поменял, но не пойму, как сделать так, чтобы поиск осуществлялся по всем категориям, а не только по выбранным. Заранее спасибо.
Нужна помощь чайнику!Перелопатил кучу статей, не могу разобраться. Есть произвольное поле cost_1 (цена) мне необходимо сделать сортировку от наименьшей к большей и наоборот в определённой рубрике, ID рубрики 40. Сделал всё как описано в статье, НО, вы пишите «Находим в нем начало цикла, которое выглядит примерно так:
«1 if (have_posts()) :…..»
НЕТ у меня начала этого цикла. Вот всё что у меня в файле page-customsearch:
?php
/**
* The main template file.
*
* This is the most generic template file in a WordPress theme
* and one of the two required files for a theme (the other being style.css).
* It is used to display a page when nothing more specific matches a query.
* E.g., it puts together the home page when no home.php file exists.
* Learn more: http://codex.wordpress.org/Template_Hierarchy
*
* @package Omega
*/
get_header(); ?>
<main class="» >
ПОМОГИТЕ!Идеальный вариант что б я тупо скопировал код и вставил куда надо(((((((((((((((((((((((
НЕ НАДО вставлять в комментарии код из ваших файлов.
Ищите в своем шаблоне файлы с циклом и пробуйте использовать их для создания шаблона вывода результатов поиска. Такие файлы могут быть page.php, index.php, search.php, category.php, archive.php и тп.
Андрей, добрый день, у меня такая проблема. Весь код прописал, захожу на страницу поиска выводит "К сожалению, нет страницы, соответствующие вашим критериям." Где может быть косяк?
На это может быть несколько причин: не верно создан файл вывода результатов поиска, не верно сформирована форма поиска и поисковый запрос передает неверные данные
Добрый день. Хочу создать каталог сортов на моем винограднике. У каждого сорта есть произвольные поля "срок созревания", "цвет ягоды" и "вкус". Можно ли этим методом сделать фильтр по всем этим полям? И можно ли форму фильтра сделать как виджет на сайдбаре?
Да, все это реализуемо. Плагин может искать сразу по нескольким произвольным полям, форму можно вывести через шорткод в сайдбаре сайта.
Спасибо, буду пробовать!
Добрый день!
Есть страница на нее выводятся дочерние страницы через цикл
"page", "numberposts" => "-1", "child_of" => "0","sort_column" => "post_title" );
if (is_page("snyat")) {
$pages = get_posts ( $args );
}?>
<a href="ID ); ?>">
post_title; ?>
ID, 'thumbnail'); ?>
post_excerpt; ?>
<a class="podrobnee" href="ID ); ?>">Подробнее
Прицепляю форму которая указана в статье и при нажатии кнопки меня перебрасывает на новую страницу на которой выводиться текст.
Всю голову уже сломал какна моей странице сделать сортировку выводимых дочерних страниц?
Подскажите хотя бы в каком направлении копать, как искать в инете, неделю уже бьюсь над задачей, облазел кучу сайтов, ничего не смог придумать.
для начала надо понять на какую именно страницу перекидывает и почему. УРЛ страницы на которую отправляются данные с формы прописывается в атрибуте action тега form
перекидывает на главную
если в action bloginfo('url'); echo $_SERVER["REQUEST_URI"]
то форма не работает вообще
зачем вставлять это в action? для главной страницы достаточно прописать action="/", а для текущей страницы можно оставить атрибут пустым.
Если у вас что то работает неправильно, то надо начинать сначала и постепенно усложнять форму и код, отслеживая текущие ошибки в работе и исправляя их.
если в action пустое значение форма также не работает, даже та которую вставляю отсюда с сайта.
Я думаю что проблема в том что вывод дочерних страниц идет одним способом, а сортировка указаная в вашей статье другим способом производится.
я не знаю, что у вас там за сортировка страниц и как она может влиять на работу формы. Форма отсылает данные туда куда ей укажут, в статье рассказывается как сформировать запрос к БД через форму для получения определенных данных с помощью функции query_posts, если вы уже используете на этой странице эту функцию, то вам надо предварительно сбросить данные цикла функцией wp_reset_query();
нет никакой сортировки есть вывод дочерних страниц через get_page
и вот то что выведено я патаюсь сортировать через форму указаную в статье.
Данные отправляются это видно по УРЛ, но сортировка не действует на выведеные дочерние страницы не по одному параметру.
Если action='/' идет переадресация на другую страницу в котрой выводятся данные.
Проблема в что запросы к бд никак не влияют на сортировку выведенных страниц на текущей странице
при чему тут вообще вывод дочерних страниц и при чем тут функция get_page? Если в передаваемых данных есть ошибка, то запрос не будет ничего получать. Убедитесь что данные переданные с формы формируют верный массив $args передаваемый в функцию query_posts. Пробуйте передать такой массив
$args = array('s'=>'тут ваш поисковый запрос');
просто без передачи данных с формы и смотрите что получается. Данный массив получит публикации соответствующие указанному поисковому запросу.
Андрей, здравствуйте!
Спасибо за статью, заработало. Но есть вопрос про использование нескольких произвольных полей.
Хотелось бы, чтобы пока значение произвольного поля не выбрано, показывались все товары т.е как у Вас сделано в форме поиска на сайте в правом сайдбаре.
Если есть одно поле, и в массив прописываем 'meta_value'=>'green' то при пустом значении выводятся все записи (товары).
Если же использовать 'meta_query' => array(array('key' => 'color','value' => 'green')), то при вводе пустого поля ни одна запись не выводится.
А массив нужен так как будет несколько полей для поиска. Подскажите, пожалуйста как сделать.
Здравствуйте!
Распишите пожалуйста более подробней откуда берётся products и prodcat...
это тип записи и таксономия соотвественно
Здравствуйте, возникают проблемы с выводом результатов в созданном файле. Когда добавляю код, перестает работать постраничная навигация, возможно есть какая-то альтернатива? или другой способ создать новый шаблон ?
Здравствуйте. Почему созданный Вами пример фильтра не выводит списка результата поиска, а только страницу с формой фильтра?
Создал на своем сайте копию Вашего кода, присвоил аналогичные параметры своим категориям и произвольным полям товаров, и результат аналогичный Вашему.
сейчас все работает, просто идентификаторы товарных категорий изменились.
Я тоже нашел свою ошибку в идентификаторе. Сейчас тоже работает. Еще один вопрос, Вы CSS вставляли в код HTML или создали отдельный файл?
как вам удобнее так и делаете
Андрей! Как Вы настроили вывод результата поиска на Вашем сайте (в виде продукт-листа)?
Руками.
Заменил цикл вывода товаров в шаблоне на свой код
благодарю
Здравствуйте. У меня фильтр простенький по двум полям. Произвольное поле color содержит в себе разные значения цветов (красный, синий, зеленый и т.д.), в форме фильтра сделан множественный выбор цветов (checkbox), как сделать что б фильтр выводил по двум и более значениям? Сейчас получилось только по одному, если выбрать больше, то выводит последнее.
Как то так?
Особенно это интересует:
'meta_value' => array( $_GET['color-1'], $_GET['color-2'] )
И если цветов будет больше, то $_GET в array() будет больше, или как то по другому сделать лучше?
Формируйте из значений чекбоксов единый массив name=colors[], при получении данный массив сразу передается в meta_value: 'meta_value'=>$_GET['colors']
Получилось, спасибо. Другой вопрос: сохранение выбранных checkbox таким способом уже не получится, как вы писали ранее: checked($_GET['min-price'],1) , вариант через куки? Или как то вывести из массива данные и поочередно сравнивать со значениями?
при выводе чекбоксов сравнивайте со значениями, для верности в массиве можно назначить свои ключи и затем сравнивать уже по своим ключам.
Спасибо за советы, буду пробовать.
Спасибо за руководство, почти все получилось!
Не получается сделать множественный выбор чекбоксами(
вот пример моего кода, кусочек формы и кусочек запроса:
<input type="checkbox" name="design" value="Классика">
<input type="checkbox" name="design" value="Модерн">
<input type="checkbox" name="design" value="Хай-тек">
array(
'key' => 'design',
'value' => $_GET['design'],
'compare' => 'LIKE'
),
Помогите пожалуйста, не могу понять, что я делаю не так.
Если выбираю более одного значения, в адресной строке выводится design=Классика&design=Модерн, но действует только последний выбранный.
для чекбоксов уместнее передавать значения в массиве, т.е. пропишите так name="design[]"
Спасибо за быстрый ответ, но я пробовал так писать.
<input type="checkbox" name="design[]" value="Классика">
<input type="checkbox" name="design[]" value="Модерн">
<input type="checkbox" name="design[]" value="Хай-тек">
при таком написании даже не цепляется значение чекбокса(
в адресной строке design[]=Классика
фильтр вообще не срабатывает, а WP выдает ошибку Warning: trim() expects parameter 1 to be string, array given in wp-includes/class-wp-meta-query.php on line 597
фильтр то срабатывает, но видимо в вашем обработчике данные переданного массива обрабатываются неверно, надо туда смотреть.
Еще раз здравствуйте. Вопрос возник по поводу пагинации в фильтре, стандартными методами что то не получается пишет "Страница не найдена", я так понимаю нужно номер страницы отправить GET запросом например 'paged' => $_GET['st'], с этой строчкой 'paged' => get_query_var( 'paged' ) не получается
В общем сделал через 'paged' => $_GET['st'] и paginate_links, не знаю на сколько это правильно, но все работает.
Получилось, нужно было изменить тип сравнения на IN, но теперь другая проблема, если не выбран ни один чекбокс из этого массива, фильтр ничего не выводит( Понимаю, что нужно составить условие, которое позволяло бы успешно фильтровать записи без этих чекбоксов, но не понимаю, куда его можно вписать. И не могу понять, как теперь цеплять value этих чекбоксов, чтобы стилизовать их.
https://pastebin.com/G4EtWWPf
так не получается
С условиями для подставновки нужных значений, если не чекнуты чекбоксы - разобрался. Но как получать нужные значения из массива чекбоксов и задавать эти значения соответствующим чекбоксам, пока не знаю. Может кто-нибудь подскажет?
Всем привет!
С фильтром разобрался и спасибо за него.
Подскажите пожалуйста, у меня есть произвольное поле "calories". В нем содержатся целые числа.
Я сделал сортировку вывода из этого поля таким образом:
на отдельной странице данные сортируются как надо из такого массива$args = array(
'meta_key' => 'calories',
'orderby' => 'meta_value_num',
);
добавил это поле в сортировку:
Сортировка по
дате добавления
калории
Скажите, как правильно вывести записи по такому произвольному полю "calories" через данную форму поиска?
И еще такой вопрос, можно ли сделать массив из meta_key? Ведь в форме уже используется ключ:
'meta_key' => $_GET['meta_key']
Если выводить через meta_query 'key' => 'calories', то данные не сортируются вообще никак.
форма, в которую добавил:
_select name="orderby"_
_option value="date"_дате добавления_/option_
_option value="calories"_калории_/option_
_/select_
Здравствуйте.
Технические вопросы задаем на форуме https://codeseller.ru/forum/faq/
Создавайте новую тему и давайте ссылкой отсылку к данной статье.
Комментарии для этого не приспособлены