WSDB
WSDB предоставляет статический доступ к основному подключению базы данных CMS.Поддерживает
- статический доступ к основному подключению
- регистрацию дополнительных подключений
- выборку, добавление, обновление и удаление данных
- атомарное увеличение числовых значений
- выбор одной приоритетной строки из каждой группы
- подсчёт уникальных значений столбца
- условия, сортировку и ограничение выборки
- работу с JSON-полями
- транзакции с автоматическим откатом
- блокировку параллельного выполнения операций
- проверку существования таблиц, столбцов и индексов
- автоматическое использование префикса таблиц
Класс автоматически доступен после запуска CMS. Создавать его экземпляр не нужно.
Быстрый старт
Получение одной строки:
$page = WSDB::fetchOne(
'page',
['id' => 15],
['id', 'title', 'url']
);Получение списка:
$pages = WSDB::fetchAll(
table: 'page',
where: ['status' => 'publish'],
columns: ['id', 'title', 'url'],
order: ['id' => 'DESC'],
limit: 10
);Добавление данных:
$id = WSDB::insert(
'page',
[
'title' => 'Новая страница',
'status' => 'draft',
]
);Подключения
Основное подключение регистрируется CMS автоматически. Для обычной работы дополнительно настраивать его не нужно.
on(string $name = 'default'): Database
Возвращает объект Database для выполнения запросов:
$database = WSDB::on();
$page = $database->fetchOne('page', ['id' => 15]);Для основного подключения методы Database можно вызывать напрямую через WSDB:
$page = WSDB::fetchOne('page', ['id' => 15]);connection(string $name = 'default'): DatabaseConnection
Возвращает параметры зарегистрированного подключения:
$connection = WSDB::connection();
$pdo = $connection->pdo();
$prefix = $connection->prefix();Обычно получать DatabaseConnection вручную не требуется.
isRegistered(string $name = 'default'): bool
Проверяет, зарегистрировано ли подключение с указанным именем:
if (WSDB::isRegistered('analytics')) {
$database = WSDB::on('analytics');
}register(DatabaseConnection $connection, string $name = 'default'): void
Регистрирует дополнительное подключение:
$connection = DatabaseConnection::connect('localhost', 'analytics', 'user', 'password', 'ANALYTICS_');
WSDB::register($connection, 'analytics');После регистрации запросы выполняются через выбранное подключение:
$events = WSDB::on('analytics')->fetchAllFrom('events', ['id', 'name']);Имя подключения приводится к нижнему регистру. Оно должно начинаться с латинской буквы или цифры и может содержать цифры, _ и -.
Получение данных
| Метод | Возвращает | Описание |
|---|---|---|
fetchOne() |
array|null |
Возвращает первую найденную строку. |
fetchAll() |
array |
Возвращает строки по условиям. |
fetchGroupedRepresentatives() |
array |
Возвращает одну представительную строку из каждой группы. |
fetchAllFrom() |
array |
Возвращает все строки таблицы. |
count() |
int |
Возвращает количество строк. |
countDistinct() |
int |
Возвращает количество уникальных значений столбца. |
fetchOne(string $table, array $where, array $columns = ['*'], ?array $order = null, array $jsonFields = []): ?array
$user = WSDB::fetchOne(
'user',
['id' => 7],
['id', 'login', 'email']
);Если строка не найдена, возвращается null.
fetchAll(string $table, array $where, array $columns = ['*'], ?array $order = null, ?int $limit = null, ?int $offset = null, array $jsonFields = []): array
$posts = WSDB::fetchAll(
table: 'post_news',
where: ['status' => 'publish'],
columns: ['id', 'title'],
order: ['publish_date' => 'DESC'],
limit: 20
);Условия обязательны. offset можно использовать только вместе с limit.
fetchGroupedRepresentatives(string $table, string $groupColumn, string $preferredColumn, mixed $preferredValue, array $where = [], array $columns = ['*'], ?array $order = null, ?int $limit = null, ?int $offset = null, array $jsonFields = []): array
Возвращает одну строку из каждой группы, отдавая предпочтение заданному значению:
$posts = WSDB::fetchGroupedRepresentatives(
table: 'post_news',
groupColumn: 'translation_key',
preferredColumn: 'language',
preferredValue: 'ru',
where: ['status' => 'publish'],
columns: ['id', 'title', 'language', 'translation_key'],
order: ['id' => 'DESC'],
limit: 20
);Сначала применяются условия where, затем строки объединяются по groupColumn. Если приоритетному значению соответствуют несколько строк, выбирается строка с наименьшим id среди них. Если совпадений нет, выбирается строка с наименьшим id во всей группе.
Таблица должна содержать столбец id. Сортировка, ограничение и смещение применяются к уже выбранным строкам. offset можно использовать только вместе с limit.
fetchAllFrom(string $table, array $columns = ['*'], ?array $order = null, array $jsonFields = []): array
Используйте этот метод для выборки без условий:
$languages = WSDB::fetchAllFrom(
'languages',
['id', 'code', 'name'],
['id' => 'ASC']
);count(string $table, array $where = []): int
$total = WSDB::count(
'page',
['status' => 'publish']
);Без условий подсчитываются все строки таблицы:
$total = WSDB::count('page');countDistinct(string $table, string $column, array $where = []): int
Возвращает количество уникальных значений столбца:
$total = WSDB::countDistinct(
'post_news',
'translation_key',
['status' => 'publish']
);Без условий проверяются все строки таблицы. Значения null при подсчёте не учитываются.
Условия
Простое значение проверяет равенство:
$where = ['status' => 'publish'];Поддерживаемые операторы:
| Оператор | Описание |
|---|---|
in |
Значение входит в список. |
like |
Сравнение через LIKE. |
> |
Больше. |
< |
Меньше. |
>= |
Больше или равно. |
<= |
Меньше или равно. |
!= |
Не равно. |
is-null |
Значение равно NULL. |
is-not-null |
Значение не равно NULL. |
json-search |
Поиск значения внутри JSON-массива. |
$pages = WSDB::fetchAll(
'page',
[
'status' => [
'in' => ['publish', 'draft'],
],
]
);Для объединения групп доступны $or и $and:
$users = WSDB::fetchAll(
'user',
[
'$or' => [
['role' => 'admin'],
['role' => 'editor'],
],
]
);Сортировка
Сортировка передаётся массивом поле => направление:
$order = [
'publish_date' => 'DESC',
'id' => 'ASC',
];Поддерживаются только ASC и DESC.
Выбор столбцов
По умолчанию возвращаются все столбцы. Для ограничения результата передайте список:
$page = WSDB::fetchOne(
'page',
['id' => 15],
['id', 'title', 'url']
);Для псевдонима используйте исходное поле => новое имя:
$page = WSDB::fetchOne(
'page',
['id' => 15],
[
'title' => 'name',
]
);Изменение данных
| Метод | Возвращает | Описание |
|---|---|---|
insert() |
int |
Добавляет строку и возвращает её идентификатор. |
update() |
int |
Обновляет строки и возвращает их количество. |
increment() |
int |
Увеличивает числовое значение и возвращает количество изменённых строк. |
upsert() |
int |
Добавляет или обновляет строку. |
delete() |
int |
Удаляет строки и возвращает их количество. |
insert(string $table, array $data): int
$id = WSDB::insert(
'user',
[
'login' => 'new-user',
'email' => 'user@example.com',
'role' => 'user',
]
);update(string $table, array $data, array $where): int
$updated = WSDB::update(
'page',
['status' => 'publish'],
['id' => 15]
);increment(string $table, string $column, array $where, int $amount = 1): int
Увеличивает значение числового столбца и возвращает количество изменённых строк:
$updated = WSDB::increment(
'post_news',
'views',
['id' => 15]
);По умолчанию значение увеличивается на 1. Другую величину можно передать через amount:
$updated = WSDB::increment(
'post_news',
'views',
['id' => 15],
5
);Изменение выполняется одним запросом без предварительного получения текущего значения. Если столбец содержит null, исходным значением считается 0.
Условия where обязательны. Значение amount должно быть больше 0; уменьшение значений метод не поддерживает.
upsert(string $table, array $data, array $update = []): int
$id = WSDB::upsert(
'options',
[
'type' => 'global',
'name' => 'sitename',
'value' => 'Мой сайт',
],
[
'value' => 'Мой сайт',
]
);Метод обновляет строку при конфликте уникального ключа.
delete(string $table, array $where): int
$deleted = WSDB::delete(
'page',
['id' => 15]
);Удаление без условий запрещено.
JSON-поля
Для преобразования JSON-полей в массивы передайте их через jsonFields:
$page = WSDB::fetchOne(
table: 'page',
where: ['id' => 15],
columns: ['id', 'meta'],
jsonFields: ['meta']
);Пустое значение преобразуется в пустой массив.
updateJson(string $table, string $jsonColumn, array $set, array $where): int
Обновляет отдельные значения JSON-поля:
$updated = WSDB::updateJson(
'user',
'meta',
[
'profile.name' => 'Иван',
'profile.phone' => '+375000000000',
],
['id' => 7]
);upsertJson(string $table, array $keyData, string $jsonColumn, array $jsonSet): int
Создаёт строку или обновляет отдельные значения JSON-поля:
$id = WSDB::upsertJson(
'options',
[
'type' => 'themes',
'name' => 'example',
],
'value',
[
'color' => '#1251b7',
]
);Массивы, переданные в обычные методы записи, автоматически сохраняются как JSON.
Транзакции
transaction(callable $callback): mixed
Выполняет несколько операций как единое целое:
$pageId = WSDB::transaction(function (Database $database) {
$pageId = $database->insert('page', ['title' => 'Новая страница', 'status' => 'draft']);
$database->insert('page_meta', ['page_id' => $pageId, 'name' => 'layout', 'value' => 'default']);
return $pageId;
});Если callback завершился успешно, транзакция сохраняется. Если возникло исключение, изменения отменяются, а исключение передаётся вызывающему коду.
Вложенные транзакции не поддерживаются. Изменение структуры таблиц внутри транзакции использовать нельзя.
Блокировка операций
withAdvisoryLock(string $name, int $timeout, callable $callback): mixed
Не позволяет нескольким процессам одновременно выполнять одну операцию:
$result = WSDB::withAdvisoryLock('product-import', 10, function (Database $database) {
return $database->fetchAllFrom('products');
});$timeout задаёт время ожидания блокировки в секундах. Блокировка освобождается после завершения callback, в том числе при возникновении исключения.
Имя блокировки должно содержать от 1 до 64 латинских букв, цифр или символов _, ., :, -.
Информация о базе данных
| Метод | Возвращает | Описание |
|---|---|---|
getPrefix() |
string |
Возвращает префикс таблиц подключения. |
getServerVersion() |
string |
Возвращает версию сервера базы данных. |
listTables() |
array |
Возвращает список таблиц. |
describeTable(string $table) |
array |
Возвращает описание столбцов таблицы. |
showIndexes(string $table) |
array |
Возвращает индексы таблицы. |
tableExists(string $table) |
bool |
Проверяет существование таблицы. |
columnExists(string $table, string $column) |
bool |
Проверяет существование столбца. |
indexExists(string $table, string $index) |
bool |
Проверяет существование индекса. |
Имена таблиц передаются без системного префикса:
if (WSDB::tableExists('page')) {
$columns = WSDB::describeTable('page');
}Префикс таблиц
Передавайте имя таблицы без системного префикса:
$page = WSDB::fetchOne('page', ['id' => 15]);Префикс текущего подключения добавляется автоматически.
Исключения
| Исключение | Когда возникает |
|---|---|
InvalidArgumentException |
Передано недопустимое имя, пустые данные или неверный аргумент запроса. |
LogicException |
Подключение отсутствует, уже зарегистрировано или выполняется вложенная транзакция либо блокировка. |
RuntimeException |
Не удалось подключиться, завершить транзакцию или получить блокировку. |
BadMethodCallException |
Через WSDB вызван неизвестный метод Database. |
PDOException |
Сервер базы данных отклонил запрос. |
JsonException |
Переданное значение невозможно преобразовать в JSON. |
Важные замечания
- не создавайте экземпляр
WSDB - основное подключение регистрируется CMS автоматически
- статические методы используют основное подключение
- для дополнительного подключения используйте
WSDB::on($name) fetchOne(),fetchAll(),update(),increment()иdelete()требуют непустые условия- для получения всех строк используйте
fetchAllFrom() count()без условий подсчитывает все строки таблицы- значения запросов передаются через подготовленные выражения
- имена таблиц и столбцов должны задаваться разработчиком