Как сделать поиск товаров по определенному полю — различия между версиями

Материал из Umicms
Перейти к:навигация, поиск
 
(не показано 11 промежуточных версий этого же участника)
Строка 3: Строка 3:
 
== Задача ==
 
== Задача ==
  
Если Вы столкнулись с данной задачей, то решить её стандартными средствами нельзя. Это можно сделать с помощью кастомного макроса, но поисковая модель UMI.CMS тоже не имеет такой возможности, поэтому нужно получать результат от поисковой модели и проверять наличие поисковой фразы прямо в нем, а отфильтрованный результат уже отдавать. Пример того, как это можно сделать дан ниже.
+
Если Вы столкнулись с данной задачей, то решить её стандартными средствами нельзя. Это можно сделать с помощью кастомного макроса, но поисковая модель UMI.CMS тоже не имеет такой возможности, поэтому нужно получать результат от поисковой модели и проверять наличие поисковой фразы прямо в нем, а отфильтрованный результат уже отдавать. Пример того, как это можно сделать дан ниже. Сразу нужно оговориться, поиск по конкретному полю в каталоге можно реализовать с помощью макроса %catalog search%, в данной же статье рассматривается поиск именно через поисковую модель, то есть он аналогичен %search search_do%. Необходимость его применения заключается в том, что поиск через поисковую модель работает намного быстрее, чем через %catalog search%, особенно это актуально для сайтов с большим объемом данных.
  
 
== Решение ==
 
== Решение ==
Строка 9: Строка 9:
 
%custom runSearch()% — выводит перечень страниц, у которых в указанном поле содержится поисковая фраза.
 
%custom runSearch()% — выводит перечень страниц, у которых в указанном поле содержится поисковая фраза.
  
'''Параметры: custom runSearch($str, [$field = 'h1', $parent_id, $h_type_id, $template = 'default'])'''
+
'''Параметры: 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'''
 
   Если указан, то поиск будет производится только в указанном разделе сайта. Если не указан, то - по всем разделам.
 
   Если указан, то поиск будет производится только в указанном разделе сайта. Если не указан, то - по всем разделам.
'''$h_type_id'''
 
  Если указан, то поиск будет производится только среди страницы с указанным иерархическим типом. Если не указан, то - по всем типам.
 
 
'''$template '''
 
'''$template '''
 
   Шаблон, по которому выводится результат макроса. В XSLT-шаблонизаторе игнорируется. По-умолчанию равен 'default'.
 
   Шаблон, по которому выводится результат макроса. В XSLT-шаблонизаторе игнорируется. По-умолчанию равен 'default'.
Строка 25: Строка 25:
  
 
<source lang="php">
 
<source lang="php">
public function runSearch($str, $field = 'h1', $parent_id, $h_type_id, $template = 'default'){
+
public function runSearch($str, $h_type_id, $field = 'h1', $parent_id, $template = 'default'){
+
 
if (!$str) $str = (string) getRequest('str');
+
if (!$str) $str = (string) getRequest('str');
+
$str = urldecode($str);
$str = urldecode($str);
+
$str = htmlspecialchars($str);
$str = htmlspecialchars($str);
+
$str = str_replace(". ", " ", $str);
$str = str_replace(". ", " ", $str);
+
$str = trim($str, " \t\r\n%");
$str = trim($str, " \t\r\n%");
+
$str = str_replace(array('"', "'"), "", $str);
$str = str_replace(array('"', "'"), "", $str);
+
 
+
if (!$str) return;
if (!$str) return;
+
 
+
$h_type_id = intval($h_type_id);
$h_type_id = intval($h_type_id);
+
$parent_id = intval($parent_id);
$parent_id = intval($parent_id);
+
$hierarchy = umiHierarchy::getInstance();
+
$search =  searchModel::getInstance();
$hierarchy = umiHierarchy::getInstance();
+
$h_types_col = umiHierarchyTypesCollection::getInstance();
$search =  searchModel::getInstance();
+
$o_types_col = umiObjectTypesCollection::getInstance();
$h_types_col = umiHierarchyTypesCollection::getInstance();
+
$fields = umiFieldsCollection::getInstance();
$o_types_col = umiObjectTypesCollection::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)){
 
$test++;
 
break;
 
}
 
}
 
 
if($test == 0){
 
$field = 'h1';
 
}
 
}
 
 
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) = def_module::loadTemplates('search/' . $template, 'items', 'item');
 
  
$item = array();
+
if($h_type_id == 0 || !$h_types_col->isExists($h_type_id)){
$items = array();
+
$h_type_id = false;
$count = 0;
+
$field = 'h1';
foreach($products_ids as $product_id){
+
}else{
if(stripos($hierarchy->getElement($product_id)->getValue($field), $str) !== false){
+
$o_types_arr = $o_types_col->getTypesByHierarchyTypeId($h_type_id);
$item['attribute:id'] = $hierarchy->getElement($product_id)->id;
+
$test = 0;
$item['attribute:link'] = $hierarchy->getElement($product_id)->link;
+
foreach($o_types_arr as $key=>$value){
$item['attribute:name'] =  $hierarchy->getElement($product_id)->getName();
+
$o_type = $o_types_col->getType($key);
$item["attribute:$field"] =  $hierarchy->getElement($product_id)->getValue($field);
+
if($o_type->getFieldId($field)){
$count++;
+
$field_id = $o_type->getFieldId($field);
$items[] = def_module::parseTemplate($item_template, $item);
+
$field_object = $fields->getField($field_id);
 +
if($field_object->getIsInSearch()){
 +
$test++;
 +
break;
 
}
 
}
 
}
 
}
$items = array('subnodes:items' => $items);
+
}
$items['total'] = $count;
+
if($test == 0){
return def_module::parseTemplate($items_template, $items);
+
$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;