Как стать автором
Обновить

jqGrid — Динамические таблицы на jQuery. Сложный Поиск

Время на прочтение6 мин
Количество просмотров85K

Введение


На мой взгляд, jqGrid — самый успешный и удобный на данный момент плагин для jQuery, работающий с таблицами БД через AJAX запросы и PHP (Так же существует версия для ASP.NET).

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

Для начала советую познакомиться:
Как получить данные БЕЗ условия «where» в этой статье описываться не будет. Предполагается, что вы прочли статью «Введение в jqGrid» и хотите теперь не просто сортировать результаты и разбивать их на страницы, а делать сложные поиски сразу по нескольким полям таблицы.

Прошу обратить особое внимание на пример, расположенный по ссылке выше, под названием «Searching (4.0) new» -> «Show query in search ».

И так, мы создали документ HTML:

<table id="newapi"></table>
<div id="pnewapi"></div>

Подключили JavaScript код:
jQuery("#grps1").jqGrid({ // Привязка плагина к таблице
   	url:'ajax/get.php', // Скрипт - обработчик ваших запросов
	datatype: "json", // Формат скрипта-обработчика
   	colNames:['Inv No', 'Date', 'Client', 'Amount','Tax','Total','Notes'],
   	colModel:[
   		{name:'id',	key : true,	index:'id',	width:55, searchtype:"integer"},
   		{name:'invdate',index:'invdate', width:90},
   		{name:'name', index:'name',	width:100},
   		{name:'amount',index:'amount', width:80, align:"right", searchtype:"number"},
   		{name:'tax',index:'tax', width:80, align:"right", searchtype:"number"},
   		{name:'total',index:'total', width:80,align:"right", searchtype:"number"},
   		{name:'note',index:'note', width:150, sortable:false}
   	],
   	rowNum:10,
   	width:700,
   	rowList:[10,20,30],
   	pager: '#pgrps1', // Привязка к таблице тулбара
   	sortname: 'invdate',
   	viewrecords: true,
   	sortorder: "desc"
});

jQuery("#grps1").jqGrid('navGrid','#pgrps1',  // Управление тулбаром таблицы
	{edit:false,add:false,del:false}, // Отключаем от тулбара редактирование, добавление и удаление записей. На тулбаре останутся только две кнопки: "Поиск" и "Обновить"
	{}, // Опции окон редактирования
	{}, // Опции окон добавления
	{}, // Опции окон удаления
	{
		multipleSearch:true, // Поиск по нескольким полям
		multipleGroup:true, // Сложный поиск с подгруппами условий
		showQuery: true // Показывать превью условия
	}
);

Подключили необходимые стили и скрипты (скачать можно тут):
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css"/>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>

<link rel="stylesheet" type="text/css" href="css/ui.jqgrid.css"/>
<script type="text/javascript" src="src/grid.loader.js"></script>

Обратите внимание, что я не подключаю библиотеку одним файлом или отдельными частями, как это можно было сделать, а использую файл «grid.loader.js», который также поставляется с исходниками на оффициальном сайте плагина. Я его немного изменил и привожу измененный отрывок кода:
...
    var pathtojsfiles = "src/";
    // set include to false if you do not want some modules to be included
    var modules = [
        { include: true, incfile:'i18n/grid.locale-ru.js'}, // Вот тут я изменил локаль на 'ru'
...

Используя этот файл удобно управлять компонентами этого модуля, а также выбирать его язык.

Расширенный поиск


Форма расширенного поиска:
Форма расширенного поиск

Теперь самое сладкое. Что же нам передает jqGrid при поиске?
POST или GET параметры (в зависимости от настроек jqGrid):
  1. $_REQUEST['_search'] — Булево значение, если запрос с условием поиска оно принимает истинное значение;
  2. $_REQUEST['filters'] — Объект с условиями в представлении json;
  3. $_REQUEST['searchField'] — Имя поля для поиска (если условие простое);
  4. $_REQUEST['searchOper'] — Операция сравнения поля для поиска (если условие простое);
  5. $_REQUEST['searchString'] — Значение поля для поиска (если условие простое);

Теперь зная эти данные, необходимо сгенерировать строку условий «where» и передать ее необходимой процедуре, которая раннее принимала только имя сортируемой колонки, направление сортировки, номер страницы и количество записей на одну страницу (для пагинации).

Вот код, который необходимо вставить перед запросом в БД (в примере используется POST-запрос):

if($_search){
	if (isset($_POST['filters'])) $filters = $_POST['filters'];// Фильтры для поиска
	if (isset($_POST['searchField'])) $searchField = $_POST['searchField']; // Фильтр по одному полю (имя)
	if (isset($_POST['searchOper'])) $searchOper = $_POST['searchOper']; // Фильтр по одному полю (операция)
	if (isset($_POST['searchString'])) $searchString = $_POST['searchString']; // Фильтр по одному полю (значение)
	
	$searchString = generateSearchString($filters, $searchField, $searchOper, $searchString);
}

Вот «сердце» данной статьи, функции генерации условия для поиска в БД.

Функция generateSearchString():
function generateSearchString($filters, $searchField, $searchOper, $searchString){
		$where = '';
	if($filters){
		$filters = json_decode($filters);
		$where .= self::generateSearchStringFromObj($filters);
	}
	
	return $where;
}

Рекурсивная функция generateSearchStringFromObj() генерации условий для выборки из БД:
	function generateSearchStringFromObj($filters){
	$where = '';
		
	// Генерация условий группы фильтров
	if(count($filters)) foreach($filters->rules as $index => $rule){
		$rule->data = addslashes($rule->data);
		
	$where .= "`".preg_replace('/-|\'|\"/', '', $rule->field)."`";
	switch($rule->op){ // В будущем будет больше вариантов для всех вохможных условий jqGrid
		case 'eq': $where .= " = '".$rule->data."'"; break;
		case 'ne': $where .= " != '".$rule->data."'"; break;
		case 'bw': $where .= " LIKE '".$rule->data."%'"; break;
		case 'bn': $where .= " NOT LIKE '".$rule->data."%'"; break;
		case 'ew': $where .= " LIKE '%".$rule->data."'"; break;
		case 'en': $where .= " NOT LIKE '%".$rule->data."'"; break;
		case 'cn': $where .= " LIKE '%".$rule->data."%'"; break;
		case 'nc': $where .= " NOT LIKE '%".$rule->data."%'"; break;
		case 'nu': $where .= " IS NULL"; break;
		case 'nn': $where .= " IS NOT NULL"; break;
		case 'in': $where .= " IN ('".str_replace(",", "','", $rule->data)."')"; break;
		case 'ni': $where .= " NOT IN ('".str_replace(",", "','", $rule->data)."')"; break;
	}
		
	// Добавить логику соединения, если это не последние условие
	if(count($filters->rules) != ($index + 1))
		$where .= " ".addslashes($filters->groupOp)." ";
	}
		
	// Генерация условий подгруппы фильтров
	$isSubGroup = false;	
	if(isset($filters->groups))
		foreach($filters->groups as $groupFilters){
			$groupWhere = self::generateSearchStringFromObj($groupFilters);	
			// Если подгруппа фильтров содержит условия, то добавить их
			if($groupWhere){
				// Добавить логику соединения, если условия подгруппы фильтров добавляются после условий фильтров этой группы
				// или после условий других подгрупп фильтров
				if(count($filters->rules) or $isSubGroup) $where .= " ".addslashes($filters->groupOp)." ";
				$where .= $groupWhere;
				$isSubGroup = true; // Флаг, определяющий, что было хоть одно условие подгрупп фильтров	
			}
		}
		
	if($where)
		return '('.$where.')';
		
	return ''; // Условий нет
}

P.S.

Форма inline-поиска:
Форма inline-поиска

ВНИМАНИЕ: данная формула не будет работать при inline-поиске. При inline-поиске jqGrid будет передавать в параметрах запроса имена колонок и их значения.

echo $_POST['id']; // Выведет 3, если пользователь ввел в строку поиска под колонкой id цифру 3

Таким образом для реализации inline-поиска по `id` достаточно написать такой код:

$where = "`id` = " . (int)$_POST['id'];

Для поиска по нескольким полям к условию соответственно будут добавляться дополнительные строки, соединенные между собой «AND». Естественно вместо равенства можно использовать любой условие, позволительное для вашей БД.

Исходник файла-обработчика запросов AJAX от jqGrid. (Внимательно читайте комментарии, скрипт будет работать, только если вы настроете подключение к БД и впишите вместо моего обращение к модулю свой запроса к БД).
Теги:
Хабы:
Всего голосов 49: ↑45 и ↓4+41
Комментарии48

Публикации