Базы данных

База данных — основа любого современного веб-приложения. 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
INI

Использование в конфигурации:

// config/database.php

'connections' => [
    'mysql' => [
        'driver' => 'mysql',
        'url' => env('DATABASE_URL'),
        // остальные параметры переопределяются через URL
    ],
],
PHP

Если указан 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]);
PHP

SELECT

Метод select всегда возвращает массив объектов stdClass, каждый из которых представляет запись из базы данных.

use Imhotep\Facades\DB;

$users = DB::select("SELECT * FROM users");

foreach ($users as $user) {
    echo $user->name;
}
PHP

Если запрос имеет условия, используйте связанные параметры для передачи их значений:

// Обычное связывание, через символ "?"
$users = DB::select("SELECT * FROM users WHERE active = ?", [1]);

// Именованные привязки
$users = DB::select("SELECT * FROM users WHERE active = :active", ['active' => 1]);
PHP

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']);
PHP

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']);
PHP

DELETE

Результатом выполнения DELETE запроса, будет количество удаленных записей.

// Обычное связывание, через символ "?"
$affected = DB::delete("DELETE FROM users WHERE name = ?", ['John']);

// Использование именованных привязок
$affected = DB::delete("DELETE FROM users WHERE name = :name", ['name' => 'John']);
PHP

Другие запросы

Некоторые операторы SQL-запросов не возвращают значений. Для этих операций можно использовать метод statement фасада DB, который в случае успешного выполнения вернет true:

$result = DB::statement("DROP TABLE users");
PHP

Транзакций

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;
}
PHP

Подробнее о транзакциях на этой странице.

Несколько соединений к БД

Если в конфигурационном файле config/database.php определено несколько соединений, для получения доступа к каждому из них, используйте метод connection фасада DB, передав в качестве первого аргумента имя соединения, указанному в конфигурационном файле.

use Imhotep\Facades\DB;

$users = DB::connection('sqlite')->select(...);
PHP

Прослушивание событий запроса

При необходимости, можно указать замыкание, которое будет вызываться для каждого 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;
        });
    }
}
PHP