В CRM/ERP-системах, которые мы разрабатываем под заказ, всегда используется чудесный компонент DataTables. Очень удобный процессор табличных данных, поиск, фильтр, гибкость — это всё про него. Мы его любим.
Базовое использование данного плагина подразумевает обработку имеющейся таблицы <table> или подгрузку JSON-массива. Проблемы начинаются, когда таблица имеет большое количество строк, а наши CRM-системы очень часто содержат таблицы данных от 1000 строк и выше.
В этих случаях разработчики DataTables рекомендуют использовать серверную обработку выходных данных (т.н. Server-side Processing), которая предусматривает проведение операций выборки, фильтра и сортировки на стороне сервера, и возвращает на страницу уже сформированный контент удобными порциями. В результате всё работает шустро, браузер не виснет. Подробное описание данного приёма, с примерами реализации и массой других фишек, находится здесь.
Приведённый выше пример ссылается на созданный разработчиками DataTables PHP-класс ssp.class.php (найти его можно здесь). Если внимательно посмотреть на примеры его использования, можно понять, что он не подойдёт для минимально сложных SQL-выборок из базы данных. Вы не сможете, например, использовать JOIN — и как теперь выбирать необходимые данные? Ещё одним недостатком данного класса, по крайней мере для нас, является то, что он самостоятельно подключается к БД — мы же работаем через другой класс.
Для того, чтобы комфортно работать с большими таблицами, мы будем руками писать собственные модификаторы запросов. Рассмотрим пример крупной клиентской базы в CRM: вытягиваем информацию о всех «активных» клиентах, их название и УНП, а также данные договора с ними. Разумеется, это простой пример.
По этой ссылке вы найдёте, как включить серверную обработку на стороне HTML/JS, а вот PHP-код придётся писать самим. Здесь под заголовком Sent parameters вы найдёте полный список тех данных запроса, которые DataTables посылает в ваш PHP-скрипт в $_REQUEST. Следовательно:
Разумеется, входные данные необходимо обрабатывать на предмет зловредного контента, тут вы и сами справитесь.
Мы уже видим определённые знакомые вещи, которые будут использоваться как LIMIT, OFFSET, ORDER… А для того, чтобы обработать строку поиска, напишем такую функцию (она пригодится в дальнейшем):
Эта функция, как мы видим, принимает массив наших столбцов, и если для него установлено значение searchable: true — добавляет его в строку SQL-запроса. Я также добавил сюда параметр extra_columns на тот случай, если поиск нужен по какому-нибудь иному полю, которое не имеет отдельного столбца. Обратите внимание, что выходная строка предполагает наличие хотя бы одного условия в вашем WHERE — в противном случае её потребуется немного изменить.
Используем функцию для включения в поиск ещё и поля УНП:
И вот как теперь выглядит наша строка SQL-запроса:
Предельно просто, не правда ли?
Теперь мы должны передать в DataTables значения recordsTotal (сколько всего строк в базе данных) и recordsFiltered (сколько строк мы возвращаем). Эти данные нужны для формирования пагинации и строки «Показываем с 1 по 10 из 57 записей». Мы не можем подсчитать количество возвращённых предыдущим запросом строк, потому что используется LIMIT — поэтому нам придётся сделать ещё два SQL-запроса (или один, если $search_clause пустой):
Теперь формируем выходные данные, тут всё просто:
Как видим, такой подход никоим образом не ограничивает вас в сложности вашего SQL-запроса и методах подключения к БД. Конечно же, эти приёмы можно просто переписать для работы с другими СУБД.