Wiki
Clone wikiSimpleDatabaseAdapter / Документация по SDBA на русском языке
Simple Database Adapter (SDBA)
Для русскоговорящих
По сути это ещё один велосипед с реализацией упрощённого обращения к базе данных под управлением СУБД MySQL,
берущий часть повторяющейся рутины на себя. Под капотом активно использует MySQLi и только его (не «мост» всё-таки).
Представляет собой набор статических методов. Да, создавать объект не нужно! Откуда берутся параметры?
В корне сайта ожидается файл env.cfg
(про него чуть позже), но можете изменить это поведение,
модифицировав метод Start()
.
Сам файл env.cfg
представляет собой простой исполняемый PHP-файл, возвращающий массив. Важно запретить веб-серверу
прямые обращения к этому файлу извне! SDBA считывает ключ db
у этого массива. Его значение опять же должен быть массив,
состоящий из следующих полей: host
, login
, password
, database
и timezone
. Думаю, названия параметров говорят
сами за себя. Рядом с этим файлом помощи также должен находиться env.cfg.example
, который Вы можете взять за основу.
Прежде чем перейти к рассмотрению конкретных функций, сразу хотелось бы оговорить, что в случае возникающих ошибок
все они бросают стандартное исключение mysqli_sql_exception
.
Теперь перейдём к рассмотрению основных функций класса.
Выборка данных
Здесь рассмотрим один, но весьма обширный метод:
Select($columns, $table, array $filter=null, $sorting=null, $limit=null, $unique=false)
.
Принимает он целых 6 параметров, 2 из которых обязательны! Давайте рассмотрим их все:
$columns
— определяет, какие поля мы будем получать из базы данных. Может быть как строкой из названия одного поля, так и массивом строк.$table
— определяет название таблицы, откуда будем брать данные. Просто строка.$filter
— здесь нужно описывать условия фильтрации результатов выборки. Может быть либо массивом, либо null (по умолчанию). Структура массива не так проста, так что рассмотрим её чуть позже.$sorting
— задаёт сортировку результата. Может быть строкой (тогда будет отсортировано по указанному полю в порядке возрастания) либо массивом строк (ну или null, как по умолчанию). При этом каждая строка может быть ключом. Если ключу присваивается значениеSDBA::DESC_ORDER
(по сути, это просто true), то сортировка будет выполнена в порядке убывания. Позже рассмотрим это на примере.$limit
— если не null (по умолчанию), то либо число, обозначающее максимальное число строк, которые надо вернуть, либо массив из этого числа и смещения выборки относительно её начала.$unique
— булево значение. Если true, то все строки будут уникальны. Если false (по умолчанию), то могут встречаться повторы.
Теперь вернёмся к параметру $filter
. Самый простой вариант, когда в массиве передаются пары ключ-значение.
В таком случае ключ — название поля, и выборка вернёт все строки, где поле содержит указанное значение. То есть
проверяется их равенство.
Но ведь есть и другие операции сравнения? Да, есть. Чтобы их использовать, в массив нужно передать строку со знаком
требуемой операции перед операндами, которые её используют. Непонятно? Сейчас перейдём к примерам, и я всё наглядно покажу.
Но сначала перечислю все возможные операции сравнения: =
(задан изначально), <>
и !=
, <=
, <
, >=
, >
, <=>
.
Итак, пример:
<?php // Получаем имена всех пользователей. $users = SDBA::Select("name", "users"); // А теперь только первого, используя фильтрацию по идентификатору. $user1 = SDBA::Select("name", "users", ['id' => 1]); // Берём первую десятку, указывая сортировку по столбцу `id` и ограничивая выборку 10-ю записями. $users1_10 = SDBA::Select("name", "users", null, "id", 10); // А теперь возьмём вторую десятку, указав ещё и смещение. $users10_20 = SDBA::Select("name", "users", null, "id", [10, 10]); // Отсортируем их в обратном порядке и получим последнюю десятку. $lastUsers = SDBA::Select("name", "users", null, ['id' => SDBA::DESC_ORDER], 10); // Вернём список дат регистрации без повторений. $uniqueUsers = SDBA::Select("registration_date", "users", null, null, null, true); // Заключительный и самый сложный пример: получаем идентификатор, имя и дату регистрации пользователей, // которые зарегистрировались не больше, чем месяц назад, отсортировав их от самого последнего // зарегистрировавшегося до самого "старого". В случае одинаковой даты, отсортировать по имени // в алфавитном порядке. $newUsers = SDBA::Select( ['id', 'name', 'registration_date'], "users", [ '>=', 'registration_date' => date("Y-m-j H:i:s", time() - 2592000) ], [ 'registration_date' => SDBA::DESC_ORDER, 'name' ] ); // Теперь можем по очереди получить все записи, используя стандартные методы MySQLi. $userList = []; while ($userList[] = $newUsers->fetch_assoc());
Модификация данных
Для внесения и изменения данных есть 5 методов.
Вставка новых записей
Для внесения данных в базу есть метод Insert($table, array $data)
.
Он принимает следующие параметры:
$table
— название таблицы, куда будут добавляться данные.$data
— именованный массив, где ключи представляют собой названия полей, а значения — вносимые данные.
Достаточно просто, не так ли? Я не стал делать поддержку добавления анонимных значений, чтоб код был максимально наглядным.
<?php SDBA::Insert("users", [ 'name' => 'Леонид Козарин', 'email' => 'kozalo@nekochan.ru' ]);
Изменение данных
Для модификации значений в базе данных используйте метод Update($table, array $changes, array $filter=null)
.
Он принимает следующие параметры:
$table
— название таблицы, которую таблицу будем изменять.$changes
— массив, где ключи — названия изменяемых полей, а значения — новые значения для них.$filter
(необязательный параметр) — если не null, то содержит массив-фильтр, определяющий, какие записи подвергнутся изменениям. Подробно он был рассмотрен выше в разделе про выборку данных.
<?php // Изменяем первого пользователя, чтобы им был аккаунт администратора. SDBA::Update("users", [ 'name' => 'Admin', 'email' => 'admin@nekochan.ru' ], [ 'id' => 1 ]);
Удаление данных
Для удаления записей предусмотрен метод Delete($table, array $filter=null)
.
Он принимает следующие параметры:
$table
— название таблицы, откуда будем удалять данные.$filter
(необязательный параметр) — если не null, то содержит массив-фильтр, определяющий, какие записи будут удалены. Подробно он был рассмотрен выше в разделе про выборку данных.
<?php // Похулиганим и удалим всех пользователей, кроме самого первого. SDBA::Delete("users", [ '>', 'id' => 1 ]);
Копирование данных
Для копирования строк из одной таблицы другую (но с такой же структурой!) есть метод Copy($source, $destination, array $filter=null)
.
Он принимает следующие параметры:
$source
— название таблицы, откуда будем брать данные.$destination
— название таблицы, куда будем копировать данные.$filter
(необязательный параметр) — если не null, то содержит массив-фильтр, определяющий, какие записи будут скопированы. Подробно он был рассмотрен выше в разделе про выборку данных.
<?php // Работать будем с первыми 10-ю пользователями. $filter = [ '<=', 'id' => 10 ]; // Скопируем их в VIP-таблицу. SDBA::Copy("users", "vip_users", $filter); // А теперь удалим из таблицы для простолюдинов. SDBA::Delete("users", $filter);
Перенос данных
Для перемещения записей между двумя таблицами с одинаковой структурой есть метод Move($source, $destination, array $filter=null)
.
Он принимает следующие параметры:
$source
— название таблицы, откуда будем удалять данные.$destination
— название таблицы, куда будем переносить данные.$filter
(необязательный параметр) — если не null, то содержит массив-фильтр, определяющий, какие записи будут перенесены. Подробно он был рассмотрен выше в разделе про выборку данных.
<?php // Перенесём первые 10 пользователей в VIP-таблицу. SDBA::Move("users", "vip_users", [ '<=', 'id' => 10 ]); // И теперь не нужно никого удалять, как в предыдущем примере!
Выполнение сложных запросов
Я бы настоятельно рекомендовал вместо сложных запросов в клиентском коде по возможности создавать на стороне базы данных триггеры и представления. Однако, если это представляется затруднительным, библиотека позволяет Вам использовать подготовленные запросы, что минифицирует возможность ввода некорректных данных и SQL-инъекций.
Самый простой способ выполнить SQL-запрос — это использовать метод CustomQuery($query, $typesMask=null, $values=null)
.
Параметры у него следующие:
$query
— любой корректный MySQL-запрос, в котором все вхождения конкретных данных заменены вопросительными знаками (см. пример ниже).$typesMask
— может быть равен null только в том случае, если в запросе нет никаких данных! Иначе должен быть строкой с количеством символов, равным количеству значений в следующем параметре (и количеству вопросительных знаков в запросе). Каждый символ представляет собой ожидаемый тип параметра:i
— целое число,d
- число с плавающей точкой,s
- строка. Если не очень понятно, то ниже будет пример.$values
— аналогично предыдущему может быть равен null только в том случае, если в запросе нет никаких данных! Представляет собой либо одинокое значение, подставляемое в запрос, либо массив таких значений в соответствии с указанными предыдущим параметром типами.
<?php // Да, я не придумал ничего лучше простого запроса на изменение данных. SDBA::CustomQuery( "UPDATE `users` SET `name`=?, `email`=? WHERE `id`=?", "ssi", ['Admin', 'admin@nekochan.ru', 1] );
Больше о подготовленных запросах
Под капотом CustomQuery()
использует два других метода: PrepareQuery($query, $typesMask=null, &$bindings=null)
и ExecutePreparedQuery()
. Параметры первого очень похожи на параметры уже рассмотренного нами метода. Но что за
привязки (bindings)?
Смысл наличия этих открытых методов и вообще подобная организация подготовленных выражений в MySQLi заключается в том,
чтоб для различного набора данных можно было скомпилировать запрос только один раз, а затем лишь менять значения переменных
и выполнять его. Поэтому при подготовке запроса с данными Вы должны передать третьим параметром в PrepareQuery()
переменную, значение которой будете потом менять перед каждым последующим вызовом ExecutePreparedQuery()
.
Кроме одиночной переменной, разумеется, можно передать и массив таких переменных.
Таким образом, CustomQuery()
используется в тех довольно частых случаях, когда нужно выполнить лишь одиночный запрос.
Он использует преимущество подготовленных запросов в защите от SQL-инъекций, но не реализует весь их потенциал.
Ну а пара методов PrepareQuery()
и ExecutePreparedQuery()
используются, когда надо выполнить множество однотипных
запросов, но с разными данными.
Транзакции
Класс содержит два простых метода без параметров для управления транзакцией: StartTransaction()
, чтобы обозначить её
начало, и Commit()
, чтобы сохранить внесённые изменения в базе данных.
Если между началом транзакции и её сохранением произойдёт какая-нибудь ошибка, вся транзакция будет отменена, сохраняя
все ваши данные в прошлом, целостном, состоянии.
Вспомогательные методы
Здесь я собрал 3 оставшихся метода, не относящихся ни к одной из предыдущих категорий.
ChangeTimezone($offset)
— смещает часовой пояс на указанное количество часов.GetLastInsertedId()
— очень полезный метод, возвращающий последний автоматически сгенерированный идентификатор. При использовании механизма транзакций его следует вызывать до сохранения изменений в БД!GetLastQuery()
— просто наиполезнейший метод при отладке и выявлении ошибок! Возвращает итоговый SQL-запрос, который был отправлен к базе данных.AffectedRows()
(начиная с v1.1.0) — возвращает количество строк, которое было затронуто предыдущим запросом.
Автор: Леонид Козарин (kozalo@yandex.ru)
© Kozalo.Ru, 2017
Updated