Поиск по произвольным полям.


Я рассчитываю на аудиторию, которая уже понимает как работают операторы MySQL и как строить GET или POST запрос.
Прежде чем начинать работать с поиском его надо включить в админке плагина есть галочка.

Поиск можно осуществлять либо через GET запрос, то есть сформировать соответствующий URL (ссылку), либо по средствам POST – отправив данные через форму поиска.
Фильтр обработчик запросов находится в файле ads_filters.php – строка 167 function ads_queryfilter($query) и function ads_wp_request($query_vars) строка 321.

Общий синтаксис запроса:
имя_переменной[оператор] = значение
оператор в квадратных скобках может отсутствует
имя_переменной = значение

Список операторов:

оператора нет LIKE ‘%$value%’ (ищет вхождение строки)
more > (больше)
less < (меньше)
moe >= (больше или равно)
loe <= (меньше или равно)
ne ( не равно )
isnull ISNULL ( если пусто )
notnull NOT ISNULL( если не пусто )
between BETWEEN (проверка диапазона)
in IN (принадлежность к множеству)
rlike rlike (регулярные выражения)

Простейший пример:
http://wp.od.ua/test/?ads_name=петр
Результат получим не совсем то, что ожидали, тоесть найдутся все записи в которых есть вхождение петр, причем регистр не учитывается. Это есть не что иное как SQL оператор LIKE, причем выражение взято в проценты вот так:
ads_name LIKE ‘%петр%’
В предыдущих версиях плагина я решил, что от простого знака равно толку мало и поставил LIKE, ну так оно и осталось пока – жалоб не поступало, и практика показала, что так намного функциональные. Теперь, когда мы знаем про оператор LIKE давайте найдем все объявления с почтой @gmail.com:
http://wp.od.ua/test/?ads_email=gmail.com

Рас уж начали с поиска строк то попробуем усложнить – используем регулярные выражения SQL оператор rlike.
Найдем объявления от автора Петр, чтобы было именно такое имя а не вхождение строки :
http://wp.od.ua/test/?ads_name[rlike]=(^| )Петр($| )
Url в браузере будет преобразован в http://wp.od.ua/test/?ads_name[rlike]=(^|%20)%D0%9F%D0%B5%D1%82%D1%80($|%20)
А сам патерн такой : (^| )Петр($| )

Найдем записи у которых поле цена ads_price больше 1000:
http://wp.od.ua/test/?ads_price[more]=1000
Объявления где цена меньше либо равно 1000:
http://wp.od.ua/test/?ads_price[loe]=1000

ОТ и ДО – диапазон от 1000 до 5000 :
http://wp.od.ua/test/?ads_price[between][0]=1000&ads_price[between][1]=5000
ads_price[between][0]=1000 – задаем нижнюю границу
ads_price[between][1]=5000 – задаем верхнюю границу
Как вариант можно сделать и так:
http://wp.od.ua/test/?ads_price[moe]=200&ads_price[loe]=5000
но по производительности between лучше.

Объявления у которых не указан телефон:
http://wp.od.ua/test/?ads_phones[isnull]=1

Пример с IN (принадлежность к множеству):
http://wp.od.ua/test/?ads_price[in][]=200&ads_price[in][]=750&ads_price[in][]=1000
Найдет все об. у которых цена равна 200 либо 750 либо 1000 – пример немного надуманный, но для иллюстрации механизма пойдет.

Комбинирование условий

Найдем записи у которых цена в диапазоне от 1000 до 5000 и есть в наличии телефон:
http://wp.od.ua/test/?ads_price[moe]=200&ads_price[loe]=5000&ads_phones[notnull]=1

Из определенной категории например куплю продам:
http://wp.od.ua/test/?ads_price[moe]=200&ads_price[loe]=5000&ads_phones[notnull]=1&category_name=kuplyu-prodam

Можно подключить стандартный поиск WordPress. Если мы хотим найти какую-то фразу в заголовке или основном тексте используем переменную s. Найдем записи в которых есть слово Путин и цена меньше 4000:
http://wp.od.ua/test/?ads_price[loe]=4000&s=Путин

Поиск по категориям

WordPress позволяет задавать очень сложные запросы оперирую таксономиями http://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters в плагине я добавил обработчик параметра category__and таким образом мы можем затребовать записи из разных категорий объедения условия через логическое И.
Получить записи из категории Москва(id:5) И Куплюпродам(id:10)
http://wp.od.ua/test/?category__and[]=5&category__and[]=10
Этот параметр обрабатывает фильтр function ads_wp_request.

И еще больше расширений

Если вам перечисленных возможностей недостаточно то для каждой переменной можно назначить свою пользовательскую функцию, имя функции должно начинаться с названия переменной и суффикса _query. Так для переменной ads_quality можно назначить свою функцию которая должна вернуть правильный SQL текст с условием поиска и обязательное условие в тексте должен первым идти оператор AND:

function ads_quality_query($value){ ……… return ‘ AND ‘. ваше условие поиска; }

1234 function ads_quality_query($value){   .........   return ‘ AND ‘. ваше условие поиска;}

Организуем продвинутый поиск по дате post_date стандартное поле WP.
Если указан ключ dmoe ищем объявления начиная от этой даты и старше.
Если указан ключ day ищем записи за этот день.
В ads_config.php добавляем наш обработчик:

//добавляем обработчик переменой для поиска по дате function post_date_query($var){ global $wpdb; echo ‘[crayon-5f6605a32b11d501337201 ]’; print_r($var); echo ‘

1234 //добавляем обработчик переменой для поиска по датеfunction post_date_query($var){    global $wpdb;    echo ‘[crayon-5f6605a32b11d501337201 ]’; print_r($var); echo

’;
if(is_array($var) )
list($key, $val) = each($var);
if($key==’dmoe’)
return ” AND $wpdb->posts.post_date >= STR_TO_DATE( $val, ‘%Y-%m-%d’) “;
elseif($key==’day’)
return ” AND TO_DAYS($wpdb->posts.post_date) = TO_DAYS( “.$var[‘day’].”) “;
}
[/crayon]
Теперь можно проверить – ищем объявления за 2013-06-08 (формат даты соблюдать!) и цена от 750:
http://wp.od.ua/test/?post_date[day]=2013-06-08&ads_price[moe]=750

Вариант 2 найдем записи из категории Москва:5 И продам:18 начиная с марта 2013:
http://wp.od.ua/test/?category__and[]=5&category__and[]=18&post_date[dmoe]=2013-03-01

Диапазон по возрасту

Еще пример – поиск в диапазоне по возрасту пример с сайта http://musme.ru/musicians в качестве элемента управления используется слайдер ion.rangeSlider, как он подключается это вопрос отдельный, нам же надо знать, что этот элемент пришлет на сервер в переменой ads_old двойное значение например 20;30 то есть искать музыканта от 20 до 30 лет например.
В ads_old у нас хранится дата рождения в формате 1974-03-31 – хороший формат позволяет сравнивать строку с годом(число) без лишних преобразований и форматирований.
Теперь нам надо обработать двойное значение от слайдера:

function ads_old_query($var){ list($from, $to) = explode(‘;’,$_REQUEST[‘ads_old’]); $Y = (int)date(«Y»); $y_start = $Y — $to; $y_end = $Y — $from; return «AND ads_old.meta_value >= $y_start AND ads_old.meta_value <= $y_end «; }

1234567 function ads_old_query($var){    list($from, $to) = explode(‘;’,$_REQUEST[‘ads_old’]);    $Y = (int)date(«Y»);    $y_start = $Y $to;    $y_end = $Y $from;    return «AND  ads_old.meta_value >= $y_start AND ads_old.meta_value <= $y_end «;}

Сортировка

Чтобы задать сортировку записей по какому либо полю используйте след синтаксис:
ads_order[ads_name_var]=sort где
ads_name_var имя поля по которому вы хотите задать сортировку;
sort указание типа сортировки может принимать след значения :

  • asc по возрастанию
  • desc по убыванию
  • iasc по возрастанию с конвертацией в число
  • idesc по убыванию с конвертацией в число

Например найдем записи у которых указано имя и отсортируем записи по алфавиту
http://wp.od.ua/test/?ads_order[ads_name]=asc&ads_name[notnull]=1
SQL: ORDER BY ads_name.meta_value ASC

Как я уже говорил выше, кроме простой сортировки есть сортировка с принудительной конвертацией значений к числу. Дело в том, что в мета полях, если вы записываете число, то оно сохраняется как строка т.к. тип столбца строковый, поэтому, если в мета поле хранится число то надо использовать вместо asc iasc.
Найдем записи у которых есть цена и отсортируем по возрастанию:
http://wp.od.ua/test/?ads_order[ads_price]=iasc&ads_price[notnull]=1
SQL: ORDER BY ads_price.meta_value+0 ASC
Сортировку можно комбинировать в этом случае имеет значение порядок переменных первый получает высший приоритет.

З.Ы.
Ну и напоследок, хочу обратить выше внимание на замечательную функцию worpdpress add_query_arg() при конструировании url ссылок может сильно облегчить вашу задачу.