Введение
На мой взгляд, 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. (Внимательно читайте комментарии, скрипт будет работать, только если вы настроете подключение к БД и впишите вместо моего обращение к модулю свой запроса к БД).
