BMC IO DocsBMC IO Docs
IO v6
IO v7
Notes
Docs
IO v6
IO v7
Notes
Docs
  • IO Framework v7

    • О фреймворке
    • Что изменилось в 7 версии
    • IO7 Framework vs Laravel 13 — Сравнение
    • Структура
    • Варианты проектов
    • Доступ к участкам проекта
    • Разворачивание нового проекта
    • Установка проекта
    • Запуск локальной разработки
  • API

    • Обзор API
    • IOCore::call() и IOCore::callAction()
    • Создание API
  • CLI

    • Обзор CLI
    • iocli
    • Кастомные CLI команды
  • Работа с базами данных

    • Обзор работы с базами данных
    • Cron / Планировщик задач (Schedule)
    • Фабрики
    • Миграции
    • Сидеры
    • Query Builder
    • Подключение MinIO
    • Подключение MongoDB
    • Подключение MySQL
    • Подключение PostgreSQL
    • Подключение ProxySQL
    • Подключение RabbitMQ
    • Подключение Redis
  • Логирование

    • Обзор логирования
    • IOEvent - Логирование событий
    • Pinba (PinbaManager) - Профилировщик
  • Модели

    • Обзор моделей
    • CRUD операции
    • Связи моделей
  • Очереди

    • Обзор очередей
    • RabbitMQ
  • Маршруты

    • Обзор маршрутов
    • Определение маршрутов
    • Middleware
  • Сессии

    • Обзор сессий
    • Кроссдоменная SSO
    • JWT авторизация
    • Социальная авторизация
    • OAuth2
    • Keycloak
  • Twig

    • Обзор Twig
    • Формы (FormBuilder)
    • Twig функции
  • Тестирование

    • Обзор тестирования
    • Unit тесты
  • Backend

    • Настройки проекта Conf.php
    • Настройки модуля Module.php
    • Настройки composer
    • Функции фреймворка
    • Вспомогательные функции (Helpers)
    • Глобальные переменные
    • Константы фреймворка
    • Event класс
    • Core класс
    • Route и работа с ними
    • Request и работа с ними
    • Middleware и работа с ними
    • Class и работа с ними
    • Api model и работа с ними
    • Template и работа с ними
    • Мультиязычность и словарь фраз
    • Bin скрипты и работа с ними
    • Cron скрипты и работа с ними
    • $ioSession и работа с сессией
    • $ioHash и работа с кешем
    • $ioXCache и работа с кешем
    • $iodb и работа с базой данных
    • Миграции
  • Frontend

    • Twig шаблонизатор и работа с ним
    • Twig функции
    • Twig фильтры
    • Twig контекст
    • Настройка NPM
    • Сборка Frontend составляющей
    • Обращение к Api через JS
    • Хранилище (store)
    • Навигация в хосте
    • Навигация в микрофронтенде
    • Параметры микрофронтенда
    • Проверка полномочий
  • Tailux UI Компоненты

    • Базовый UI

      • AvatarDot
      • Avatar
      • Badge
      • Button
      • Card
      • ConfirmModal
      • Divider
      • Highlight
      • Tag
    • Загрузка

      • Circlebar
      • Progress
      • Skeleton
      • Spinner
    • Навигация

      • Accordion
      • AccordionButton
      • AccordionHeader
      • AccordionItem
      • AccordionPanel
      • AccordionProvider
      • Pagination
      • PaginationControl
      • PaginationItems
      • PaginationDots
      • PaginationFirst
      • PaginationLast
      • PaginationNext
      • PaginationPrevious
    • Отображение данных

      • Box
      • Collapse
      • ContextualHelp
      • ScrollShadow
      • Timeline
      • TimelineItem
    • Элементы таблиц

      • Table
      • CollapsibleSearch
      • ColumnFilter
      • CopyableCell
      • DateFilter
      • FacetedFilter
      • FilterSelector
      • PaginationSection
      • RadioFilter
      • RangeFilter
      • ResponsiveFilter
      • RoleFilter
      • SelectedRowsActions
      • TableColumnVisibility
      • TableSettings
      • TableSortIcon
    • Элементы форм

      • Checkbox
      • Combobox
      • DatePicker
      • Filepond
      • Input
      • Listbox
      • Radio
      • Range
      • Select
      • StyledSwitch
      • Swap
      • SwapOn
      • SwapOff
      • Switch
      • Textarea
      • TextEditor
      • Upload

Обзор работы с базами данных

Внимание

Данная статья документации написана нейросетью. Возможны некоторые расхождения и неточность информации!

  • Архитектура
  • SqlConnection
    • Конструктор
    • Свойства
    • Статические свойства
    • Методы подключения
    • Статические методы (Query Builder)
    • Raw PDO запросы
    • Экранирование
    • Высокоуровневые методы
    • Транзакции
    • Получение информации
  • ConnectionManager
    • getEngine()
    • mysqlConfig()
    • pgsqlConfig()
    • readWriteConfig()
    • fromConstants()
  • DB фасад
    • init()
    • initPdo()
    • getCapsule()
    • connection()
    • __callStatic()
  • Примеры
    • Базовое подключение к MySQL
    • Подключение через DB фасад
    • Raw запросы
    • Транзакции
    • Query Builder
    • IO Фильтры в Query Builder
  • Рекомендации
  • FAQ
    • Как переключиться с MySQL на PostgreSQL?
    • Что лучше: raw SQL или Query Builder?
    • Как работать с несколькими подключениями?
    • Как проверить, что соединение активно?
    • Что возвращает search()?
  • Системные SqlClass модели (IO\Classes)
    • MigrationLog
    • CronJob
    • CronWork
    • CronData
    • CacheRow
  • Проектные SqlClass модели (App\Classes)

Руководство по подключению и работе с различными базами данных в IO7 фреймворке.

Архитектура

IO7 фреймворк предоставляет три уровня абстракции для работы с базами данных:

КомпонентНазначение
SqlConnectionRaw PDO + Query Builder для MySQL/PostgreSQL
ConnectionManagerФабрика конфигураций подключений
DBФасад — прямой мост к Laravel Capsule
┌──────────────────────────────────────────────────┐
│                    Приложение                    │
├───────────────┬─────────────────────┬────────────┤
│ SqlConnection │  ConnectionManager  │     DB     │
├───────────────┴─────────────────────┴────────────┤
│           Illuminate\Database\Capsule            │
├──────────────┬───────────────┬───────────────────┤
│    MySQL     │  PostgreSQL   │  Другие драйверы  │
└──────────────┴───────────────┴───────────────────┘

SqlConnection

Единый класс для работы с SQL базами данных. Объединяет raw PDO (для прямых SQL) и Laravel Query Builder.

Пространство имён: IO\Database

Конструктор

public function __construct(string $driver = 'mysql')
ПараметрТипЗначение по умолчаниюОбязателенОписание
$driverstring'mysql'НетТип БД: 'mysql' или 'pgsql'

Свойства

СвойствоТипЗначение по умолчаниюОбязателенОписание
$db_link?\PDOnullНетPDO подключение
$last_querystring''НетПоследний выполненный запрос (экземпляр)
$serverstring''ДаАдрес сервера БД
$userstring''ДаПользователь БД
$passstring''ДаПароль БД
$dbstring''ДаИмя базы данных
$driverstring'mysql'НетДвижок БД (mysql или pgsql)
$lastconnectint1НетРазрешение на подключение (1 — да, 0 — нет)
$log_queryint0НетЛогирование запросов (0/1)
$code_pagestring'utf8'НетКодировка
$time_zonestring'+05:00'НетЧасовой пояс
$_errorstrstring''НетТекст последней ошибки
$_errornostring''НетКод последней ошибки
$_time_query_maxint2000НетМаксимальное время запроса (мс)
$columnsarray[]НетСтруктура таблиц information_schema

Статические свойства

СвойствоТипЗначение по умолчаниюОбязателенОписание
$last_query_allstring''НетПоследний выполненный запрос (глобальный)
$db_connectionsarray<string, self>[]НетКэш подключений

Методы подключения

tryconnect()

public function tryconnect(): int

Пытается подключиться к БД. Использует свойства $server, $user, $pass, $db.

Возвращает: 1 — успех, 0 — ошибка

$db = new SqlConnection('mysql');
$db->server = 'localhost';
$db->user = 'root';
$db->pass = 'password';
$db->db = 'mydb';

if ($db->tryconnect()) {
    echo "Подключено!";
}

connect()

public function connect(string $server, string $user, string $pass, ?string $db = null): int
ПараметрТипЗначение по умолчаниюОбязателенОписание
$serverstring—ДаАдрес сервера
$userstring—ДаПользователь
$passstring—ДаПароль
$db?stringnullНетИмя базы данных (null для подключения без выбора БД)

Возвращает: 1 — успех, 0 — ошибка

$db = new SqlConnection('pgsql');
$db->connect('192.168.1.10', 'admin', 'secret', 'production');

create_conn()

public static function create_conn(
    string $server,
    string $user,
    string $pass,
    string $db = '',
    string $driver = 'mysql'
): self

Создаёт или получает кэшированное подключение.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$serverstring—ДаАдрес сервера
$userstring—ДаПользователь
$passstring—ДаПароль
$dbstring''НетИмя базы данных
$driverstring'mysql'НетТип БД
$db = SqlConnection::create_conn('localhost', 'root', 'password', 'mydb');
// Повторный вызов вернёт тот же экземпляр
$db2 = SqlConnection::create_conn('localhost', 'root', 'password', 'mydb');
// $db === $db2

ping()

public function ping(): bool

Проверяет соединение через SELECT 1.

if (!$db->ping()) {
    $db->tryconnect();
}

is_valid()

public function is_valid(): bool

Проверяет, установлен ли PDO объект.

connected()

public function connected(): bool

Проверяет активность соединения.

usedb()

public function usedb(string $dbname): void

Переключает на другую базу данных (только MySQL).

ПараметрТипЗначение по умолчаниюОбязателенОписание
$dbnamestring—ДаИмя базы данных

Статические методы (Query Builder)

table()

public static function table(string $table): \Illuminate\Database\Query\Builder

Получить Query Builder для таблицы.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$tablestring—ДаИмя таблицы
$users = SqlConnection::table('users')
    ->where('active', 1)
    ->orderBy('name')
    ->get();

connection()

public static function connection(string $name = null): \Illuminate\Database\Connection

Получить подключение к БД по имени.

$conn = SqlConnection::connection('mysql');
$schema = $conn->getSchemaBuilder();

__callStatic()

public static function __callStatic(string $method, array $args)

Делегирует вызовы в Capsule. Все методы Laravel Capsule доступны через статический вызов.

SqlConnection::purge();
SqlConnection::beginTransaction();

Raw PDO запросы

query()

public function query(string $query = '', ?array $arr = null, bool $save_log = true)

Выполнить SQL запрос через PDO с подготовленными выражениями.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$querystring''НетSQL запрос с плейсхолдерами
$arr?\arraynullНетПараметры для подстановки
$save_logbooltrueНетСохранять ли в лог
$save_logboolСохранять ли в лог. По умолчанию true

Возвращает: \PDOStatement|false

$r = $db->query("SELECT * FROM users WHERE id = ?", [1]);
while ($row = $db->fetch($r)) {
    echo $row['name'];
}
$db->free_result($r);

query_params()

public function query_params(string $query = '', ?array $arr = null, bool $save_log = true)

Алиас для query().

fetch()

public function fetch(?\PDOStatement $result): array|false

Получить одну строку из результата (ассоциативный массив).

fetch_assoc()

public function fetch_assoc(?\PDOStatement $result): array|false

Алиас для fetch().

fetchAll()

public function fetchAll(?\PDOStatement $result): array|false

Получить все строки из результата.

free_result()

public function free_result(?\PDOStatement $result): bool

Закрыть курсор результата.

num_rows()

public function num_rows(?\PDOStatement $res): int

Получить количество строк в результате.

last_insert_id()

public function last_insert_id(): string|int

Получить ID последней вставленной записи.

get_var()

public function get_var(string $field, string $q, array $arr = [])

Получить значение одного поля из запроса.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$fieldstring—ДаИмя поля
$qstring—ДаSQL запрос
$arrarray[]НетПараметры
$name = $db->get_var('name', "SELECT name FROM users WHERE id = 1");

get_count()

public function get_count(string $q, string $field = 'count')

Получить значение COUNT из запроса.

Экранирование

escape()

public static function escape(string $msg): string

Экранирование специальных символов для SQL.

$safe = SqlConnection::escape("O'Brien");
// O\'Brien

escape2()

public static function escape2(string $field): string

Экранирование имени таблицы/поля для SQL.

$escaped = SqlConnection::escape2('users.name');
// `users`.`name`

// Префикс # отключает экранирование
$raw = SqlConnection::escape2('#COUNT(*)');
// COUNT(*)

// Префикс * возвращает как есть
$star = SqlConnection::escape2('*');
// *

Высокоуровневые методы

insert()

public function insert(string $table, array $data, ?array $data2 = null): int

Вставить запись в таблицу.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$tablestring—ДаИмя таблицы
$dataarray—ДаАссоциативный массив данных
$data2?\arraynullНетДополнительные данные (не используется)

Возвращает: 1 — успех, -1 — ошибка

$db->insert('users', [
    'name' => 'John',
    'email' => 'john@example.com',
    'status' => 1,
]);

update()

public function update(string $table, array $filter, array $data, ?array $data2 = null): int

Обновить записи в таблице.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$tablestring—ДаИмя таблицы
$filterarray—ДаФильтр (условия WHERE)
$dataarray—ДаДанные для обновления
$db->update('users', ['pkid' => 1], ['name' => 'Jane']);
$db->update('users', ['status' => 0, '>created_at' => '2024-01-01'], ['active' => 0]);

delete()

public function delete(string $table, array $filter, ?int $count = null): int

Удалить записи из таблицы.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$tablestring—ДаИмя таблицы
$filterarray—ДаФильтр (условия WHERE)
$count?\intnullНетЛимит удаления
$db->delete('users', ['pkid' => 1]);
$db->delete('logs', ['<created_at' => '2024-01-01'], 100);

insert_or_update()

public function insert_or_update(string $table, array $data, ?array $data2 = null): int

Вставить или обновить запись (MySQL: ON DUPLICATE KEY UPDATE, PostgreSQL: ON CONFLICT DO UPDATE).

insert_or_ignore()

public function insert_or_ignore(string $table, array $data, ?array $data2 = null): int

Вставить или игнорировать (MySQL: INSERT IGNORE, PostgreSQL: ON CONFLICT DO NOTHING).

search()

public function search(string $table, array $params): array

Поиск записей в таблице.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$tablestring—ДаИмя таблицы
$paramsarray—ДаПараметры поиска

Параметры $params:

КлючТипЗначение по умолчаниюОбязателенОписание
filterarray[]НетФильтр
fieldsarray[]НетПоля
joinarray|string[]НетJOIN
groupbyarray[]НетGROUP BY
orderarray[]НетORDER BY [field => 'asc'|'desc']
distinctboolfalseНетDISTINCT
limitint1000НетЛимит
startint0НетСмещение

Возвращает:

[
    'error_str' => '',
    'error_code' => EIO_OK,
    'res' => [...],       // массив записей
    'count' => 150,       // общее количество
    'time' => 5,          // время выполнения (мс)
]
$result = $db->search('users', [
    'filter' => ['status' => 1, '%name' => 'John'],
    'order' => ['name' => 'asc', 'id' => 'desc'],
    'limit' => 25,
    'start' => 0,
]);

foreach ($result['res'] as $row) {
    echo $row['name'];
}
echo "Всего: {$result['count']}";

sync_items()

public function sync_items(string $table, array $params): void

Синхронизация элементов (create/update/delete).

ПараметрТипЗначение по умолчаниюОбязателенОписание
$tablestring—ДаИмя таблицы
$paramsarray—ДаПараметры синхронизации

Параметры $params:

КлючТипЗначение по умолчаниюОбязателенОписание
new_itemsarray—ДаНовые элементы
filterarray—ДаФильтр для поиска старых
findcallable—ДаФункция поиска соответствия function(array $old, array $new): bool
createcallable|nullnullНетФункция создания function(array $new): void
updatecallable|nullnullНетФункция обновления function(array $old, array $new): void
deletecallable|nullnullНетФункция удаления function(array $old): void
$db->sync_items('categories', [
    'new_items' => $importedCategories,
    'filter' => ['parent_id' => 0],
    'find' => function(array $old, array $new): bool {
        return $old['code'] === $new['code'];
    },
    'create' => function(array $new) use ($db): void {
        $db->insert('categories', $new);
    },
    'update' => function(array $old, array $new) use ($db): void {
        $db->update('categories', ['pkid' => $old['pkid']], $new);
    },
    'delete' => function(array $old) use ($db): void {
        $db->delete('categories', ['pkid' => $old['pkid']]);
    },
]);

Транзакции

public function beginTransaction(): bool
public function commit(): bool
public function rollBack(): bool
$db->beginTransaction();
try {
    $db->insert('orders', ['user_id' => 1, 'total' => 100]);
    $db->update('users', ['pkid' => 1], ['balance' => '-100']);
    $db->commit();
} catch (\Exception $e) {
    $db->rollBack();
    throw $e;
}

Получение информации

affected_rows()

public function affected_rows(): ?int

Количество затронутых строк (MySQL ROW_COUNT()).

found_rows()

public function found_rows(): ?int

Количество найденных строк (MySQL FOUND_ROWS()).

error()

public function error(): string

Код последней ошибки.

errorstr()

public function errorstr(): string

Текст последней ошибки.

information_schema_load_current_db()

public function information_schema_load_current_db(): void

Загружает структуру таблиц из information_schema (MySQL). Результат доступен в $db->columns.


ConnectionManager

Фабрика конфигураций подключений. Все методы статические.

Пространство имён: IO\Database

getEngine()

public static function getEngine(): string

Определяет движок БД из константы DB_ENGINE или переменной окружения. По умолчанию 'mysql'.

$engine = ConnectionManager::getEngine(); // 'mysql' или 'pgsql'

mysqlConfig()

public static function mysqlConfig(
    $host,
    $database,
    $username,
    $password,
    $port = 3306
): array

Создаёт конфигурацию для MySQL подключения.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$hoststring—ДаАдрес сервера
$databasestring—ДаИмя базы данных
$usernamestring—ДаПользователь
$passwordstring—ДаПароль
$portint3306НетПорт
$config = ConnectionManager::mysqlConfig('localhost', 'mydb', 'root', 'secret');
// ['driver' => 'mysql', 'host' => 'localhost', ...]

pgsqlConfig()

public static function pgsqlConfig(
    $host,
    $database,
    $username,
    $password,
    $port = 5432
): array

Создаёт конфигурацию для PostgreSQL подключения.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$hoststring—ДаАдрес сервера
$databasestring—ДаИмя базы данных
$usernamestring—ДаПользователь
$passwordstring—ДаПароль
$portint5432НетПорт

readWriteConfig()

public static function readWriteConfig(
    $readHosts,
    $writeHosts,
    $database,
    $username,
    $password
): array

Конфигурация для read/write разделения.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$readHostsstring|array—ДаАдрес(а) реплик для чтения
$writeHostsstring|array—ДаАдрес(а) мастеров для записи
$databasestring—ДаИмя базы данных
$usernamestring—ДаПользователь
$passwordstring—ДаПароль
$config = ConnectionManager::readWriteConfig(
    ['replica1.local', 'replica2.local'],
    'master.local',
    'mydb',
    'root',
    'secret'
);

fromConstants()

public static function fromConstants(): array

Создаёт подключения из глобальных констант и переменных окружения.

Приоритет:

  1. Если ProxySQL прокинут — используется его с движком из DB_ENGINE
  2. Иначе — движок-специфичные переменные (MYSQL_* или PGSQL_*)
$connections = ConnectionManager::fromConstants();
// ['mysql' => [...]] или ['pgsql' => [...]]

DB фасад

Прямой мост к Laravel Capsule. Все вызовы проксируются в Capsule, новые методы Laravel доступны автоматически.

Пространство имён: IO\Database

init()

public static function init($config, $name = 'default'): \Illuminate\Database\Capsule\Manager

Инициализация подключения.

ПараметрТипЗначение по умолчаниюОбязателенОписание
$configarray—ДаКонфигурация подключения
$namestring'default'НетИмя подключения
DB::init([
    'driver' => 'mysql',
    'host' => 'localhost',
    'database' => 'mydb',
    'username' => 'root',
    'password' => 'secret',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
]);

initPdo()

public static function initPdo(\PDO $pdo, string $driver = 'mysql'): \Illuminate\Database\Capsule\Manager

Инициализация через существующий PDO (общее подключение).

ПараметрТипЗначение по умолчаниюОбязателенОписание
$pdo\PDO—ДаСуществующее PDO подключение
$driverstring'mysql'НетТип драйвера
$pdo = new PDO('mysql:host=localhost;dbname=mydb', 'root', 'secret');
DB::initPdo($pdo);

getCapsule()

public static function getCapsule(): \Illuminate\Database\Capsule\Manager

Получить экземпляр Capsule.

connection()

public static function connection($name = null): \Illuminate\Database\Connection

Получить соединение по имени.

$conn = DB::connection('mysql');

__callStatic()

Все неопределённые статические вызовы проксируются в Capsule:

DB::table('users')->where('active', 1)->get();
DB::beginTransaction();
DB::purge();

Примеры

Базовое подключение к MySQL

use IO\Database\SqlConnection;

$db = new SqlConnection('mysql');
$db->server = 'localhost';
$db->user = 'root';
$db->pass = 'password';
$db->db = 'mydb';

if ($db->tryconnect()) {
    $result = $db->search('users', [
        'filter' => ['status' => 1],
        'limit' => 10,
    ]);

    foreach ($result['res'] as $user) {
        echo $user['name'] . "\n";
    }
}

Подключение через DB фасад

use IO\Database\DB;
use IO\Database\ConnectionManager;

// Из констант окружения
$connections = ConnectionManager::fromConstants();
foreach ($connections as $name => $config) {
    DB::init($config, $name);
}

// Использование
$users = DB::table('users')->where('active', 1)->get();
DB::table('users')->insert(['name' => 'New User']);

Raw запросы

$db = new SqlConnection('mysql');
$db->connect('localhost', 'root', 'pass', 'mydb');

// SELECT
$r = $db->query("SELECT * FROM users WHERE status = ?", [1]);
while ($row = $db->fetch($r)) {
    echo $row['name'];
}
$db->free_result($r);

// INSERT
$db->query("INSERT INTO logs (msg, created_at) VALUES (?, NOW())", ['test']);

// UPDATE
$db->query("UPDATE users SET active = 0 WHERE last_login < DATE_SUB(NOW(), INTERVAL 1 YEAR)");

Транзакции

$db->beginTransaction();
try {
    $db->insert('transfers', [
        'from_user' => 1,
        'to_user' => 2,
        'amount' => 500,
    ]);

    $db->update('users', ['pkid' => 1], ['balance' => '-500']);
    $db->update('users', ['pkid' => 2], ['balance' => '+500']);

    $db->commit();
} catch (\Exception $e) {
    $db->rollBack();
    throw $e;
}

Query Builder

// SELECT с фильтрами
$users = SqlConnection::table('users')
    ->where('active', 1)
    ->where('role', 'admin')
    ->orderBy('name', 'asc')
    ->limit(25)
    ->get();

// JOIN
$orders = SqlConnection::table('orders')
    ->join('users', 'users.id', '=', 'orders.user_id')
    ->select('orders.*', 'users.name')
    ->where('orders.status', 'pending')
    ->get();

// COUNT
$count = SqlConnection::table('users')->where('active', 1)->count();

// UPDATE
SqlConnection::table('users')
    ->where('pkid', 1)
    ->update(['last_login' => now()]);

IO Фильтры в Query Builder

$filter = [
    'status' => 1,                    // WHERE status = 1
    '%name' => 'John',                // WHERE name LIKE '%John%'
    '>age' => 18,                     // WHERE age > 18
    '<=price' => 100,                 // WHERE price <= 100
    '~deleted_at' => null,            // WHERE deleted_at IS NULL
    '!~deleted_at' => null,           // WHERE deleted_at IS NOT NULL
    'role' => ['admin', 'moderator'], // WHERE role IN ('admin', 'moderator')
    '$or' => [
        ['type' => 'premium'],
        ['status' => 'active'],
    ],
];

$users = SqlConnection::table('users');
$users = SqlConnection::applyFilterToQuery($users, $filter);
$results = $users->get();

Рекомендации

  1. Предпочитайте Query Builder raw-запросам для простых операций
  2. Используйте транзакции для связанных операций записи
  3. Экранируйте пользовательский ввод через escape() при raw-запросах
  4. Используйте кэш подключений через create_conn() для повторных соединений
  5. Проверяйте соединение через ping() перед критическими операциями
  6. Используйте фильтры IO для единообразной фильтрации данных
  7. Избегайте SELECT * — указывайте конкретные поля в search()

FAQ

Как переключиться с MySQL на PostgreSQL?

Измените значение DB_ENGINE в .env на pgsql и убедитесь, что переменные PGSQL_* заданы. ConnectionManager::fromConstants() автоматически определит нужный драйвер.

Что лучше: raw SQL или Query Builder?

Query Builder безопаснее (защита от SQL-инъекций) и проще для поддержки. Raw SQL используйте только для сложных запросов, которые нельзя выразить через Query Builder.

Как работать с несколькими подключениями?

$db1 = SqlConnection::create_conn('host1', 'user1', 'pass1', 'db1');
$db2 = SqlConnection::create_conn('host2', 'user2', 'pass2', 'db2');

Как проверить, что соединение активно?

if ($db->ping()) {
    // Соединение активно
} else {
    $db->tryconnect();
}

Что возвращает search()?

Ассоциативный массив с ключами: error_str, error_code, res (данные), count (общее кол-во), time (время в мс).


Системные SqlClass модели (IO\Classes)

Фреймворковые классы таблиц в modules/io7/php/Classes/:

КлассТаблицаОписание
MigrationLogmigrationsТрекинг миграций (batch, applied_at)
CronJobcronОпределения cron задач
CronWorkcron_workЛоги выполнения cron
CronDatacron_dataДанные cron задач (key-value)
CacheRowcacheКеш в БД (при CACHE_ENGINE=database)

MigrationLog

use IO\Classes\MigrationLog;

MigrationLog::getApplied();      // list<string> имен миграций
MigrationLog::getMaxBatch();     // int максимальный batch
MigrationLog::log('name', 1);    // записать миграцию
MigrationLog::removeLog('name', 1); // удалить запись

CronJob

use IO\Classes\CronJob;

CronJob::getEnabled();            // list<array> активные задачи
CronJob::findByClassname('DeleteCron'); // ?array
CronJob::getRunningCount(1);     // int выполняющихся потоков

CronWork

use IO\Classes\CronWork;

CronWork::markRunning(1);        // int ID записи
CronWork::markDone($id, $log, $timestamps, $avg, $count);
CronWork::markFailed($id, $error);
CronWork::getStats();            // array{running, completed, failed}
CronWork::cleanupOlderThan('2026-01-01');

CronData

use IO\Classes\CronData;

CronData::load('my_key');        // ?array
CronData::save('my_key', $data);

CacheRow

use IO\Classes\CacheRow;

CacheRow::get('key');             // mixed
CacheRow::set('key', $value, 3600);
CacheRow::forget('key');
CacheRow::flush();
CacheRow::gc();                  // удалить истёкшие

Проектные SqlClass модели (App\Classes)

Классы таблиц проекта в app/Classes/:

// app/Classes/User.php
namespace App\Classes;
use IO\SqlClass;

class User extends SqlClass
{
    protected string $table = 'users';
    protected string $primaryKey = 'pkid';
    public bool $timestamps = false;
}
Next
Cron / Планировщик задач (Schedule)