Как сделать поиск товаров по определенному полю — различия между версиями
Mad grant (обсуждение | вклад) |
Mad grant (обсуждение | вклад) |
||
(не показано 10 промежуточных версий этого же участника) | |||
Строка 3: | Строка 3: | ||
== Задача == | == Задача == | ||
− | Если Вы столкнулись с данной задачей, то решить её стандартными средствами нельзя. Это можно сделать с помощью кастомного макроса, но поисковая модель UMI.CMS тоже не имеет такой возможности, поэтому нужно получать результат от поисковой модели и проверять наличие поисковой фразы прямо в нем, а отфильтрованный результат уже отдавать. Пример того, как это можно сделать дан ниже. | + | Если Вы столкнулись с данной задачей, то решить её стандартными средствами нельзя. Это можно сделать с помощью кастомного макроса, но поисковая модель UMI.CMS тоже не имеет такой возможности, поэтому нужно получать результат от поисковой модели и проверять наличие поисковой фразы прямо в нем, а отфильтрованный результат уже отдавать. Пример того, как это можно сделать дан ниже. Сразу нужно оговориться, поиск по конкретному полю в каталоге можно реализовать с помощью макроса %catalog search%, в данной же статье рассматривается поиск именно через поисковую модель, то есть он аналогичен %search search_do%. Необходимость его применения заключается в том, что поиск через поисковую модель работает намного быстрее, чем через %catalog search%, особенно это актуально для сайтов с большим объемом данных. |
== Решение == | == Решение == | ||
Строка 9: | Строка 9: | ||
%custom runSearch()% — выводит перечень страниц, у которых в указанном поле содержится поисковая фраза. | %custom runSearch()% — выводит перечень страниц, у которых в указанном поле содержится поисковая фраза. | ||
− | '''Параметры: | + | '''Параметры: runSearch($str, $h_type_id, [$field = 'h1', $parent_id, $template = 'default'])''' |
'''$str''' | '''$str''' | ||
− | Строка, которую требуется найти. | + | Строка, которую требуется найти. Передается через GET в 'str'. |
+ | '''$h_type_id''' | ||
+ | Иерархический тип, по страницам которого нужно производить поиск. | ||
'''$field ''' | '''$field ''' | ||
− | Поле, в котором производить поиск, если не указано, то равно 'h1'. | + | Поле, в котором производить поиск, если не указано, то равно 'h1'. Поле должно быть индексируемым. |
'''$parent_id''' | '''$parent_id''' | ||
Если указан, то поиск будет производится только в указанном разделе сайта. Если не указан, то - по всем разделам. | Если указан, то поиск будет производится только в указанном разделе сайта. Если не указан, то - по всем разделам. | ||
− | |||
− | |||
'''$template ''' | '''$template ''' | ||
Шаблон, по которому выводится результат макроса. В XSLT-шаблонизаторе игнорируется. По-умолчанию равен 'default'. | Шаблон, по которому выводится результат макроса. В XSLT-шаблонизаторе игнорируется. По-умолчанию равен 'default'. | ||
Строка 25: | Строка 25: | ||
<source lang="php"> | <source lang="php"> | ||
− | + | public function runSearch($str, $h_type_id, $field = 'h1', $parent_id, $template = 'default'){ | |
− | + | ||
− | + | if (!$str) $str = (string) getRequest('str'); | |
− | + | $str = urldecode($str); | |
− | + | $str = htmlspecialchars($str); | |
− | + | $str = str_replace(". ", " ", $str); | |
− | + | $str = trim($str, " \t\r\n%"); | |
− | + | $str = str_replace(array('"', "'"), "", $str); | |
− | + | ||
− | + | if (!$str) return; | |
− | + | ||
− | + | $h_type_id = intval($h_type_id); | |
− | + | $parent_id = intval($parent_id); | |
− | + | $hierarchy = umiHierarchy::getInstance(); | |
− | + | $search = searchModel::getInstance(); | |
− | + | $h_types_col = umiHierarchyTypesCollection::getInstance(); | |
− | + | $o_types_col = umiObjectTypesCollection::getInstance(); | |
− | + | $fields = umiFieldsCollection::getInstance(); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | if($h_type_id == 0 || !$h_types_col->isExists($h_type_id)){ | |
− | + | $h_type_id = false; | |
− | + | $field = 'h1'; | |
− | + | }else{ | |
− | + | $o_types_arr = $o_types_col->getTypesByHierarchyTypeId($h_type_id); | |
− | + | $test = 0; | |
− | + | foreach($o_types_arr as $key=>$value){ | |
− | + | $o_type = $o_types_col->getType($key); | |
− | + | if($o_type->getFieldId($field)){ | |
− | $ | + | $field_id = $o_type->getFieldId($field); |
− | + | $field_object = $fields->getField($field_id); | |
+ | if($field_object->getIsInSearch()){ | ||
+ | $test++; | ||
+ | break; | ||
} | } | ||
} | } | ||
− | $items = array(' | + | } |
− | $ | + | if($test == 0){ |
− | + | $field = 'artikul'; | |
+ | } | ||
+ | } | ||
+ | if(!$hierarchy->getElement($parent_id)){ | ||
+ | $parent_id = false; | ||
+ | } | ||
+ | $products_ids = array(); | ||
+ | $products_ids = $search->runSearch( '%' . $str, $h_type_id, $parent_id, false); | ||
+ | |||
+ | list($items_template, $item_template, $empty_template) = def_module::loadTemplates('search/' . $template, 'items', 'item', 'empty'); | ||
+ | |||
+ | if(count($products_ids) == 0){ | ||
+ | $empty = array(); | ||
+ | $empty['request'] = $str; | ||
+ | return def_module::parseTemplate($empty_template, $empty); | ||
+ | } | ||
+ | |||
+ | $item = array(); | ||
+ | $items = array(); | ||
+ | $count = 0; | ||
+ | foreach($products_ids as $product_id){ | ||
+ | if(stripos($hierarchy->getElement($product_id)->getValue($field), $str) !== false){ | ||
+ | $item['attribute:id'] = $hierarchy->getElement($product_id)->id; | ||
+ | $item['attribute:link'] = $hierarchy->getElement($product_id)->link; | ||
+ | $item['attribute:name'] = $hierarchy->getElement($product_id)->getName(); | ||
+ | $item["attribute:$field"] = $hierarchy->getElement($product_id)->getValue($field); | ||
+ | $count++; | ||
+ | $items[] = def_module::parseTemplate($item_template, $item); | ||
} | } | ||
+ | } | ||
+ | $items = array('subnodes:items' => $items); | ||
+ | $items['total'] = $count; | ||
+ | $items['request'] = $str; | ||
+ | return def_module::parseTemplate($items_template, $items); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | == Пример реализации для tpl == | ||
+ | |||
+ | В шаблон страницы, на которой Вы хотите видеть результат помещается макрос и простенькая форма, в action указывается текущая страница. | ||
+ | |||
+ | Пример: | ||
+ | |||
+ | <source lang="html4strict"> | ||
+ | <form method="get" action="/glavnaya"> | ||
+ | <input type="text" name="str" value="" /> | ||
+ | <input type="submit" value="Найти!"/> | ||
+ | </form> | ||
+ | %custom runSearch('', '38', 'artikul', '', 'default')% | ||
+ | </source> | ||
+ | |||
+ | Потом откройте файл шаблон /tpls/search/default.tpl и добавьте в него следующие блоки: | ||
+ | |||
+ | <source lang="html4strict"> | ||
+ | $FORMS['items'] = <<<END | ||
+ | <table> | ||
+ | <tr> | ||
+ | По запросу "%request%" найдено %total%: | ||
+ | </tr> | ||
+ | %items% | ||
+ | </table> | ||
+ | END; | ||
+ | |||
+ | $FORMS['item'] = <<<END | ||
+ | <tr> | ||
+ | <td> | ||
+ | Артикул: %artikul% | ||
+ | </td> | ||
+ | <td> | ||
+ | Товар: <a href="%link%">%name%</a> | ||
+ | </td> | ||
+ | </tr> | ||
+ | END; | ||
+ | |||
+ | $FORMS['empty'] = <<<END | ||
+ | <p>По Вашему запросу "%request%" ничего не найдено.</p> | ||
+ | END; | ||
</source> | </source> | ||
[[category:Модуль Каталог]][[category:Модуль_Поиск]][[category:API]] | [[category:Модуль Каталог]][[category:Модуль_Поиск]][[category:API]] |
Текущая версия на 08:34, 21 марта 2014
Актуально для версии 2.9.5
Задача
Если Вы столкнулись с данной задачей, то решить её стандартными средствами нельзя. Это можно сделать с помощью кастомного макроса, но поисковая модель UMI.CMS тоже не имеет такой возможности, поэтому нужно получать результат от поисковой модели и проверять наличие поисковой фразы прямо в нем, а отфильтрованный результат уже отдавать. Пример того, как это можно сделать дан ниже. Сразу нужно оговориться, поиск по конкретному полю в каталоге можно реализовать с помощью макроса %catalog search%, в данной же статье рассматривается поиск именно через поисковую модель, то есть он аналогичен %search search_do%. Необходимость его применения заключается в том, что поиск через поисковую модель работает намного быстрее, чем через %catalog search%, особенно это актуально для сайтов с большим объемом данных.
Решение
%custom runSearch()% — выводит перечень страниц, у которых в указанном поле содержится поисковая фраза.
Параметры: runSearch($str, $h_type_id, [$field = 'h1', $parent_id, $template = 'default'])
$str
Строка, которую требуется найти. Передается через GET в 'str'.
$h_type_id
Иерархический тип, по страницам которого нужно производить поиск.
$field
Поле, в котором производить поиск, если не указано, то равно 'h1'. Поле должно быть индексируемым.
$parent_id
Если указан, то поиск будет производится только в указанном разделе сайта. Если не указан, то - по всем разделам.
$template
Шаблон, по которому выводится результат макроса. В XSLT-шаблонизаторе игнорируется. По-умолчанию равен 'default'.
Для применения этого макроса скопируйте содержимое листинга макроса в файл /classes/modules/custom.php.
public function runSearch($str, $h_type_id, $field = 'h1', $parent_id, $template = 'default'){
if (!$str) $str = (string) getRequest('str');
$str = urldecode($str);
$str = htmlspecialchars($str);
$str = str_replace(". ", " ", $str);
$str = trim($str, " \t\r\n%");
$str = str_replace(array('"', "'"), "", $str);
if (!$str) return;
$h_type_id = intval($h_type_id);
$parent_id = intval($parent_id);
$hierarchy = umiHierarchy::getInstance();
$search = searchModel::getInstance();
$h_types_col = umiHierarchyTypesCollection::getInstance();
$o_types_col = umiObjectTypesCollection::getInstance();
$fields = umiFieldsCollection::getInstance();
if($h_type_id == 0 || !$h_types_col->isExists($h_type_id)){
$h_type_id = false;
$field = 'h1';
}else{
$o_types_arr = $o_types_col->getTypesByHierarchyTypeId($h_type_id);
$test = 0;
foreach($o_types_arr as $key=>$value){
$o_type = $o_types_col->getType($key);
if($o_type->getFieldId($field)){
$field_id = $o_type->getFieldId($field);
$field_object = $fields->getField($field_id);
if($field_object->getIsInSearch()){
$test++;
break;
}
}
}
if($test == 0){
$field = 'artikul';
}
}
if(!$hierarchy->getElement($parent_id)){
$parent_id = false;
}
$products_ids = array();
$products_ids = $search->runSearch( '%' . $str, $h_type_id, $parent_id, false);
list($items_template, $item_template, $empty_template) = def_module::loadTemplates('search/' . $template, 'items', 'item', 'empty');
if(count($products_ids) == 0){
$empty = array();
$empty['request'] = $str;
return def_module::parseTemplate($empty_template, $empty);
}
$item = array();
$items = array();
$count = 0;
foreach($products_ids as $product_id){
if(stripos($hierarchy->getElement($product_id)->getValue($field), $str) !== false){
$item['attribute:id'] = $hierarchy->getElement($product_id)->id;
$item['attribute:link'] = $hierarchy->getElement($product_id)->link;
$item['attribute:name'] = $hierarchy->getElement($product_id)->getName();
$item["attribute:$field"] = $hierarchy->getElement($product_id)->getValue($field);
$count++;
$items[] = def_module::parseTemplate($item_template, $item);
}
}
$items = array('subnodes:items' => $items);
$items['total'] = $count;
$items['request'] = $str;
return def_module::parseTemplate($items_template, $items);
}
Пример реализации для tpl
В шаблон страницы, на которой Вы хотите видеть результат помещается макрос и простенькая форма, в action указывается текущая страница.
Пример:
<form method="get" action="/glavnaya">
<input type="text" name="str" value="" />
<input type="submit" value="Найти!"/>
</form>
%custom runSearch('', '38', 'artikul', '', 'default')%
Потом откройте файл шаблон /tpls/search/default.tpl и добавьте в него следующие блоки:
$FORMS['items'] = <<<END
<table>
<tr>
По запросу "%request%" найдено %total%:
</tr>
%items%
</table>
END;
$FORMS['item'] = <<<END
<tr>
<td>
Артикул: %artikul%
</td>
<td>
Товар: <a href="%link%">%name%</a>
</td>
</tr>
END;
$FORMS['empty'] = <<<END
<p>По Вашему запросу "%request%" ничего не найдено.</p>
END;