Joomla 1.5 Мануал о том, как модифицировать поиск под свои нужды.

Тема в разделе "Программирование", создана пользователем omfgpanda, 08.02.2010.

  1. omfgpanda
    Offline

    omfgpanda специалист

    Регистрация:
    22.01.2008
    Сообщения:
    673
    Симпатии:
    53
    Пол:
    Мужской
    Данную статью я решил написать вод воздействием ... нет, ни грибов ))) ... а много численных постов в асю и личку.

    Перед началом работы хочу предупредить - ВСЕ манипуляции вы делаете на свой страх и риск! Если вы новичек НЕ ЗАБУДЬТЕ сделать бекапы.

    Протестировано на J1.5.11.

    И так, приступим :)

    Все начинается с того, что Вам необходимо модифицировать стандартную форму поиска, а точнее добавить туда нужные Вам поля.
    Топаем в:
    Код (CODE):
    1. components/com_search/views/search/tmpl/default_form.php

    С первых строк в нем описывается форма, туда нужно добавить необходимые Вам поля.
    В своем примере я буду использовать два поля типа TEXT и именами param1 и param2.
    Код (html):
    1. <td nowrap="nowrap">
    2.                 <input type="text" name="param1" id="search_param1" size="10" maxlength="20" value="<?php echo JRequest::getInt('param1'); ?>" class="inputbox" />
    3.             </td>
    4.             <td nowrap="nowrap">
    5.                 <input type="text" name="param2" id="search_param2" size="10" maxlength="20" value="<?php echo JRequest::getInt('param2'); ?>" class="inputbox" />
    6.             </td>


    После того, как поля были добавлены, Вам необходимо получить значения, введенные в эти поля.
    Топаем в
    Код (CODE):
    1. components/com_search/controller.php

    Строка 41, function search():
    В теле функции необходимо получить значения, переданные из формы.
    Я передаю два числа, поэтому и обрабатываю с помощью метода getInt класса JRequest.
    getString - строка, getVar - общий тип данных, если так можно выразиться...
    Для получения других типов данных рекомендую почитать документацию.
    Код (PHP):
    1. $post["param1"] = JRequest::getInt('param1');
    2.         $post["param2"] = JRequest::getInt('param2');

    В ассоциативном массиве $post накапливаются пары "ключ" - "значение" для формирования строки GET-запроса.


    Теперь настало время получить данные и сформировать sql-запрос для выборки.

    Топаем в
    Код (CODE):
    1. component/com_search/models/search.php

    строка 62, конструктор (function __construct()), получаем наши параметры

    Код (PHP):
    1. $arrParams["param1"] = JRequest::getInt('param1');
    2. $arrParams["param2"] = JRequest::getInt('param2');

    и модифицируем вызов функции setSearch():
    Код (PHP):
    1. $this->setSearch($keyword, $arrParams, $match, $ordering);

    теперь конструктор выглядит так:
    Код (PHP):
    1. function __construct()
    2.     {
    3.         parent::__construct();
    4.  
    5.         global $mainframe;
    6.  
    7.         //Get configuration
    8.         $config = JFactory::getConfig();
    9.  
    10.         // Get the pagination request variables
    11.         $this->setState('limit', $mainframe->getUserStateFromRequest('com_search.limit', 'limit',
    12.                   $config->getValue('config.list_limit'), 'int'));
    13.         $this->setState('limitstart', JRequest::getVar('limitstart', 0, '', 'int'));
    14.  
    15.         // Set the search parameters
    16.         $arrParams = array();
    17.         $keyword        = urldecode(JRequest::getString('searchword'));
    18.         $match          = JRequest::getWord('searchphrase', 'all');
    19.         $arrParams["param1"] = JRequest::getInt('param1');
    20.         $arrParams["param2"] = JRequest::getInt('param2');
    21.        // print_r($arrParams);
    22.         $ordering       = JRequest::getWord('ordering', 'newest');
    23.         $this->setSearch($keyword, $arrParams, $match, $ordering);
    24.  
    25.         //Set the search areas
    26.         $areas = JRequest::getVar('areas');
    27.         $this->setAreas($areas);
    28.     }

    Было принято решение использовать массив для хранения дополнительных параметров, массивы очень удобны для динамических структур - за ранее количество параметров не известно, и что бы постоянно не модифицировать функции - используем массив параметров.

    Далее нужно модифицировать саму функцию(строка 98 - function setSearch()).
    Изменяем заголовок функции:
    Код (PHP):
    1. function setSearch($keyword, $arrParams = array(), $match = 'all', $ordering = 'newest')

    Добавляем дополнительный блок для обработки Вашего массива с параметрами:
    Код (PHP):
    1. if(count($arrParams))
    2.              $this->setState('arrParams', $arrParams);

    Получаем модифицированную функцию setSearch():
    Код (PHP):
    1. function setSearch($keyword, $arrParams = array(), $match = 'all', $ordering = 'newest')
    2.     {
    3.         if(isset($keyword)) {
    4.             $this->setState('keyword', $keyword);
    5.         }
    6.        
    7.         if(isset($keyword)) {
    8.             $this->setState('keyword', $keyword);
    9.         }
    10.  
    11.         if(isset($match)) {
    12.             $this->setState('match', $match);
    13.         }
    14.  
    15.         if(isset($ordering)) {
    16.             $this->setState('ordering', $ordering);
    17.         }
    18.        
    19.         if(count($arrParams))
    20.              $this->setState('arrParams', $arrParams);
    21.              
    22.             // print_r($arrParams);
    23.     }

    Немного прервусь и объясню логику этой замечательной конструкции....
    Дело в том, что поиск в джумле устроен по очень хитрому механизму:
    1. Модуль - используется для вывода упрощенной формы поиска на сайте. После отправки формы модуль передает управление компоненту.
    2. Компонент(com_search) - используется для вывода полноценной формы поиска и вывода результатов поиска. Компонент сам не обладает механизмом обработки запроса, вместо этого он инициализирует событие OnSearch, которое, в свою очередь, перехватывают плагины, которые расположены в папке
    Код (CODE):
    1. plugins/search/

    Так вот, к чему я все это... метод "setState" позволяет передавать параметры внутри классов, которые используются при обработке результатов запроса.

    Вернемся к search.php, строка 141, функция getData():
    В данной функции управление передается плагинам поиска и обрабатывается результат запроса, который нас, в данной ситуации не интересует.
    Строка 148
    Код (PHP):
    1. JPluginHelper::importPlugin( 'search');
    2.             $dispatcher =& JDispatcher::getInstance();
    3.             $results = $dispatcher->trigger( 'onSearch', array(
    4.             $this->getState('keyword'),
    5.             $this->getState('match'),
    6.             $this->getState('ordering'),
    7.             $areas['active']) );

    Нам нужно передать наш массив с дополнительными параметрами, получим:
    Код (PHP):
    1. JPluginHelper::importPlugin( 'search');
    2.             $dispatcher =& JDispatcher::getInstance();
    3.             $results = $dispatcher->trigger( 'onSearch', array(
    4.             $this->getState('keyword'),
    5.                         $this->getState('arrParams'),
    6.             $this->getState('match'),
    7.             $this->getState('ordering'),
    8.             $areas['active']) );


    Работа с компонентом завершена и теперь переходим к работе с плагином.
    Топаем в
    Код (CODE):
    1. plugins/search/content.php

    Этот плагин отвечает за поиск по таблице jos_content.
    Строка 42, функция plgSearchContent(), меняем заголовок функции:
    Код (PHP):
    1. function plgSearchContent( $text, $arrParams = array(),$phrase='', $ordering='', $areas=null )

    Теперь, в теле функции нам доступен массив с дополнительными параметрами. Осталось модифицировать sql-запрос.
    Строка 82, блок, отвечающий за формирование куска запроса с условиями выборки, его то нам и нужно )
    Код (PHP):
    1. switch ($phrase) {
    2.         case 'exact':
    3.             $text       = $db->Quote( '%'.$db->getEscaped( $text, true ).'%', false );
    4.             $wheres2    = array();
    5.             $wheres2[]  = 'a.title LIKE '.$text;
    6.             $wheres2[]  = 'a.introtext LIKE '.$text;
    7.             $wheres2[]  = 'a.fulltext LIKE '.$text;
    8.             $wheres2[]  = 'a.metakey LIKE '.$text;
    9.             $wheres2[]  = 'a.metadesc LIKE '.$text;
    10.             $where      = '(' . implode( ') OR (', $wheres2 ) . ')';
    11.             break;
    12.  
    13.         case 'all':
    14.         case 'any':
    15.         default:
    16.             $words = explode( ' ', $text );
    17.             $wheres = array();
    18.             foreach ($words as $word) {
    19.                 $word       = $db->Quote( '%'.$db->getEscaped( $word, true ).'%', false );
    20.                 $wheres2    = array();
    21.                 $wheres2[]  = 'a.title LIKE '.$word;
    22.                 $wheres2[]  = 'a.introtext LIKE '.$word;
    23.                 $wheres2[]  = 'a.fulltext LIKE '.$word;
    24.                 $wheres2[]  = 'a.metakey LIKE '.$word;
    25.                 $wheres2[]  = 'a.metadesc LIKE '.$word;
    26.                 $wheres[]   = implode( ' OR ', $wheres2 );
    27.             }
    28.             $where = '(' . implode( ($phrase == 'all' ? ') AND (' : ') OR ('), $wheres ) . ')';
    29.             break;
    30.     }

    Добавляем наши параметры и получаем:
    Код (PHP):
    1. switch ($phrase) {
    2.         case 'exact':
    3.             $text       = $db->Quote( '%'.$db->getEscaped( $text, true ).'%', false );
    4.             $wheres2    = array();
    5.             $wheres2[]  = 'a.title LIKE '.$text;
    6.             $wheres2[]  = 'a.introtext LIKE '.$text;
    7.             $wheres2[]  = 'a.fulltext LIKE '.$text;
    8.             $wheres2[]  = 'a.metakey LIKE '.$text;
    9.             $wheres2[]  = 'a.metadesc LIKE '.$text;
    10.                         $wheres2[] = 'a.field_name1 LIKE '.$arrParams["param1"];    
    11.                         $wheres2[] = 'a.field_name2 LIKE '.$arrParams["param2"];
    12.             $where      = '(' . implode( ') OR (', $wheres2 ) . ')';
    13.             break;
    14.  
    15.         case 'all':
    16.         case 'any':
    17.         default:
    18.             $words = explode( ' ', $text );
    19.             $wheres = array();
    20.             foreach ($words as $word) {
    21.                 $word       = $db->Quote( '%'.$db->getEscaped( $word, true ).'%', false );
    22.                 $wheres2    = array();
    23.                 $wheres2[]  = 'a.title LIKE '.$word;
    24.                 $wheres2[]  = 'a.introtext LIKE '.$word;
    25.                 $wheres2[]  = 'a.fulltext LIKE '.$word;
    26.                 $wheres2[]  = 'a.metakey LIKE '.$word;
    27.                 $wheres2[]  = 'a.metadesc LIKE '.$word;
    28.                                 $wheres2[] = 'a.field_name1 = '.$arrParams["param1"];    
    29.                                 $wheres2[] = 'a.field_name2 = '.$arrParams["param2"];
    30.                 $wheres[]   = implode( ' OR ', $wheres2 );
    31.             }
    32.             $where = '(' . implode( ($phrase == 'all' ? ') AND (' : ') OR ('), $wheres ) . ')';
    33.             break;
    34.     }

    Тут очень важно, что бы имена полей, которые Вы используете в условиях присутствовали в таблице, в нашем случае - jos_content. В противном случае вы получите фатал при запросе.

    Также использование оператора "=" не принципиально, используете любой подходящий Вам оператор.

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

    Любая адекватная критика приветствуется ;)
     
    Последнее редактирование: 12.02.2010
    Asylum и Gronpipmaster нравится это.
  2.  
  3. Gronpipmaster
    Offline

    Gronpipmaster специалист

    Регистрация:
    21.01.2009
    Сообщения:
    1 392
    Симпатии:
    62
    Пол:
    Мужской
    хорошо расписали, спасибо большое, я бы скрины добавил результата, что-бы можно было увидеть результат того что получится, но задачи разные, хотя бы для вашего примера
     
  4. Offline

    botanist специалист

    Регистрация:
    15.02.2009
    Сообщения:
    461
    Симпатии:
    49
    Пол:
    Мужской
    plugins/search/content.php
     
  5. Asylum
    Offline

    Asylum специалист

    Регистрация:
    09.02.2007
    Сообщения:
    2 568
    Симпатии:
    152
    Пол:
    Мужской
    Интересная статья
     
  6. omfgpanda
    Offline

    omfgpanda специалист

    Регистрация:
    22.01.2008
    Сообщения:
    673
    Симпатии:
    53
    Пол:
    Мужской
    Gronpipmaster, скрины...хммм... а скрины чего Вас интересуют ? ) кода ? или внешнего вида самой формы поиска ?

    botanist, спс, исправлю )
     
  7. Asylum
    Offline

    Asylum специалист

    Регистрация:
    09.02.2007
    Сообщения:
    2 568
    Симпатии:
    152
    Пол:
    Мужской
    Скрины нужны, вникать в код это время, а скрин быстро все проясняет
     
  8. Offline

    botanist специалист

    Регистрация:
    15.02.2009
    Сообщения:
    461
    Симпатии:
    49
    Пол:
    Мужской
    Так визуально меняется только форма,
    Код (PHP):
    1. <td nowrap="nowrap">
    2.                 <input type="text" name="param1" id="search_param1" size="10" maxlength="20" value="" class="inputbox" />
    3.             </td>
    4.             <td nowrap="nowrap">
    5.                 <input type="text" name="param2" id="search_param2" size="10" maxlength="20" value="" class="inputbox" />
    6.             </td>

    все остальное не визуально. Даже вывод результатов поиска внешне не меняется.
     
  9. Gronpipmaster
    Offline

    Gronpipmaster специалист

    Регистрация:
    21.01.2009
    Сообщения:
    1 392
    Симпатии:
    62
    Пол:
    Мужской
    botanist, я вижу что должны появится 2 текстовых поля), а кто-то не видит ;)
     
  10. OlegM
    Offline

    OlegM Russian Joomla! Team Команда форума

    Регистрация:
    12.04.2007
    Сообщения:
    4 356
    Симпатии:
    370
    Пол:
    Мужской
    Да, не хватает примеров, хотя бы что требовалось сделать, тем более, что в форму добавляются простые текстовые поля, а в запросе знак =. Это ж еще надо угадать.
     
  11. omfgpanda
    Offline

    omfgpanda специалист

    Регистрация:
    22.01.2008
    Сообщения:
    673
    Симпатии:
    53
    Пол:
    Мужской
    просто за последнее время я столкнулся с массой пользователей, которые с трудом могут описать массив в пхп, не то что там где то запросы править )
     
  12. Offline

    Sanyo Недавно здесь

    Регистрация:
    26.01.2010
    Сообщения:
    4
    Симпатии:
    0
    Пол:
    Мужской
    Panda, отлично!

    Теперь я думаю у многих вопросы отпадут сами собой!

    Сделал еще вот так:
    Код (CODE):
    1. <input type="text" name="param1" id="search_param1" size="10" maxlength="20" value="<?php echo JRequest::getInt('param1'); ?>" class="inputbox" />
     
  13. omfgpanda
    Offline

    omfgpanda специалист

    Регистрация:
    22.01.2008
    Сообщения:
    673
    Симпатии:
    53
    Пол:
    Мужской
    Sanyo, действительно, было моим упущением... исправил , спс )
     
  14. Offline

    Sanyo Недавно здесь

    Регистрация:
    26.01.2010
    Сообщения:
    4
    Симпатии:
    0
    Пол:
    Мужской
    Хотим сделать что бы искалось ЛИБО по "ключевым словам" ЛИБО по "созданному полю".
    *примечание: сейчас поиск осуществляется обязательно по полю "ключевые слова" и дополнительно по "созданному полю"

    Лезем в plugins/search/content.php

    Строка 73

    Убираем:

    Код (CODE):
    1. if ($text == '') {
    2. return array();
    3. }
     
  15. omfgpanda
    Offline

    omfgpanda специалист

    Регистрация:
    22.01.2008
    Сообщения:
    673
    Симпатии:
    53
    Пол:
    Мужской
    раз уж вы решили убрать строку дефолтную строку поиска таким способом, так потрудитесь и изменить блоки "WHERE".
     
  16. Tureckiy
    Offline

    Tureckiy специалист

    Регистрация:
    11.04.2009
    Сообщения:
    423
    Симпатии:
    30
    Пол:
    Мужской
    в Джумле если нет плагина поиска для какого либо компонента можно свой по аналогии написать (если конечно метод получения записей из БД позволяет использовать множество условий, переданных постом с моделя поиска), недовно пришлось для lyftenbloggie накатать B), правда пришлось подпатчить процедуры выборки немного :)
     
  17. Tureckiy
    Offline

    Tureckiy специалист

    Регистрация:
    11.04.2009
    Сообщения:
    423
    Симпатии:
    30
    Пол:
    Мужской
    ) потому что такие вещи написаны для коллег программистов а не для пользователей Джумлы
     
  18. Offline

    juventus Недавно здесь

    Регистрация:
    29.08.2011
    Сообщения:
    25
    Симпатии:
    0
    Пол:
    Мужской
    День добрый.
    Помогите пожалуйста.
    Нужно организовать поиск по 3 полям одновреммено.
    1 поля - текст.
    Два остальных - выпадающие списки.
    Пробывал следовать примеру - не получилось.
    Может кто сталкивался? И сможет мне помочь?
    Очень срочно надо.
    Эта единственная тема которую я нашёл в nete.
    Помогите, пожалуйста.
    Заранее спасибо.
     
  19. Offline

    Knaze Недавно здесь

    Регистрация:
    13.10.2012
    Сообщения:
    1
    Симпатии:
    0
    Пол:
    Мужской
    Автору - ОГРОМНОЕ СПАСИБО!
     
    Последнее редактирование: 13.10.2012

Поделиться этой страницей

Загрузка...