Класс для безопасной и удобной работы с MySQL
ВступлениеБезопасность
Удобство
Простота и универсальность
Комментарии (253)
Переход с функций mysql_*
Пример CRUD-приложения
Примеры использования
Вопросы и ответы
Вступление
Данный класс создавался для реализации следующих основополагающих принципов:
К сожалению, встроенные в PHP библиотеки обеспечивают недостаточную безопасность и не дают вообще никакого удобства, заставляя писать один и тот же код сотни раз.
Различные самописные библиотеки не обеспечивают либо должной безопасности, либо удобства, либо являются монстрообразными компонентами толстых фреймворков, требующими многодневного изучения.
Поэтому я и решил написать простой класс, обеспечивающий необходимую функциональность, который можно и нужно использовать для замены классических mysql_query/mysql_fetch_array.
Код доступен на Гитхабе: http://github.com/colshrapnel/safemysql/blob/master/safemysql.class.php
Главными отличиями от существующих библиотек являются
Эти два отличия обеспечивают гарантированную безопасность в сочетании с невиданной гибкостью.
Основной принцип работы таков:
Большая часть операций выполняется в одну строчку. В боле сложных случаях всё делается по-старинке - запрос собирается вручную, НО - с использованием гарантированно безопасных плейсхолодеров.
Безопасность
Безопасность достигается за счёт соблюдения двух основных правил:
На данный момент библиотека поддерживает 6 плейсхолдеров. Это:
- ?s ("string") - строки (а также DATE, FLOAT и DECIMAL).
- ?i ("integer") - целые числа.
- ?n ("name") - имена полей и таблиц
- ?p ("parsed") - для вставки уже обработанных частей запроса
- ?a ("array") - набор значений для IN (строка вида
'a','b','c'
)- ?u ("update") - набор значений для SET (строка вида
`field`='value',`field`='value'
)Первый служит для добавления строк, а так же всех типов данных, приравненных к ним. Второй - целых чисел.
Третий - идентификаторый - служит для динамической вставки в запрос имен полей и таблиц.
Он требуется потому, что правила форматирования идентификаторов отличаются от правил форматирования строк. Ограничивается он не одинарной кавычкой, а обратным апострофом, а экранируется не слешем, а удвоением.
Назначение четвёртого - подставлять в запрос уже обработанные части запроса.
Последние два введены для удобства. Очень часто бывает нужно подставить массив в оператор IN(). Классическими средствами это сделать затруднительно, а с помощью плейсхолдера - не сложнее, чем строку.
Наличие плейсхолдера
?u
позволяет избавиться от выделенных методов insert() и update(), сделав запросы более гибкими.При необходимости набор плейсхолдеров может быть легко расширен.
Единственный случай, не охватываемый плейсхолдерами - это SQL операторы, такие, как AND, DESC и любые другие.
В случае, если они добавляются в запрос динамически, то их надо помещать в запрос только из белого списка, заранее прописанного в скрипте.
Следует учесть, что идентификаторы тоже желательно добавлять из белого списка, во всяком случае, при поступлении данных от пользователя, поскольку ему может быть запрещён доступ к определенным полям таблицы.
Для такой фильтрации служат методы filterArray() и whiteList()
filterArray()
выбрасывает из переданного первым параметром массива все элементы, которых нет во втором массиве. Используется для фильтрации массивов, передаваемых для плейсхолдера ?uwhiteList()
просто проверяет переданный параметр на наличие в списке разрешённых значенийподробнее их использование будет показано на примерах
Удобство
Удобство достигается за счёт следующих факторов:
Хелпер - функция, берущая на себя всю рутинную работу по обработке запроса, и сразу возвращающая нужный результат. В сочетании с плейсхолдерами позволяет сокращать код в 3-5 раз!
Пример: допустим, нам надо получить информацию о пользователе по имени, полученного из GET запроса.
Классический код будет таким:
$name = mysql_real_escape_string($_GET['name']);
$result = mysql_query("SELECT * FROM users where name='$name'");
$user = mysql_fetch_array($result);
Как это делается с помощью функции-хелпера? В одну строчку!
$user = $db->getRow("SELECT * FROM users where name=?s",$_GET['name']);
причём чем сложнее наш запрос, то больше выгода.
Полный список функций приведён ниже. В основном они различаются типом возвращаемого результата.
- query($query,$param1,$param2, ...) - возвращает mysqli resource. аналог mysqli_query
- getOne($query,$param1,$param2, ...) - возвращает скаляр, первый элемент первой строки результата
- getRow($query,$param1,$param2, ...) - одномерный массив, первую строку результата
- getCol($query,$param1,$param2, ...) - одномерный массив скаляров - колонку таблицы.
- getAll($query,$param1,$param2, ...) - двумерный массив, индексированный числами по порядку
- getInd($key,$query,$par1,$par2, ...) - двумерный массив, индексированный значениями поля, указанного первым параметром
- getIndCol($key,$query,$par1,$par2, ...) - массив скаляров, индексированный полем из первого параметра. Незаменимо для составления словарей вида key => value
Как видно, имена функций напоминают таковые из PEAR::DB, но не во всём совпадают с ними.
В первую очередь, сокращено их количество, поскольку поддержка плейсхолдеров сделала многие искусственные функции (типа limitQuery() или INSERT) попросту ненужными, а синтаксис запросов - более естественным и в тоже время - гибким.
Также удобство обеспечивается умным обработчиком ошибок, который всегда укажет конкретное место, в коде, в котором произошла ошибка.
Простота и универсальность
Достигаются за счёт того, что с использованием всего лишь трёх элементов - набора плейсхолдеров, набора хелперов, и функции parse() можно решать неограниченный набор задач, не перегружая класс десятками дополнительных функций и параметров.
Написать комментарий
Пожалуйста, воздержитесь от посылки спама.
Сообщения, содержащие гиперссылки, проходят премодерацию.