Базы данных
База данных — основа любого современного веб-приложения. Imhotep предоставляет единый API для работы с MySQL, PostgreSQL и SQLite, позволяя выполнять запросы, управлять структурой данных и контролировать транзакции через интуитивно понятный интерфейс.
В основе лежат три ключевых принципа:
- Безопасность — все запросы проходят через параметризацию, исключая SQL-инъекции на уровне API.
- Удобство — построитель запросов и схема данных позволяют работать с БД без написания сырого SQL.
- Гибкость — разделение подключений на чтение/запись, транзакции с автоматическим восстановлением и поддержка нескольких соединений одновременно.
Поддерживаемые СУБД
Imhotep поддерживает наиболее популярные реляционные баз данных:
| СУБД | Минимальная версия |
|---|---|
| MariaDB | 10.3 |
| MySQL | 5.7 |
| PostgreSQL | 10.0 |
| SQLite | 3.26.0 |
Конфигурирование
Все подключения настраиваются в файле config/database.php. Этот файл содержит полный набор опций для каждой поддерживаемой СУБД.
Подробные инструкции по настройке каждой СУБД:
Подключение через URL
Вместо указания отдельных параметров host, port, database, username и password, вы можете задать подключение через единый DSN-подобный URL. Это удобно для облачных сервисов, которые могут предоставлять строку подключения в переменной окружения.
# .env
DATABASE_URL = mysql://root:secret@127.0.0.1:3306/imhotep
Использование в конфигурации:
// config/database.php
'connections' => [
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
// остальные параметры переопределяются через URL
],
],
Если указан
url, параметры из него имеют приоритет над отдельными параметрами host, port, database и т.д.
Выполнение SQL-запросов
Для выполнения SQL-запросов используйте фасад DB. Он содержит методы для всех типов запросов.
Важно: Всегда используйте связанные параметры вместо подстановки значений напрямую в SQL-запрос. Это защищает приложение от SQL-инъекций.
use Imhotep\Facades\DB;
// Неправильно — опасно!
DB::select("SELECT * FROM users WHERE id = {$id}");
// Правильно — безопасно
DB::select("SELECT * FROM users WHERE id = ?", [$id]);
SELECT
Метод select всегда возвращает массив объектов stdClass, каждый из которых представляет запись из базы данных.
use Imhotep\Facades\DB;
$users = DB::select("SELECT * FROM users");
foreach ($users as $user) {
echo $user->name;
}
Если запрос имеет условия, используйте связанные параметры для передачи их значений:
// Обычное связывание, через символ "?"
$users = DB::select("SELECT * FROM users WHERE active = ?", [1]);
// Именованные привязки
$users = DB::select("SELECT * FROM users WHERE active = :active", ['active' => 1]);
INSERT
Результатом выполнения INSERT запроса, будет количество вставленных записей.
// Обычное связывание, через символ "?"
$affected = DB::insert("INSERT INTO users (id, name) VALUES (?, ?)", [1, 'John']);
// Использование именованных привязок
$affected = DB::insert("INSERT INTO users (id, name) VALUES (:id, :name)", ['id' => 1, 'name' => 'John']);
UPDATE
Результатом выполнения UPDATE запроса, будет количество обновленных записей.
// Обычное связывание, через символ "?"
$affected = DB::update("UPDATE users SET age = ? WHERE name = ?", [24, 'John']);
// Использование именованных привязок
$affected = DB::update("UPDATE users SET age = :age WHERE name = :name", ['age' => 24, 'name' => 'John']);
DELETE
Результатом выполнения DELETE запроса, будет количество удаленных записей.
// Обычное связывание, через символ "?"
$affected = DB::delete("DELETE FROM users WHERE name = ?", ['John']);
// Использование именованных привязок
$affected = DB::delete("DELETE FROM users WHERE name = :name", ['name' => 'John']);
Другие запросы
Некоторые операторы SQL-запросов не возвращают значений. Для этих операций можно использовать метод statement фасада DB, который в случае успешного выполнения вернет true:
$result = DB::statement("DROP TABLE users");
Транзакций
Imhotep предоставляет мощный механизм для работы с транзакциями, включая автоматические и ручные транзакции, вложенные транзакции через savepoints, а также автоматическое восстановление при deadlock.
use Imhotep\Facades\DB;
// Автоматическая транзакция
DB::transaction(function () {
DB::update('UPDATE accounts SET balance = balance - ?', [100]);
DB::update('UPDATE accounts SET balance = balance + ?', [100]);
});
// Ручное управление
DB::beginTransaction();
try {
// операции...
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
Подробнее о транзакциях на этой странице.
Несколько соединений к БД
Если в конфигурационном файле config/database.php определено несколько соединений, для получения доступа к каждому из них, используйте метод connection фасада DB, передав в качестве первого аргумента имя соединения, указанному в конфигурационном файле.
use Imhotep\Facades\DB;
$users = DB::connection('sqlite')->select(...);
Прослушивание событий запроса
При необходимости, можно указать замыкание, которое будет вызываться для каждого SQL-запроса, используя метод listen фасада DB. Этот метод может быть полезен для логирования или отладки. Зарегистрировать замыкание удобней всего в методе boot в AppServiceProvider:
<?php
namespace App\Providers;
use Imhotep\Facades\DB;
use Imhotep\Framework\Providers\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
// ...
public function boot()
{
DB::listen(function ($query) {
// $query->sql;
// $query->bindings;
// $query->time;
});
}
}