Делаем поиск по множественным TV

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

Ну и чтобы всё это было встроено в админку и легко редактировалось, разумеется. А надо сказать, что я работала с разными CMS - от дорогого и тяжеловесного Битрикса до самописных простеньких движочков, и в конце концов остановила свой выбор на MODx - ибо, не сочтите за рекламу/антирекламу, но то, что на том же Битриксе делалось за неделю (а именно - несложный корпоративный сайтец), на MODx спокойно делается за день.

Я к чему это, собственно, пишу. В практически любой CMS для реализации этой задачи пришлось бы писать дополнительный код и всячески извращаться. В MODx же это решается при помощи исключительно стандартных средств движка, и единственная вещь, которую приходится писать "ручками" - это непосредственно сама форма поиска. Пусть неочевидно (пришлось всё же покопаться по документации, пока сообразила) - но всё ж полезно.

Итак, задача разбивается на следующие этапы:

  1. Создать TV для свойств, по которым будет происходить поиск.
  2. Задать шаблон и логику для выводов результатов поиска.
  3. Создать саму форму поиска.

 

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

Семантически наша база квартир будет представлять из себя контейнер с публикациями (выделенный в отдельную группу документов, чтобы не было путаницы). Одна квартира - одна публикация, и параметры TV в данном случае для каждой публикации о квартире исполнят роль этих самых свойств. Примерно вот так:

структура документов
свойства публикации

Чтобы при редактировании публикации с квартирой у нас получалась вот такая вот красота, мы идём в "Управление ресурсами" -> "Параметры (TV)", и для каждого параметра задаём выпадающий список примерно вот так:

задаём параметр

Да, разделителем для возможных значений служит "||", а значение по умолчанию на всякий случай делаем пустым.

Теперь создаём новый документ в корне сайта. Называем его как хотим, что-нибудь типа "поиск". И вместо того, чтобы писать свои сниппеты и всячески извращаться, используем магию стандартного и дико мощного Ditto. Вставляем в тело документа следующее:

[!Ditto? &tpl=`Apartments` &startID=`52` &filter=`tvrooms,@EVAL return $_POST['rooms'];,1|tvcity,@EVAL return $_POST['city'];,1|tvregion,@EVAL return $_POST['region'];,1|tvplan,@EVAL return $_POST['plan'];,1|tvcost,@EVAL return $_POST['cost'];,1` &noResults=`Извините, недвижимости по Вашему запросу не найдено.`!]

Разберём, что делает этот вызов.

&tpl=`Apartments` - определяем, как будет называться чанк с шаблоном для вывода найденных публикаций. Обычный чанк для Ditto, думаю, не надо отдельно говорить, как его создавать.

&startID=`52` - ID контейнера с публикациями, по которому делается выборка. В нашем случае, как видно на скриншоте, это 52.

&filter=`tvrooms,@EVAL return $_POST['rooms'];,1... - самая волшебная штука. Это, как можно догадаться, фильтр, по которому отсеиваются ненужные нам значения и выбираются нужные. В зацитированном логика такова: "отсеять все документы, значения TV-параметра rooms которого НЕ РАВНО значению php-переменной rooms из суперглобального массива $_POST".

То есть у нас есть три аргумента, разделённых запятыми. Первый - это параметр, по которому фильтруем (если это TV-параметр - то добавляем TV к его названию для указания на это). Второй - это значение параметра. В данном случае мы используем вызов @EVAL, чтобы выполнить PHP-код с прямым указанием на переменную из $_POST. Ну и третий параметр - это указатель на логический оператор, связывающий между собой параметр и значение. Единица означает "не равно", да (подробнее об этом можно прочитать вот тут). Ну и, собственно, такие правила фильтрации можно объединять при помощи символа "|", соответствующего логическому "ИЛИ". Что мы и делаем для того, чтобы объединить в один фильтр все наши TV-параметры.

Кстати, обратите внимание, что названия TV-параметров и названия переменных в $_POST сделаны одинаковыми. Это для удобства, чтобы не было никакой путаницы.

А теперь последний штрих - создаём чанк с формой поиска, выпадающие списки в которой называем - угадайте как? - да-да, именно так же, как TV-параметры. Значения option пишем те же, что и при задании параметров (пока не пробовала искать способ, чтобы это происходило автоматически, но попробую обязательно). А в атрибуте action тэга form указываем URL страницы поиска с вызовом Ditto. Называем чанк как хотим, например, SearchForm - и вставляем его на все страницы, с которых мы хотим производить поиск, при помощи вызова . Вуаля!

Так можно делать привязки и формы поиска по каким угодно расширенным параметрам, не написав при этом ни строчки PHP-кода. Наслаждайтесь!

автор статьи Ad-Astra

с 1 по 10 из 33 | Далее | Последние
new comment 15.11.2007, 19:36:36

Ad-Astra, я тебя обожаю!) как раз то что нужно)

new comment 18.11.2007, 10:48:49

Спасибо за статью! Было очень интересно. :)

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

С уважением, Владимир.

new comment 18.11.2007, 11:09:08

Забыл только на один момент обратить внимание в этой статье - что НЕ безопасно использовать $_POST для передачи непосредственно в Ditto или куда-нибудь еще. Лучше предварительно обязательно проэскейпить:

@EVAL return mysql_escape_string($_POST['region']);

new comment 18.11.2007, 23:06:27

2 Владимир:

Если не сложно, можно воспользоваться этим сниппетом? просто такая же задача стоит) буду очень благодарен) почта: polinas (собачка) newmail.ru

new comment 19.11.2007, 02:38:00

2Владими Ким: а разве Ditto сам не эскейпит параметры?

new comment 17.12.2007, 23:29:33

А как сделать разбиение вывода по страницам? Например, в результате работы фильтра выводится 50 элементов на страницу. А как сделать разбиение, например, по 10? Пробовал по аналогии с блогом, ничего не выходит - ведь сама страница результатов с вызовом Дитто не содержит в себе дочерние документы, над которыми работает фильтр.

new comment 06.02.2008, 12:31:38

Я не все понял. Только познаю MODx.

Спасибо за статью

<a href=google.ru>поиск</a>:)

new comment 06.02.2008, 12:33:48

В MODx ссылки вешать нельзя что-ли?

[url=http://google.ru]поиск[/url]:)

mac
new comment 03.03.2008, 02:12:58

А как при таком способе реализовать в форме пункт "Все"?

new comment 03.03.2008, 21:24:33

Еще вопрос. Как при поиске организовать постраничный вывод результатов поиска? Если стандартным методом <div id="pages-list"> Стр. </div> То следующие странички ни чего не найдут. Они не будут знать фильтра поиска.

с 1 по 10 из 33 | Далее | Последние

Добавить комментарий

Для форматирования используйте синтаксис Markdown. Если вы не можете разобрать символы в рисунке, нажмите на него для автоматического обновления
Если вы не можете разобрать символы в рисунке, нажмите на него для автоматического обновления
Код безопасности: