Беседа ВК (Помощь) | Беседа ВК (Лог обновлений) |
---|
- Универсальность — Благодаря тому, что DataBase наследуется от
PHP-PDO
, её можно использовать с различными БД. - Простота — DataBase включает в себя удобные заполнители, которы серьёзно упрощают работу с SQL запросами. Также частые SQL запросы уже составлены и вынесены в виде методов.
- При использовании Заполнителей, вы полностью защищены от
SQL инъекций
.
В библиотеке поддерживается:
- Все методы PHP-PDO
- Свои заполнители
- ORM конструкции
- Подключение
- Заполнители
- Настройка PhpStorm
- Хандлер sql запросов
- Типы заполнителей
- Дополнительные методы
- getQueryString
- execCommit
- rows($sql, $args = [], $fetchMode = PDO::FETCH_ASSOC)
- row($sql, $args = [], $fetchMode = PDO::FETCH_ASSOC)
- getById($table, $id, $fetchMode = PDO::FETCH_ASSOC)
- count($sql, $args = [])
- insert($table, $data)
- update($table, $data, $where = [])
- delete($table, $where, $limit = -1)
- deleteAll($table)
- deleteById($table, $id)
- deleteByIds($table, $column, $ids)
- truncate($table)
composer require digitalstars/database
require_once "vendor/autoload.php"; //Подключаем библиотеку
- Скачать последний релиз
- Подключить
autoload.php
Вот так будет происходить подключение, если ваш бот находится в той же папке, что и папка
DataBase-master
require_once "DataBase-master/autoload.php"; //Подключаем библиотеку
Синтаксис конструктора базового класса такой же, как и у PHP-PDO
use DigitalStars\DataBase\DB;
$dsn = ''; // Имя источника данных или DSN, содержащее информацию, необходимую для подключения к базе данных.
$login = ''; // Логин
$pass = ''; // Пароль
$options = []; // Массив ключ=>значение специфичных для драйвера настроек подключения.
$db = new DB($dsn, $login, $pass, $options);
use DigitalStars\DataBase\DB;
$db_type = 'mysql'; // Это может быть mysql, sybase или любой другой, в зависимости от вашей СуБД
$db_name = 'test'; // Имя БД
$login = 'root'; // Логин
$pass = 'pass'; // Пароль
$ip = 'localhost'; // Адрес
// С портом по умолчанию
$db = new DB("$db_type:host=$ip;dbname=$db_name", $login, $pass);
// С нестандартным портом
$port = 1234;
$db = new DB("$db_type:host=$ip;port=$port;dbname=$db_name", $login, $pass);
// Подключение с выбором кодировки UTF8
$db = new DB("$db_type:host=$ip;dbname=$db_name;charset=UTF8", $login, $pass);
// Или вот так (советуем использовать этот вариант)
$db = new DB("$db_type:host=$ip;dbname=$db_name;", $login, $pass, [
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'",
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
// В этом примере, сразу после подключения выполнится SQL запрос "SET NAMES 'utf8'"
use DigitalStars\DataBase\DB;
$db_type = 'sqlite';
$db_path = 'path/to/file/test.sqlite'; // Путь к файлу с базой данных
// Подключение
$db = new DB("$db_type:$db_path");
Заполнители — специальные типизированные маркеры, которые пишутся в строке SQL запроса вместо явных значений (параметров запроса), чем упрощают читаемость кода и защищают от SQL инъекций.
Заполнители поддерживаются в следующих методах:
- exec()
- execCommit()
- query()
- prepare()
О том как работают эти методы можно посмотреть в PHP-PDO.
<?php
require 'vendor/autoload.php';
use DigitalStars\DataBase\DB;
// Соединение с СУБД SQLite и получение объекта, который включает в себя все методы PHP-PDO и библиотеки
$db = new DB("sqlite:./test.sqlite");
// Получение объекта результата PDOStatement
$result = $db->query("SELECT * FROM users WHERE name = ?s AND age = ?i", ["Василий", 30]);
// Получаем данные (в виде ассоциативного массива)
$data = $result->fetch();
// Не работает запрос? Не проблема - выведите его на печать:
echo $db->getQueryString();
Параметры SQL-запроса, прошедшие через заполнители, обрабатываются специальными функциями экранирования, в зависимости от типа заполнителей. Т.е. вам теперь нет необходимости заключать переменные в функции экранирования типа
quote()
или приводить их к числовому типу, как это было раньше
Типы заполнителей и их предназначение описываются ниже. Прежде чем знакомиться с типами заполнителей, необходимо понять как работает механизм библиотеки DataBase.
$db->query("SELECT ?i", [123]);
SQL-запрос после преобразования шаблона:
SELECT 123
В процессе исполнения этой команды библиотека проверяет, является ли аргумент
123
целочисленным значением. Заполнитель?i
представляет собой символ?
(знак вопроса) и первую букву словаinteger
. Если аргумент действительно представляет собой целочисленный тип данных, то в шаблоне SQL-запроса заполнитель?i
заменяется на значение123
и SQL передается на исполнение.
Поскольку PHP слаботипизированный язык, то вышеописанное выражение эквивалентно нижеописанному:
$db->query("SELECT ?i", '123');
SQL-запрос после преобразования шаблона:
SELECT 123
Т.е. числа (целые и с плавающей точкой) представленные как в своем типе, так и в виде
string
— равнозначны с точки зрения библиотеки.
$db->query("SELECT ?i", '123.7');
SQL-запрос после преобразования шаблона:
SELECT 123
В данном примере заполнитель целочисленного типа данных ожидает значение типа integer
, а передается double
.
Допускаются следующие преобразования:
- К типу
int
(заполнитель?i
) приводятся:- Числа с плавающей точкой, представленные как
string
илиdouble
bool(true)
преобразуется вint(1)
bool(false)
иnull
преобразуется вint(0)
- Числа с плавающей точкой, представленные как
- К типу
double
(заполнитель?d
) приводятся:- Целые числа, представленные как
string
илиint
bool(true)
преобразуется вfloat(1)
bool(false)
иnull
преобразуется вfloat(0)
- Целые числа, представленные как
- К типу
string
(заполнитель?s
) приводятся:numeric
преобразуется вstring
null
преобразуется вstring(0) ""
bool(true)
преобразуется вstring(1) "1"
bool(false)
преобразуется вstring(1) "0"
Это поведение отличается от приведения типа
bool
кint
в PHP, т.к. зачастую на практикеbool
записывается в MySql именно как число. - Тип
null
(заполнитель?n
) просто вставляетNULL
в место заполнителя.
Входные параметры не требуются
Для того, что-бы IDE нормально реагировала на заполнители, и не подсвечивала места с заполнителями ошибками, необходимо добавить заполнители в список пользовательских параметров.
Путь диалогового окна с настройками
File >> Settings... >> Tools >> Database >> User Parameters
Затем в окошке "Parameter patterns" нужно добавить следующие 2 шаблона и поставить обе галочки "In scripts" и "In literals":
\?[aAvw]\[.*?\]
\?[aAvw]?[sSidnf]
Окно настройки должно выглядеть следующим образом
Если вам необходимо обрабатывать все выполняемые в скрипте SQL запросы, например для дебага.
$db->setLoggerFunc(function ($query) {
$file = 'log.txt';
$query = "Время: ".date('d.m.y H:i:s')."\n".$query;
file_put_contents($file, $query, FILE_APPEND | LOCK_EX);
});
$_POST['id'] = '123456';
$db->query('SELECT * FROM `users` WHERE `id` = ?i', [$_POST['id']]);
SQL-запрос после преобразования шаблона:
SELECT * FROM `users` WHERE `id` = 123456
ВНИМАНИЕ! Если вы оперируете числами, выходящими за пределы
PHP_INT_MAX
, то:
- Оперируйте ими исключительно как строками в своих программах.
- Не используйте данный заполнитель, используйте заполнитель строки
?s
(см. ниже). Дело в том, что числа, выходящие за пределыPHP_INT_MAX
, PHP интерпретирует как числа с плавающей точкой. Парсер библиотеки постарается преобразовать параметр к типу int, в итоге:«результат будет неопределенным, так как float не имеет достаточной точности, чтобы вернуть верный результат. В этом случае не будет выведено ни предупреждения, ни даже замечания!» — php.net.
ВНИМАНИЕ! Если вы используете библиотеку для работы с типом данных
double
, установите соответствующую локаль, что бы разделитель целой и дробной части был одинаков как на уровне PHP, так и на уровне СУБД.
Значения экранируются с помощью функции PDO::quote()
$db->query('SELECT ?s, ?s, ?s, ?s, ?s', [55.5, true, false, null, 'Д"Артаньян']);
SQL-запрос после преобразования шаблона:
SELECT "55.5", "1", "0", "", "Д\"Артаньян"
Значения экранируются с помощью функции PDO::quote() + экранирование спецсимволов, используемых в операторе LIKE (%
и _
):
$db->query('SELECT "?S"', '% _');
SQL-запрос после преобразования шаблона:
SELECT "\% \_"
Заполнитель просто вставляет NULL
в запрос, входной параметр не нужен
$db->query('SELECT ?n');
SQL-запрос после преобразования шаблона:
SELECT NULL
Данный заполнитель предназначен для случаев, когда имя таблицы или поля передается в запросе через параметр. Значение обрамляется символом апостроф:
$db->query('SELECT * FROM ?f', 'table');
SQL-запрос после преобразования шаблона:
SELECT * FROM `table`
?A*
— заполнитель ассоциативного множества из ассоциативного массива, генерирующий последовательность пар ключ = значение
Пример: "key_1" = "val_1", "key_2" = "val_2", ..., "key_N" = "val_N"
Ключи экранируются заполнителем ?f
где *
после заполнителя — один из типов:
i
(заполнитель целого числа)d
(заполнитель числа с плавающей точкой)s
(заполнитель строкового типа)f
(заполнитель имени таблицы или поля)
Правила преобразования и экранирования такие же, как и для одиночных скалярных типов, описанных выше.
$db->query('UPDATE test SET ?Ai', [
['count' => 30, 'amount' => 1000, 'status' => 66]
]);
SQL-запрос после преобразования шаблона:
UPDATE test SET `count` = 30, `amount` = 1000, `status` = 66
?A[?n, ?s, ?i, ?d, ...]
— заполнитель ассоциативного множества с явным указанием типа и количества аргументов, генерирующий последовательность пар ключ = значение
Пример: "key_1" = "val_1", "key_2" => "val_2", ..., "key_N" = "val_N"
$db->query('UPDATE test SET ?A[?i, ?s, ?d]', [
['count' => 30.25, 'title' => 'Какой-то заголовок', 'amount' => '66.55']
]);
SQL-запрос после преобразования шаблона:
UPDATE test SET `count` = 30, `title` = 'Какой-то заголовок', `amount` = 66.55
?a*
— заполнитель множества из простого (или также ассоциативного) массива, генерирующий последовательность значений
Пример: "val_1", "val_2", ..., "val_N"
где * после заполнителя — один из типов:
i
(заполнитель целого числа)d
(заполнитель числа с плавающей точкой)s
(заполнитель строкового типа)f
(заполнитель имени таблицы или поля)
правила преобразования и экранирования такие же, как и для одиночных скалярных типов, описанных выше.
$db->query('INSERT INTO test (count, amount, status) VALUES (?ai)', [
[30, 1000, 66]
]);
SQL-запрос после преобразования шаблона:
INSERT INTO test (count, amount, status) VALUES (30, 1000, 66)
?a[?n, ?s, ?i, ?d, ...]
— заполнитель множества с явным указанием типа и количества аргументов, генерирующий последовательность значений
Пример: "val_1", "val_2", ..., "val_N"
$db->query('INSERT INTO test (count, title, amount) VALUES (?a[?i, ?s, ?d])', [
[30.25, 'Какой-то заголовок', '66.55']
]);
SQL-запрос после преобразования шаблона:
INSERT INTO test (count, title, amount) VALUES (30, 'Какой-то заголовок', 66.55)
?v*
— заполнитель VALUES из простого (или также ассоциативного) двумерного массива, генерирующий последовательность значений для заполнения VALUES
Пример: ("val_1", "val_2", ..., "val_N"), ("val_1", "val_2", ..., "val_N"), ...
где * после заполнителя — один из типов:
i
(заполнитель целого числа)d
(заполнитель числа с плавающей точкой)s
(заполнитель строкового типа)f
(заполнитель имени таблицы или поля)
правила преобразования и экранирования такие же, как и для одиночных скалярных типов, описанных выше.
$db->query('INSERT INTO test (count, amount, status) VALUES ?vi', [
[
[30, 1000, 66],
[41, 2500, 77],
[25, 3211, 24]
]
]);
SQL-запрос после преобразования шаблона:
INSERT INTO test (count, amount, status) VALUES (30, 1000, 66), (41, 2500, 77), (25, 3211, 24)
?v[?n, ?s, ?i, ?d, ...]
— заполнитель множества из двумерного массива с явным указанием типа и количества аргументов, генерирующий последовательность значений для заполнения VALUES
Пример: ("val_1", "val_2", ..., "val_N"), ("val_1", "val_2", ..., "val_N"), ...
$db->query('INSERT INTO test (count, title, amount) VALUES ?v[?i, ?s, ?d]', [
[
[30.25, 'Какой-то заголовок', '66.55'],
[40, 'Какой-то заголовок 2', '77'],
['21.55', 'Какой-то заголовок 3', 66.88]
]
]);
SQL-запрос после преобразования шаблона:
INSERT INTO test (count, title, amount) VALUES (30, 'Какой-то заголовок', 66.55), (40, 'Какой-то заголовок 2', 77), (21, 'Какой-то заголовок 3', 66.88)
?w*
— заполнитель ассоциативного множества из ассоциативного массива, генерирующий последовательность пар ключ = значение
с разделителем AND
Пример: "key_1" = "val_1" AND "key_2" = "val_2" AND ... AND "key_N" = "val_N"
Ключи экранируются заполнителем ?f
где * после заполнителя — один из типов:
i
(заполнитель целого числа)d
(заполнитель числа с плавающей точкой)s
(заполнитель строкового типа)f
(заполнитель имени таблицы или поля)
Правила преобразования и экранирования такие же, как и для одиночных скалярных типов, описанных выше.
$db->query('SELECT * FROM test WHERE ?wi', [
['count' => 30, 'amount' => 1000, 'status' => 66]
]);
SQL-запрос после преобразования шаблона:
SELECT * FROM test WHERE `count` = 30 AND amount = 1000 AND status = 66
?w[?n, ?s, ?i, ?d, ...]
— заполнитель ассоциативного множества с явным указанием типа и количества аргументов, генерирующий последовательность пар ключ = значение
с разделителем AND
Пример: "key_1" = "val_1" AND "key_2" => "val_2" AND ... AND "key_N" = "val_N"
$db->query('SELECT * FROM test WHERE ?w[?i, ?s, ?d]', [
['count' => 30.25, 'title' => 'Какой-то заголовок', 'amount' => '66.55']
]);
SQL-запрос после преобразования шаблона:
SELECT * FROM test WHERE `count` = 30 AND `title` = 'Какой-то заголовок' AND `amount` = 66.55
$db->query("INSERT INTO `users` VALUES (?n, ?s, ?i, ?s)", ['Иоанн Грозный', '54', 'в палатах']);
SQL-запрос после преобразования шаблона:
INSERT INTO `users` VALUES (NULL, 'Иоанн Грозный', 54, 'в палатах')
$user = ['name' => 'Пётр', 'age' => '30', 'adress' => "ООО 'Рога и Копыта'"];
$db->query('INSERT INTO `users` SET ?As', [$user]);
SQL-запрос после преобразования шаблона:
INSERT INTO `users` SET `name` = "Пётр", `age` = "30", `adress` = "ООО \'Рога и Копыта\'"
Вставка значений через заполнитель ассоциативного множества с явным указанием типа и количества аргументов:
$user = ['name' => "Д'Артаньян", 'age' => '19', 'adress' => 'замок Кастельмор'];
$db->query('INSERT INTO `users` SET ?A[?s, ?i, ?s]', [$user]);
SQL-запрос после преобразования шаблона:
INSERT INTO `users` SET `name` = "Д\'Артаньян",`age` = 19,`adress` = "замок Кастельмор"
$db->query('SELECT * FROM `users` WHERE `id` = ?i', ['1.00']);
SQL-запрос после преобразования шаблона:
SELECT * FROM `users` WHERE `id` = 1
$db->query(
'SELECT id, adress FROM `users` WHERE `name` IN (?a["?s", "?s", "?s"])',
[['Василий', 'Иван', "Д'Артаньян"]]
);
SQL-запрос после преобразования шаблона:
SELECT id, adress FROM `users` WHERE `name` IN ("Василий", "Иван", "Д\'Артаньян")
$db->query(
'SELECT * FROM ?f WHERE ?f IN (?as) OR `id` IN (?ai)',
'users', 'users.name', ['Василий'], ['2', 3.000]
);
SQL-запрос после преобразования шаблона:
SELECT * FROM `users` WHERE `users`.`name` IN ("Василий") OR `id` IN (2, 3)
В библиотеке есть несколько методов ORM. Заполнители встроены дополнительным 2-ым параметром, остальные параметры методов сдвинуты. Методы с поддержкой заполнителей:
- exec()
- execCommit()
- query()
- prepare()
Пример:
<?php
require_once "vendor/autoload.php"; //Подключаем библиотеку
use DigitalStars\DataBase\DB;
$db = new DB('sqlite:./test.sqlite');
// Вернёт PDOStatement
$stm = $db->prepare("SELECT * FROM ?f WHERE name = ?s AND count = ?", ['test', 'имя']);
// Вернёт выборку где count = 100
if ($stm->execute([100]))
print_r($stm->fetchAll());
// Вернёт выборку где count = 200
if ($stm->execute([200]))
print_r($stm->fetchAll());
Метод возвращает последний собранный запрос, в котором были заполнители
$stm = $db->prepare("SELECT * FROM ?f WHERE name = ?s AND count = ?", ['test', 'имя']);
echo $db->getQueryString();
Вернёт
SELECT * FROM `test` WHERE name = 'имя' AND count = ?
Аналогичен exec()
, но запрос проходит с использованием beginTransaction()
, commit()
и rollBack()
в случае неудачи.
$db->execCommit("DELETE FROM users WHERE id = ?i", [5]);;
Соберёт $sql
запрос по заполнителям из $args
и вернёт все строки (вызов PDOStatement::fetchAll
) с режимом выборки $fetchMode
.
Подробнее о режимах выборки PHP-PDO
$rows = $db->rows("SELECT * FROM users WHERE age = ?i", [30]);
// Вернёт false или все строки таблицы, где age = 30
Соберёт $sql
запрос по заполнителям из $args
и вернёт строку (вызов PDOStatement::fetch
) с режимом выборки $fetchMode
.
Подробнее о режимах выборки PHP-PDO
$row = $db->row("SELECT * FROM users WHERE age = ?i", [30]);
// Вернёт false или строку таблицы, где age = 30
Вернёт строку (вызов PDOStatement::fetch
) с режимом выборки $fetchMode
из таблицы $table
ро правилу, описанному ниже.
Подробнее о режимах выборки PHP-PDO
-
Если
$id
- число, то вернёт запись, гдеid = $id
-
Если
$id
- массив, то вернёт запись по WHERE, где ключи массив - названия полей, значения массива - значения полей
$row = $db->getById('users', 6);
// Выполнит SELECT * FROM `users` WHERE id = 6
// Вернёт false или строку таблицы, где id = 6
$row = $db->getById('users', ['user_id' => 12, 'status' => 5]);
// Выполнит SELECT * FROM `users` WHERE user_id = '12' AND status = '5'
// Вернёт false или строку таблицы, где user_id = 12 или status = 5
Соберёт $sql
запрос по заполнителям из $args
и вернёт количество затронутых строк (вызов метода PDOStatement::rowCount
)
$row = $db->count('SELECT * FROM users WHERE name = ?s', ['Василий']);
// Вернёт false или количество строк таблицы users, в которых name = 'Василий'
Вставит в таблицу $table
значения из массива $data
, в котором ключи - названия полей, значения - значения полей. Вернёт id
добавленной записи
$last_id = $db->insert('users', ['name' => 'Иван', 'age' => 30]);
// Выполнит запрос: INSERT INTO `users` (`name`, `age`) VALUES ('Иван', '30')
// Вернёт false или ID добавленной записи
Изменить таблицу $table
значениями из массива $data
, в котором ключи - названия полей,
значения - значения полей, где по $where
, в котором ключи - названия полей,
значения - значения полей. Вернёт количество затронутых строк или false
в случае ошибки.
Внимание! Если функция отработала без ошибок, но затронула
0 строк
- она вернёт0
. Что при нестрогой проверке приведётся кfalse
Если не передан
$where
, то будут затронуты все строки
$count = $db->update('users',
[
'name' => 'Иван',
'age' => 30
],
[
'id' => 6,
'status' => 9
]);
// Выполнит запрос: UPDATE `users` SET `name` = 'Иван', `age` = '30' WHERE `id` = '6' AND `status` = '9'
// Вернёт false или количество затронутых строк
Удалить из таблицы $table
$limit
записей, где по $where
, в котором ключи - названия полей,
значения - значения полей. Вернёт количество затронутых строк или false
в случае ошибки.
Внимание! Если функция отработала без ошибок, но затронула
0 строк
- она вернёт0
. Что при нестрогой проверке приведётся кfalse
Если не передан
$limit
или равен-1
, то будут удален все выбранные записи
$count = $db->delete('users', ['id' => 6, 'status' => 9], 5);
// Выполнит запрос: DELETE FROM `users` WHERE `id` = '6' AND `status` = '9' LIMIT 5
// Вернёт false или количество затронутых строк
Удалить из таблицы $table
все записи. Вернёт количество затронутых строк или false
в случае ошибки.
Внимание! Если функция отработала без ошибок, но затронула
0 строк
- она вернёт0
. Что при нестрогой проверке приведётся кfalse
$count = $db->deleteAll('users');
// Выполнит запрос: DELETE FROM `users`
// Вернёт false или количество затронутых строк
Удалить из таблицы $table
записи с id = $id
. Вернёт количество затронутых строк или false
в случае ошибки.
Внимание! Если функция отработала без ошибок, но затронула
0 строк
- она вернёт0
. Что при нестрогой проверке приведётся кfalse
$count = $db->deleteById('users', 6);
// Выполнит запрос: DELETE FROM `users` WHERE `id` = 6
// Вернёт false или количество затронутых строк
Удалить из таблицы $table
записи, где $column
равен одному из $ids
. Вернёт количество затронутых строк или false
в случае ошибки.
$ids
должен быть обычным или ассоциативным массивом.
Внимание! Если функция отработала без ошибок, но затронула
0 строк
- она вернёт0
. Что при нестрогой проверке приведётся кfalse
$count = $db->deleteByIds('users', 'status', [6, 8, 10]);
// Выполнит запрос: DELETE FROM `users` WHERE `status` IN ('6', '8', '10')
// Вернёт false или количество затронутых строк
Очищает таблицу $table
. Вернёт количество затронутых строк или false
в случае ошибки.
Сбрасываются также внутренние счётчики таблицы
Внимание! Если функция отработала без ошибок, но затронула
0 строк
- она вернёт0
. Что при нестрогой проверке приведётся кfalse
$count = $db->truncate('users');
// Выполнит запрос: TRUNCATE TABLE `users`
// Вернёт false или количество затронутых строк