Введение
На мой взгляд, jqGrid — самый успешный и удобный на данный момент плагин для jQuery, работающий с таблицами БД через AJAX запросы и PHP (Так же существует версия для ASP.NET).
Все подробности в данной статье я опущу, акцентируя ваше внимание лишь на вопросе, как сделать сложный поиск по таблице, используя этот плагин.
Для начала советую познакомиться:
- с самим плагином вот тут;
- с примерами его работы вот здесь;
- со статьей «Введение в jqGrid», в которой описано как связать jqGrid + php + Mysql (или иные БД).
Как получить данные БЕЗ условия «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):
- $_REQUEST['_search'] — Булево значение, если запрос с условием поиска оно принимает истинное значение;
- $_REQUEST['filters'] — Объект с условиями в представлении json;
- $_REQUEST['searchField'] — Имя поля для поиска (если условие простое);
- $_REQUEST['searchOper'] — Операция сравнения поля для поиска (если условие простое);
- $_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-поиске jqGrid будет передавать в параметрах запроса имена колонок и их значения.
echo $_POST['id']; // Выведет 3, если пользователь ввел в строку поиска под колонкой id цифру 3
Таким образом для реализации inline-поиска по `id` достаточно написать такой код:
$where = "`id` = " . (int)$_POST['id'];
Для поиска по нескольким полям к условию соответственно будут добавляться дополнительные строки, соединенные между собой «AND». Естественно вместо равенства можно использовать любой условие, позволительное для вашей БД.
Исходник файла-обработчика запросов AJAX от jqGrid. (Внимательно читайте комментарии, скрипт будет работать, только если вы настроете подключение к БД и впишите вместо моего обращение к модулю свой запроса к БД).