Введение
Этот документ описывает синтаксис для выполнения запросов к нашему API, позволяя вам динамически фильтровать, сортировать, группировать и пагинировать данные. Используйте навигацию слева для изучения различных возможностей.
Базовая структура URL
Запросы отправляются на эндпоинты вида:
- `http://myapi.org/api/list/{resource_name}` - получить список записей
- `http://myapi.org/api/count/{resource_name}` - подсчитать записи по фильтрам
- `http://myapi.org/api/read/{resource_name}/{id}` - получить одну запись
- `http://myapi.org/api/create/{resource_name}` - создать запись
- `http://myapi.org/api/update/{resource_name}/{id}` - обновить запись
- `http://myapi.org/api/update/{resource_name}/{item}/{field}` - обновить вложенный фрагмент JSON
- `http://myapi.org/api/delete/{resource_name}/{id}` - удалить запись
- `http://myapi.org/api/save/{resource_name}` - создать или обновить запись
- `http://myapi.org/api/save/{resource_name}/{item}` - upsert по ID
- `http://myapi.org/api/save/{resource_name}/{item}/{field}` - upsert вложенного фрагмента (поля тела относительно `{field}`)
Поддержка GET и POST
API поддерживает как GET, так и POST запросы. Для сложных запросов рекомендуется использовать POST с JSON телом.
Использование API в PHP коде
Класс Api предоставляет удобные методы для работы с базой данных напрямую из PHP кода, без необходимости делать HTTP запросы.
Инициализация API
Создайте экземпляр класса Api для работы с базой данных:
<?php
require_once __DIR__ . '/api/api.php';
$api = new Api();
// API автоматически загружает настройки из api.json
// и подключает драйвер базы данных, указанный в конфигурации
?>💡 Важно!
- • Драйвер подключается автоматически на основе настройки
driverвapi.json - • Поддерживается динамическое подключение драйверов (mysql, postgresql и т.д.)
- • Драйвер инициализируется при первом использовании (lazy loading)
CRUD методы
Класс Api предоставляет следующие методы для работы с данными:
📋 list() - Получить список записей
<?php
$api = new Api();
// Простой список
$users = $api->list([
'@table' => 'users',
'status' => 'active',
'@limit' => 10
]);
// С фильтрацией и сортировкой
$orders = $api->list([
'@table' => 'orders',
'status' => 'pending',
'@order' => 'created_at:desc',
'@page' => 1,
'@size' => 20
]);
// С JOIN
$ordersWithUsers = $api->list([
'@table' => 'orders',
'@join' => ['left:users[orders.user_id=users.id]'],
'@return' => 'orders.id,orders.total,users.name:customer_name',
'@order' => 'orders.created_at:desc'
]);
?>👁️ read() - Получить одну запись
<?php
$api = new Api();
// По ID
$user = $api->read([
'@table' => 'users',
'id' => 'user123'
]);
// С дополнительными полями
$user = $api->read([
'@table' => 'users',
'id' => 'user123',
'@return' => 'id,name,email,profile.avatar,settings.theme'
]);
// Если id не указан, используется из маршрута (если доступен)
$api->route = ['item' => 'user123', 'table' => 'users'];
$user = $api->read();
?>🔗 apiRequest() - Запрос по URL (внутренний вызов без HTTP)
Выполняет запрос по строке URL эндпоинта, без HTTP — удобно для вызова из того же приложения (шаблоны, тег <variable>, контроллеры). Поддерживаются list, read, delete. create/update/save не поддерживаются (нужно тело запроса).
Форматы URL: /api/list/{table}?... → list(); /api/count/{table}?... → count(); /api/read/{table}/{id} → read(); /api/delete/{table}/{id} → delete(). Возвращает массив или null.
<?php
$api = new Api();
// Список по URL
$roles = $api->apiRequest('/api/list/users?type=role&@size=100&@order=name:asc');
// Одна запись по URL
$page = $api->apiRequest('/api/read/pages/123');
$users = $api->apiRequest('api/list/users?status=active');
// Удаление по URL
$result = $api->apiRequest('/api/delete/users/123');
?>➕ create() - Создать запись
<?php
$api = new Api();
// Создание с простыми полями
$newUser = $api->create([
'@table' => 'users',
'@set' => [
'name' => 'Иван Иванов',
'email' => 'ivan@example.com',
'status' => 'active'
],
'@return' => 'id,name,email,created_at'
]);
// Создание с вложенными JSON полями
$newUser = $api->create([
'@table' => 'users',
'@set' => [
'name' => 'Иван Иванов',
'email' => 'ivan@example.com',
'profile.avatar' => 'https://example.com/avatar.jpg',
'profile.bio' => 'Разработчик',
'settings.theme' => 'dark',
'settings.notifications.email' => true
],
'@return' => 'id,name,email,profile,settings'
]);
?>✏️ update() - Обновить запись
<?php
$api = new Api();
// Обновление по ID
$result = $api->update([
'@table' => 'users',
'id' => 'user123',
'@set' => [
'status' => 'inactive',
'last_login' => date('Y-m-d H:i:s')
],
'@return' => 'id,name,status,last_login'
]);
// Массовое обновление с условиями
$result = $api->update([
'@table' => 'users',
'last_login(lt)' => '2024-01-01',
'status' => 'active',
'@set' => [
'status' => 'inactive',
'deactivated_at' => date('Y-m-d H:i:s')
]
]);
// Обновление JSON полей
$result = $api->update([
'@table' => 'users',
'id' => 'user123',
'@set' => [
'profile.avatar.url' => 'https://new-avatar.jpg',
'profile.bio' => 'Новая биография',
'settings.theme' => 'light'
]
]);
?>🗑️ delete() - Удалить запись
<?php
$api = new Api();
// Удаление по ID
$result = $api->delete([
'@table' => 'users',
'id' => 'user123'
]);
// Массовое удаление с условиями
$result = $api->delete([
'@table' => 'users',
'status' => 'inactive',
'last_login(lt)' => '2020-01-01'
]);
// Удаление с возвратом удаленных записей
$result = $api->delete([
'@table' => 'users',
'id' => 'user123',
'@return' => 'id,name,email'
]);
?>💾 save() - Создать или обновить
<?php
$api = new Api();
// Если запись с таким ID существует - обновит, иначе создаст
$result = $api->save([
'@table' => 'users',
'@set' => [
'id' => 'user123',
'name' => 'Иван Иванов',
'email' => 'ivan@example.com',
'status' => 'active'
],
'@return' => 'id,name,email,created_at,updated_at'
]);
// Без ID - всегда создаст новую запись
$result = $api->save([
'@table' => 'users',
'@set' => [
'name' => 'Новый пользователь',
'email' => 'new@example.com'
]
]);
?>Метод save() автоматически определяет, нужно ли создавать новую запись или обновлять существующую на основе наличия ID и его существования в базе данных.
Логические операции (OR и AND)
Синтаксис GET/POST, таблицы и сценарии — в разделе «Логические операции». Ниже — примеры для PHP API.
🔀 Использование @or (ИЛИ)
Оператор @or позволяет найти записи, которые соответствуют хотя бы одному из условий.
<?php
$api = new Api();
// Найти пользователей со статусом "active" ИЛИ ролью "admin"
$users = $api->list([
'@table' => 'users',
'@or' => [
['status' => 'active'],
['role' => 'admin']
]
]);
// Более сложный пример: активные пользователи ИЛИ администраторы ИЛИ модераторы
$users = $api->list([
'@table' => 'users',
'@or' => [
['status' => 'active'],
['role' => 'admin'],
['role' => 'moderator']
],
'@order' => 'created_at:desc'
]);
// Комбинация с другими условиями
$users = $api->list([
'@table' => 'users',
'department' => 'IT', // Всегда должно быть выполнено
'@or' => [
['status' => 'active'],
['role' => 'admin']
]
]);
?>🔗 Использование @and (И)
Оператор @and позволяет явно указать, что все условия должны быть выполнены одновременно.
<?php
$api = new Api();
// Найти пользователей со статусом "active" И возрастом больше 18
$users = $api->list([
'@table' => 'users',
'@and' => [
['status' => 'active'],
['age(gt)' => 18]
]
]);
// Несколько условий с разными операторами
$users = $api->list([
'@table' => 'users',
'@and' => [
['status' => 'active'],
['age(gte)' => 18],
['age(lte)' => 65],
['city(in)' => ['Moscow', 'SPB']]
]
]);
?>Эквивалентный компактный формат: '@and' => ['date(gt)' => '...', 'date(lt)' => '...'] — то же самое, что канонический [['date' => ['gt' => '...']], ...].
🔀🔗 Комбинирование @or и @and
Вы можете создавать сложные вложенные структуры, комбинируя @or и @and.
<?php
$api = new Api();
// Найти пользователей, которые:
// (статус = "active" ИЛИ роль = "admin") И отдел = "IT"
$users = $api->list([
'@table' => 'users',
'@and' => [
[
'@or' => [
['status' => 'active'],
['role' => 'admin']
]
],
['department' => 'IT']
]
]);
// Более сложный пример:
// (статус = "active" ИЛИ роль = "admin")
// И
// (возраст >= 18 И возраст <= 65)
$users = $api->list([
'@table' => 'users',
'@and' => [
[
'@or' => [
['status' => 'active'],
['role' => 'admin']
]
],
[
'@and' => [
['age(gte)' => 18],
['age(lte)' => 65]
]
]
]
]);
// Использование в update() с условиями
$result = $api->update([
'@table' => 'users',
'@and' => [
[
'@or' => [
['status' => 'active'],
['status' => 'pending']
]
],
['last_login(lt)' => '2024-01-01']
],
'@set' => [
'status' => 'inactive',
'deactivated_at' => date('Y-m-d H:i:s')
]
]);
// Использование в delete() с условиями
$result = $api->delete([
'@table' => 'users',
'@or' => [
['status' => 'deleted'],
['last_login(lt)' => '2020-01-01']
]
]);
?>💡 Важные моменты:
- • По умолчанию все условия объединяются через
AND, если не указан@or - •
@andполезен для явного указания логики, особенно при комбинации с@or - • Можно создавать многоуровневые вложенные структуры
- • Логические операторы работают во всех CRUD методах:
list(),read(),update(),delete()
Работа с драйверами и подключениями
В настройках можно задать несколько именованных подключений. У каждого указывается type (mysql, json, mongodb) и параметры. Поле driver в корне — имя подключения по умолчанию.
Пример api.json (несколько подключений):
{
"driver": "mysql",
"drivers": {
"mysql": {
"type": "mysql",
"host": "localhost",
"port": 3306,
"database": "mydb",
"username": "user",
"password": "pass"
},
"json": {
"type": "json",
"database_path": "/path/to/json",
"allowed_tables": []
}
}
}💡 Как это работает:
- • Подключение по умолчанию задаётся в
"driver" - • В запросе можно указать
@driverили@dbдля выбора подключения - • Файл драйвера загружается по полю
typeподключения:drivers/{type}.php - • Экземпляр драйвера кэшируется по имени подключения
Практические примеры
Пример 1: Получение данных с фильтрацией
<?php
$api = new Api();
// Получить активных пользователей за последний месяц
$activeUsers = $api->list([
'@table' => 'users',
'status' => 'active',
'created_at(gte)' => date('Y-m-01'),
'@order' => 'created_at:desc',
'@page' => 1,
'@size' => 50
]);
foreach ($activeUsers as $user) {
echo $user['name'] . " - " . $user['email'] . "\n";
}
?>Пример 2: Создание записи с валидацией
<?php
$api = new Api();
// Проверить, существует ли пользователь
$existingUser = $api->read([
'@table' => 'users',
'email' => 'ivan@example.com'
]);
if (!$existingUser) {
// Создать нового пользователя
$newUser = $api->create([
'@table' => 'users',
'@set' => [
'name' => 'Иван Иванов',
'email' => 'ivan@example.com',
'status' => 'active'
]
]);
echo "Пользователь создан: " . $newUser['id'];
} else {
echo "Пользователь уже существует";
}
?>Пример 3: Использование save() для upsert
<?php
$api = new Api();
// Автоматически создаст или обновит запись
$result = $api->save([
'@table' => 'users',
'@set' => [
'id' => 'user123',
'name' => 'Иван Иванов',
'email' => 'ivan@example.com',
'last_seen' => date('Y-m-d H:i:s')
]
]);
// Не нужно проверять существование - save() сделает это сам
?>Пример 4: Работа с JOIN
<?php
$api = new Api();
// Получить заказы с информацией о пользователях
$orders = $api->list([
'@table' => 'orders',
'@join' => ['left:users[orders.user_id=users.id]'],
'@return' => 'orders.id,orders.total,orders.created_at,users.name:customer_name,users.email:customer_email',
'orders.status' => 'completed',
'@order' => 'orders.created_at:desc',
'@page' => 1,
'@size' => 20
]);
foreach ($orders as $order) {
echo "Заказ #{$order['id']} от {$order['customer_name']} на сумму {$order['total']}\n";
}
?>Пример 5: Массовые операции
<?php
$api = new Api();
// Обновить статус всех неактивных пользователей
$result = $api->update([
'@table' => 'users',
'status' => 'active',
'last_login(lt)' => '2024-01-01',
'@set' => [
'status' => 'inactive',
'deactivated_at' => date('Y-m-d H:i:s')
]
]);
echo "Обновлено записей: " . ($result['affected'] ?? 0);
// Удалить старые записи
$result = $api->delete([
'@table' => 'logs',
'created_at(lt)' => date('Y-m-d', strtotime('-1 year'))
]);
echo "Удалено записей: " . ($result['affected'] ?? 0);
?>Преимущества использования PHP методов
- ✅ Нет HTTP overhead - прямые вызовы методов без сетевых запросов
- ✅ Типобезопасность - IDE подсказки и проверка типов
- ✅ Производительность - быстрее чем HTTP запросы
- ✅ Удобство отладки - можно использовать отладчик PHP
- ✅ Единый код - один и тот же API для HTTP и PHP вызовов
- ✅ Автоматический парсинг - запросы парсятся автоматически
- ✅ Несколько подключений — в запросах можно указывать
@driverили@dbдля выбора подключения
Подключения и алиасы таблиц
API поддерживает несколько именованных подключений к базам данных, подключение по умолчанию и алиасы таблиц для маршрутизации запросов.
Несколько подключений (Database)
В настройках (раздел Database) можно добавить несколько подключений с произвольными именами (например mysql, json, mysql_db2). У каждого подключения задаётся тип (MySQL, JSON, MongoDB) и параметры. Одно из подключений выбирается как Default connection — оно используется, если в запросе не указан @driver/@db и таблица не найдена в алиасах.
Параметры @driver и @db
Чтобы явно выбрать подключение в запросе, укажите его имя:
@driver=имя_подключения— выбор подключения@db=имя_подключения— то же самое (синоним)
GET /api/list/users?@driver=json
GET /api/list/pages?@db=mysql_db2Если указан @driver или @db, алиасы таблиц не применяются.
Алиасы таблиц (Aliases)
В разделе Aliases настраивается соответствие: имя алиаса → подключение + таблица. При запросе с @table=алиас API обращается к указанному подключению и таблице. Если алиаса нет и не задан @driver/@db, используется подключение по умолчанию и имя таблицы как есть.
Пример:
Алиас jUsers → подключение json, таблица users. Запрос GET /api/list/jUsers вернёт данные из таблицы users в JSON-подключении.
Быстрый старт
Пошаговое руководство по подключению API к вашему проекту.
Шаг 1: Клонирование репозитория
Клонируйте репозиторий API на ваш сервер:
git clone https://gitflic.ru/project/digiport/api.gitИли добавьте как подмодуль в существующий проект:
git submodule add https://gitflic.ru/project/digiport/api.git apiСтруктура файлов после клонирования:
project/
├── api/
│ ├── api.php # Точка входа
│ ├── api_parser.php # Парсер запросов
│ ├── drivers/
│ │ └── mysql.php # MySQL драйвер
│ ├── api_router.php # Роутер
│ ├── api_settings.php # Веб-интерфейс настроек
│ ├── api_help.php # Эта документация
│ ├── api.ini # Маршруты
│ └── api.json # Настройки пакета api (fallback)
├── database/
│ └── api.json # Настройки проекта (создастся автоматически)
└── index.php # Ваше приложение⚠️ Требования:
- Убедитесь, что веб-сервер имеет доступ к файлам API
- Проверьте права на запись для файла
database/api.json(хранит настройки проекта) - PHP версии 7.4 или выше
Шаг 2: Подключение в вашем проекте
Добавьте следующий код в самое начало вашего основного файла (например, index.php):
require_once __DIR__ . '/api/api.php';
$api = new Api();
$api->run();
// Далее сод вашего приложения
💡 Важно!
- • Код должен быть добавлен в самом начале файла, до любого вывода HTML
- • API обрабатывает только запросы к
/api/* - • Если запрос не к API, выполнение продолжается дальше в вашем коде
- • Не нужен закрывающий тег
?>в конце файла
Шаг 3: Настройка через веб-интерфейс
- Откройте в браузере:
http://ваш-сайт.com/api/settings - При первом входе используйте дефолтный пароль:
password⚠️ Важно!
После первого входа обязательно смените пароль на безопасный в разделе "Tokens" → "Web Interface Password".
- В разделе Database (Connections) добавьте одно или несколько подключений (имя, тип: MySQL/JSON/MongoDB, параметры). Выберите Default connection. При необходимости в разделе Aliases настройте алиасы таблиц (имя алиаса → подключение + таблица).
- Нажмите кнопку "Save Settings" для сохранения настроек
Шаг 4: Первый запрос
Проверьте работу API, выполнив простой запрос:
GET http://ваш-сайт.com/api/list/users?@limit=10Или используйте cURL:
curl http://ваш-сайт.com/api/list/users?@limit=10🔒 Если API защищен токеном:
curl -H "Authorization: Bearer YOUR_TOKEN" \
http://ваш-сайт.com/api/list/users?@limit=10Шаг 5: Обновление кода
Для обновления API до последней версии выполните:
cd api
git pull origin masterЕсли используете подмодуль:
git submodule update --remote api💡 Рекомендация:
Перед обновлением сделайте резервную копию файла api.json с настройками,
так как обновление может изменить структуру конфигурации.
✅ Готово!
Теперь ваш API полностью настроен. Настройте подключения и алиасы и токены в панели настроек.
Аутентификация
Токен передаётся только в HTTP-заголовке Authorization: Bearer. Параметр @token в URL или JSON не принимается.
Bearer Token
Authorization: Bearer YOUR_SECRET_TOKENcurl -H "Authorization: Bearer YOUR_SECRET_TOKEN" \
https://ваш-сайт.com/api/list/usersJavaScript (fetch):
fetch('/api/list/users?@limit=10', {
headers: { Authorization: 'Bearer YOUR_SECRET_TOKEN' }
});Управление API
Раздел Security позволяет настроить пароль веб-интерфейса, HTTPS и токены доступа с правами по умолчанию и переопределениями по таблицам.
Создание токена через веб-интерфейс
-
Откройте панель управления:
http://ваш-сайт.com/api/settings - Перейдите в раздел Security (Tokens) в боковом меню
-
Включите защиту API (переключатель "Protect API access with tokens")
Если защита отключена, API доступен без токена
- Нажмите "+ Add Token" для создания нового токена
-
Заполните параметры токена:
- Token name — имя для идентификации (например, "Mobile App", "Frontend")
- Token — сам токен (кнопка 🔄 для автогенерации)
- Default — общие права по умолчанию для всех таблиц: C Create, R Read, U Update, D Delete, S Save, L List
- Table-specific permissions — при необходимости задайте переопределения прав для отдельных таблиц (например, для таблицы
usersтолько L). Если переопределения нет, используются права по умолчанию
- Нажмите "Save Settings" для сохранения изменений
💡 Пример:
Имя: "Mobile App"
Default: R, L (чтение и список)
Переопределение: для таблицы users — только L
Получение токена программно
Вы можете получить токен из настроек API в вашем PHP коде:
<?php
require_once __DIR__ . '/api/api.php';
$api = new Api();
// Получить токен по имени
$token = $api->getToken('Mobile App Token');
if ($token) {
echo "Token: " . $token['value'] . "\n";
echo "Access: " . implode(', ', $token['access']) . "\n";
} else {
echo "Token not found\n";
}
?>Результат:
Token: abc123xyz456def789...
Access: r, lИспользование токена в запросах
Только заголовок Authorization: Bearer:
curl -H "Authorization: Bearer YOUR_SECRET_TOKEN" \
https://ваш-сайт.com/api/list/usersОграничение доступа к таблицам
Токены можно ограничить конкретными таблицами для повышения безопасности:
✅ Токен с доступом к users
GET /api/list/users
→ ✅ Разрешено❌ Токен без доступа к orders
GET /api/list/orders
→ ❌ 403 Access denied⚠️ Важно:
Если список таблиц пуст, токен имеет доступ ко ВСЕМ таблицам (с учетом разрешений C/R/U/D/S/L).
Примеры разрешений токенов
📱 Мобильное приложение
Разрешения: R, L (только чтение)
Таблицы: users, products, categories
🖥️ Панель администратора
Разрешения: C, R, U, D, S, L (полный доступ)
Таблицы: все (список пуст)
📊 Сервис аналитики
Разрешения: L (только списки)
Таблицы: orders, analytics
⚙️ Внешняя интеграция
Разрешения: C, U, S (создание и обновление)
Таблицы: webhooks, sync_log
🔐 Безопасность токенов
- Храните токены в безопасном месте (переменные окружения, защищенные конфиги)
- Параметр
@tokenв URL и JSON не принимается — только заголовокAuthorization: Bearer - Регулярно меняйте токены для критичных систем
- Используйте разные токены для разных приложений
- Настраивайте минимальные необходимые разрешения (принцип наименьших привилегий)
Действия (CRUD операции)
API поддерживает полный набор CRUD операций для работы с данными.
LIST - Получение списка
Получить список записей с фильтрацией, сортировкой и пагинацией.
GET /api/list/users?status=active&@page=1&@size=10COUNT - Подсчёт записей
Подсчитать количество записей по тем же фильтрам, что у list, без загрузки списка. Право токена: l (как у list).
GET /api/count/classes?private=false&@or=(status=opened,status=closed)Ответ: {"count": 182}
Уникальные значения поля: @distinct=email. Группировка: @group + агрегаты в @return (@supress включается автоматически).
GET /api/count/orders?@group=status&@return=status,@count(id):total@query — экспорт запроса в PHP
Модификатор отладки: не выполняет запрос, возвращает только PHP-код в <pre> (HTML).
GET /api/count/classes?private=false&@or=(status=opened,status=closed)&@query=1Из PHP $api->count([..., '@query' => 1]) — строка с тем же кодом. Работает с list, count, read, create, update, delete, save.
READ - Чтение одной записи
Получить одну запись по ID.
GET /api/read/users/user123CREATE - Создание записи
Создать новую запись. Данные передаются через параметр @set или в теле POST запроса.
Способ 1: POST запрос с JSON телом
POST /api/create/users
Content-Type: application/json
{
"@set": {
"name": "Иван Иванов",
"email": "ivan@example.com",
"role": "user"
},
"@return": "id,name,email,created_at"
}Способ 2: GET запрос с параметром @set
Для быстрого создания можно использовать GET запрос:
GET /api/create/users?@set=name=Иван%20Иванов&email=ivan@example.com&role=user&@return=id,name,email,created_atСпособ 3: GET с @set в квадратных скобках
Более читаемый вариант с использованием квадратных скобок:
GET /api/create/users?@set=[name=John%20Doe&email=john@example.com&role=admin]&@return=id,name,emailСоздание с вложенными JSON полями через GET
GET /api/create/users?@set=name=John&email=john@test.com&profile.avatar=https://example.com/pic.jpg&profile.bio=Developer&settings.theme=dark&@return=id,name,profile,settingsТо же самое с использованием квадратных скобок:
GET /api/create/users?@set=[name=John&email=john@test.com&profile.avatar=https://example.com/pic.jpg&profile.bio=Developer&settings.theme=dark]&@return=id,name,profile,settings💡 Параметр @return указывает, какие поля вернуть после создания.
UPDATE - Обновление записи
Обновить существующую запись. Можно обновлять по ID или по условию.
Способ 1: POST запрос с JSON телом
POST /api/update/users/user123
{
"@set": {
"status": "inactive",
"updated_at": "2025-11-11"
},
"@return": "id,name,status"
}Способ 2: GET запрос с множественными @set
Для простых обновлений можно использовать GET запрос:
GET /api/update/users/user123?@set=status=inactive&@set=last_login=2025-11-11&@return=id,name,statusСпособ 3: GET запрос с объединенным @set
Можно передать несколько полей в одном параметре @set, разделяя их через &:
GET /api/update/users/user123?@set=status=inactive&updated_at=2025-11-11&@return=id,name,statusСпособ 4: GET запрос с @set в квадратных скобках (рекомендуется)
Квадратные скобки улучшают читаемость и чётко отделяют параметры @set от других:
GET /api/update/users/user123?@set=[status=inactive&updated_at=2025-11-11]&@return=id,name,statusПример с токенами (ваш случай):
GET /api/update/users/user123?@set=[firebaseToken=abc123&mobileFirebaseToken=xyz789]&@return=id,firebaseToken,mobileFirebaseTokenОбновление JSON полей через GET
Используйте dot notation для вложенных полей:
GET /api/update/users/user123?@set=profile.avatar.url=https://new-avatar.jpg&profile.bio=Новая%20биография&@return=id,profileПримечание
Для массового обновления используйте условия без указания ID в URL. Для сложных обновлений рекомендуется использовать POST запросы.
DELETE - Удаление записи
Удалить запись по ID или по условию.
DELETE /api/delete/users/user123Для массового удаления используйте POST с условиями фильтрации.
SAVE - Создание или обновление
Автоматически создает запись, если ID не существует, или обновляет существующую.
POST /api/save/users
{
"@set": {
"id": "user123",
"name": "Обновленное имя"
}
}Сохранение вложенного JSON по URL
Сегмент {field} задаёт срез записи: поля из тела получают префикс {field}. Вложенный объект заменяется целиком.
POST /api/save/settings/modules/courses
{
"courses": [{"id": 1, "name": "Курс A"}],
"expert": true,
"time": 60
}В формах engine: <data table="settings" item="modules" field="courses"> и action="/api/save/settings/modules/courses".
Параметр @set для CREATE/UPDATE
Параметр @set содержит данные для создания или обновления записи. Поддерживает dot notation для вложенных JSON полей: `profile.avatar.url`.
Синтаксис @set в GET запросах:
- Простой: `@set=field1=value1&field2=value2`
- В квадратных скобках: `@set=[field1=value1&field2=value2]`
- Множественный: `@set=field1=value1&@set=field2=value2`
- С dot notation: `@set=profile.name=John&profile.age=30`
- Dot notation в скобках: `@set=[profile.name=John&profile.age=30]`
- Комбинированный: `@set=name=John&profile.avatar=url&status=active`
💡 Квадратные скобки автоматически удаляются при парсинге. Используйте их для лучшей читаемости URL-запросов.
Синтаксис @set в POST запросах:
Условия
Вы можете фильтровать данные, указывая условия для отдельных полей. Условия можно передавать как в GET-запросах (через URL параметры), так и в POST-запросах (через JSON тело). Общий синтаксис: `field(operator)=value`. Если оператор не указан, по умолчанию используется `eq` (равно).
GET-запросы (URL параметры)
Условия передаются через URL параметры. Удобно для простых запросов и тестирования в браузере.
GET /api/users?status=active&age(gt)=18&name(like)=%john%POST-запросы (JSON тело)
Условия передаются в JSON теле запроса. Позволяет передавать сложные структуры данных.
{
"status": "active",
"age(gt)": 18,
"name(like)": "%john%"
}
Доступные операторы
| Оператор | Описание | GET пример | POST пример |
|---|---|---|---|
| `eq` (или нет) | Равно | status=active |
"status": "active" |
| `ne` | Не равно | status(ne)=archived |
"status(ne)": "archived" |
| `gt` | Больше | amount(gt)=100 |
"amount(gt)": 100 |
| `lt` | Меньше | price(lt)=50 |
"price(lt)": 50 |
| `gte` | Больше или равно | date(gte)=2025-01-01 |
"date(gte)": "2025-01-01" |
| `lte` | Меньше или равно | date(lte)=2025-12-31 |
"date(lte)": "2025-12-31" |
| `in` | Входит в список | role(in)=[admin,moderator] |
"role(in)": ["admin", "moderator"] |
| `not_in` | Не входит в список | category(not_in)=[spam,deleted] |
"category(not_in)": ["spam", "deleted"] |
| `contains` / `has` | Поле (массив/JSON) содержит значение | tags(contains)=important или tags(has)=important |
"tags(contains)": "important" или "tags(has)": "important" |
| `not_contains` / `not_has` | Поле не содержит значение | tags(not_contains)=spam |
"tags(not_contains)": "spam" |
| `between` | Между диапазоном | date(between)=[2025-07-01,2025-07-08] |
"date(between)": ["2025-07-01", "2025-07-08"] |
| `like` | Похож (сопоставление по шаблону) | name(like)=%book% |
"name(like)": "%book%" |
| `is_null` | Равен NULL | last_login(is_null)=true |
"last_login(is_null)": true |
| `not_null` | Не равен NULL | description(not_null)=true |
"description(not_null)": true |
| `empty` | Пустое значение (NULL, пустая строка, пустой массив) | email(empty)=true |
"email(empty)": true |
| `not_empty` | Не пустое значение | avatar(not_empty)=true |
"avatar(not_empty)": true |
| `not_between` | Не между диапазоном | date(not_between)=[2025-01-01,2025-06-30] |
"date(not_between)": ["2025-01-01", "2025-06-30"] |
| `not_like` | Не похож (исключение по шаблону) | name(not_like)=%test% |
"name(not_like)": "%test%" |
Инверсия предикатов через =false
Булевые операторы (empty, not_empty, is_null, not_null): =false инвертирует оператор и трактуется как true.
GET /api/list/members?image(empty)=false
GET /api/list/members?image=(empty)=falseОператоры со значением: синтаксис field(op=value)=false — значение сохраняется, оператор инвертируется (like↔not_like, in↔not_in, contains↔not_contains, between↔not_between).
GET /api/list/users?name(like=%ivan%)=false
GET /api/list/members?@or=(teacher=true,admin=true)&active=trueБулевы JSON-поля в @or нормализуются в строки "true"/"false" для корректного сравнения в MySQL.
Полные примеры запросов
GET-запрос с несколькими условиями
Находит активных пользователей от 18 до 65 лет из Москвы или СПб, чьё имя содержит "john".
GET /api/users?status=active&age(gte)=18&age(lte)=65&city(in)=[Moscow,SPB]&name(like)=%john%POST-запрос с несколькими условиями
Тот же запрос, но через POST с JSON телом.
{
"status": "active",
"age(gte)": 18,
"age(lte)": 65,
"city(in)": ["Moscow", "SPB"],
"name(like)": "%john%"
}
Логические операции
Операторы @and и @or объединяют условия фильтрации. Работают в list, count, read, update, delete и при явном @where в save.
AND по умолчанию
Все параметры на верхнем уровне URL или JSON связаны через AND. Каждое условие должно выполняться одновременно.
GET /api/list/users?status=active&department=IT&age(gte)=18→ status = active И department = IT И age ≥ 18
Когда что использовать
| Задача | Решение |
|---|---|
| A и B и C | A=v1&B=v2&C=v3 |
| A или B или C | @or=(A,B,C) |
| (A или B) и C | @or=(A,B)&C=v |
| Глубокая вложенность | POST JSON или PHP-массив |
GET-запросы
Внутри @or=(...) или @and=(...) условия разделяются запятой или &. Значения в [...] не разбиваются.
Простое ИЛИ
GET /api/list/users?@or=(status=active,role=admin)ИЛИ + обязательное условие (частый паттерн)
GET /api/list/users?@or=(status=active,role=admin)&department=IT→ (status = active OR role = admin) AND department = IT
Разные поля и операторы
GET /api/list/members?active=true&@or=(teacher=true,admin=true)
GET /api/list/users?@or=(age(lt)=18,age(gt)=65)&status=active
GET /api/count/classes?private=false&@or=(status=opened,status=closed)Предикаты empty и инверсия =false
GET /api/list/users?@or=(profile.avatar(empty)=true,profile.bio(empty)=true)&status=active
GET /api/list/members?image(empty)=false
GET /api/list/users?@or=(name(like=%test%)=false,city(ne)=archive)in vs @or
Для одного поля с несколькими значениями короче in:
GET /api/list/orders?status(in)=[pending,processing]
# эквивалент:
GET /api/list/orders?@or=(status=pending,status=processing)@or нужен, когда условия на разных полях или с разными операторами.
POST-запросы (JSON)
Для вложенных структур и длинных условий. Поддерживаются канонический массив и компактный объект — оба нормализуются парсером.
Канонический формат
POST /api/list/users
{
"@and": [
{
"@or": [
{"status": "active"},
{"role": "admin"}
]
},
{"department": "IT"}
]
}Компактный формат
{
"@and": {
"@or": {
"status": "active",
"role": "admin"
},
"department": "IT"
}
}Булевы JSON-поля
POST /api/list/members
{
"active": true,
"@or": [
{"teacher": true},
{"admin": true}
]
}Сводка: GET ↔ POST
| Смысл | GET | POST |
|---|---|---|
| A или B | @or=(A,B) | "@or": [{"f1":"v1"}, {"f2":"v2"}] |
| (A или B) и C | @or=(A,B)&C=v | "@or":[...], "C":"v" |
| A и B и C | A=v1&B=v2 | "A":"v1", "B":"v2" |
Типичные сценарии
Массовый update по условию OR
POST /api/update/orders
{
"@or": [
{"status": "cancelled"},
{"due_date(lt)": "2025-01-01"}
],
"@set": {"status": "archived"}
}Массовый delete
POST /api/delete/sessions
{
"@or": [
{"expires_at(lt)": "2025-01-01"},
{"revoked": true}
]
}Dot notation внутри логики
GET /api/list/users?@or=(settings.theme=dark,settings.theme=auto)&profile.verified=truePHP API
Те же структуры в $api->list(), count(), update(), delete(). Раздел «Использование в PHP» содержит расширенные примеры вложенности.
$api->list([
'@table' => 'users',
'department' => 'IT',
'@or' => [
['status' => 'active'],
['role' => 'admin'],
],
]);Важные моменты
- Параметры верхнего уровня — всегда AND, если не сгруппированы в
@or. - Внутри
(...)разделители — запятая или&; между параметрами URL — только&. - Булевы JSON-поля в
@orнормализуются в строки"true"/"false"для MySQL. - Сложная многоуровневая вложенность — POST или PHP, не длинный GET.
countиспользует те же@or/@and, что иlist.- Инверсия предикатов
=falseработает внутри@or/@and— см. раздел «Условия».
Объединения (JOIN)
Параметр `@join` позволяет объединять данные из нескольких связанных таблиц в одном запросе, значительно упрощая работу с реляционными данными.
Базовый синтаксис
Параметр `@join` принимает массив строк, где каждая строка описывает одно присоединение:
Формат:
[тип]:[таблица][[условие_связи]]
Тип JOIN
inner, left, right, full
Таблица
Имя присоединяемой таблицы
Условие
Поля для связи таблиц
Простой пример:
@join=["left:users[orders.user_id=users.id]"]Присоединяет таблицу users к таблице orders по полю user_id
Типы JOIN
🔹 INNER JOIN (inner)
Возвращает только записи, для которых найдено совпадение в обеих таблицах.
@join=["inner:users[orders.user_id=users.id]"]Результат: Только заказы, у которых есть пользователь
🔹 LEFT JOIN (left)
Возвращает все записи из левой таблицы и совпадающие из правой. Если совпадений нет, поля правой таблицы будут NULL.
@join=["left:users[orders.user_id=users.id]"]Результат: Все заказы, даже если пользователь не найден (поля user будут NULL)
🔹 RIGHT JOIN (right)
Возвращает все записи из правой таблицы и совпадающие из левой.
@join=["right:users[orders.user_id=users.id]"]Результат: Все пользователи, даже без заказов
🔹 FULL JOIN (full)
Возвращает все записи из обеих таблиц, даже без совпадений.
@join=["full:users[orders.user_id=users.id]"]Результат: Все заказы и все пользователи
💡 Рекомендация:
Используйте LEFT JOIN в 90% случаев - это самый распространенный и безопасный тип объединения.
Множественные JOIN
Можно объединить несколько таблиц в одном запросе:
GET запрос:
GET /api/list/orders?@join=["left:users[orders.user_id=users.id]","inner:products[orders.product_id=products.id]"]&@return=orders.id,users.name:customer_name,products.name:product_namePOST запрос (рекомендуется для сложных JOIN):
POST /api/list/orders
Content-Type: application/json
{
"@join": [
"left:users[orders.user_id=users.id]",
"inner:products[orders.product_id=products.id]",
"left:categories[products.category_id=categories.id]"
],
"@return": "orders.id,users.name:customer,products.name:product,categories.name:category,orders.total"
}Результат: Заказы с данными пользователя, продукта и категории в одном запросе
Практические примеры
📱 Пример 1: Заказы с пользователями
Получить все заказы со статусом "pending" и информацией о пользователях:
GET /api/list/orders?status=pending&@join=["left:users[orders.user_id=users.id]"]&@return=orders.*,users.name,users.email&@order=orders.created_at:desc🛒 Пример 2: Продукты с категориями и производителями
Каталог продуктов с полной информацией:
POST /api/list/products
{
"@join": [
"left:categories[products.category_id=categories.id]",
"left:manufacturers[products.manufacturer_id=manufacturers.id]"
],
"@return": "products.id,products.name,products.price,categories.name:category,manufacturers.name:brand",
"products.status": "active",
"@order": "products.price:asc",
"@page": 1,
"@size": 20
}👥 Пример 3: Пользователи с количеством заказов
Список пользователей с статистикой их заказов:
POST /api/list/users
{
"@join": [
"left:orders[users.id=orders.user_id]"
],
"@return": "users.id,users.name,users.email,@count(orders.id):orders_count,@sum(orders.total):total_spent",
"@group": "users.id,users.name,users.email",
"@order": "total_spent:desc",
"@having": "orders_count(gt)=0"
}📊 Пример 4: Сложный JOIN с фильтрацией
Заказы за последний месяц с детализацией:
POST /api/list/orders
{
"@join": [
"left:users[orders.user_id=users.id]",
"left:products[orders.product_id=products.id]",
"left:payments[orders.id=payments.order_id]"
],
"@return": "orders.id,orders.created_at,users.name:customer,users.email,products.name:product,orders.total,payments.status:payment_status",
"@and": [
{"orders.created_at(gte)": "2025-10-01"},
{"orders.status": "completed"}
],
"@order": "orders.created_at:desc",
"@page": 1,
"@size": 50
}Работа с полями из JOIN таблиц
Фильтрация по полям JOIN таблиц:
POST /api/list/orders
{
"@join": ["left:users[orders.user_id=users.id]"],
"users.email(like)": "%@gmail.com",
"users.status": "active",
"@return": "orders.*,users.name,users.email"
}Сортировка по полям JOIN таблиц:
@join=["left:users[orders.user_id=users.id]"]&@order=users.name:asc,orders.created_at:descГруппировка с JOIN:
POST /api/list/orders
{
"@join": ["left:products[orders.product_id=products.id]"],
"@group": "products.id,products.name",
"@return": "products.name:product,@count(orders.id):total_orders,@sum(orders.total):revenue",
"@order": "revenue:desc"
}Выбор полей при использовании JOIN
Выбрать все поля из основной таблицы:
@return=orders.*,users.name,users.emailВыбрать все поля из всех таблиц:
@return=orders.*,users.*,products.*⚠️ Не рекомендуется - возвращает много данных
Выбрать конкретные поля с псевдонимами:
@return=orders.id:order_id,orders.total,users.name:customer_name,users.email:customer_email,products.name:product_title✅ Рекомендуется - явное указание нужных полей
Если @return (и запасной @select) не указаны:
API автоматически вернет все поля из всех таблиц (основной + все JOIN)
❌ Частые ошибки при работе с JOIN
1. Неправильный формат условия связи
❌ Неверно: @join=["left:users[user_id=id]"]
✅ Верно: @join=["left:users[orders.user_id=users.id]"]
Нужно указывать таблицу для каждого поля
2. Забыли указать @return
Без @return (и без запасного @select) вернутся все поля из всех таблиц, что может быть избыточно
3. Неправильный порядок JOIN
Порядок JOIN важен! Сначала присоединяйте таблицы первого уровня, потом второго
4. Дублирование имен полей
Если в разных таблицах есть поля с одинаковыми именами, используйте псевдонимы
✅ @return=orders.id:order_id,users.id:user_id
⚡ Советы по производительности
- ✅ Используйте
@returnдля выбора только нужных полей - ✅ Добавляйте индексы на поля, используемые в условиях JOIN
- ✅ Используйте фильтрацию для уменьшения количества данных до JOIN
- ✅ Предпочитайте INNER JOIN, если не нужны записи без совпадений
- ✅ Ограничивайте результаты с помощью
@limitили@page/@size - ⚠️ Избегайте JOIN более 4-5 таблиц в одном запросе
- ⚠️ Не используйте
table.*для всех JOIN таблиц одновременно
Поля ответа (@return)
Параметр @return — основной способ задать проекцию: какие столбцы попадают в запрос к данным и какие ключи получает клиент. Список полей задаётся через запятую; синтаксис тот же, что раньше у @select: псевдонимы источник:alias, агрегаты @count, @sum и т.д., пути к вложенным JSON через точку.
Если @return не указан, для обратной совместимости используется параметр @select с тем же форматом списка.
Основной синтаксис
@return=id,name,email,created_atПсевдонимы полей
Используйте двоеточие для переименования полей в ответе:
@return=id,name:full_name,email:contact_emailПоля из JOIN таблиц
@return=orders.id,users.name:user_name,products.name:product_nameАгрегатные функции
Используйте @ перед именем функции:
@return=category,@count(id):total,@sum(amount):total_amount,@avg(price):avg_priceДоступные функции: @count, @sum, @avg, @min, @max. С @group — агрегаты по каждой группе; с @supress на листе только объект-итог без массива записей.
Выбор всех полей таблицы
@return=users.*,orders.id,orders.totalПримечание
Если не заданы ни @return, ни запасной @select, возвращаются все поля основной таблицы и всех JOIN.
CREATE, UPDATE, DELETE, SAVE
В этих операциях @return задаёт, какие поля затронутой записи включить в ответ (подмножество доступных полей после операции).
Использование в CREATE
POST /api/create/users
{
"@set": {
"name": "Иван Иванов",
"email": "ivan@example.com"
},
"@return": "id,name,email,created_at"
}API вернет только указанные поля созданной записи.
Использование в UPDATE
POST /api/update/users
{
"status": "active",
"@set": {
"last_login": "2025-11-11"
},
"@return": "id,name,status,last_login"
}Возвращает только указанные поля всех обновленных записей.
Использование в LIST
GET /api/list/users?status=active&@return=id,name,emailФормат значения
Поля перечисляются через запятую (в теле POST — строка или массив, в зависимости от клиента):
@return=id,name,email,profile.avatar,created_atЗапасной параметр @select
- @return — приоритетный список проекции и ключей ответа для list/read и драйверов с SQL-подобной выборкой.
- @select — учитывается только если
@returnпустой или отсутствует; нужен для старых интеграций.
Рекомендация
В новых запросах всегда указывайте @return — так проще поддерживать клиент и контролировать объём данных.
Сортировка
Параметр `@order` (или `@sort`) упорядочивает результаты по одному или нескольким полям.
Простая сортировка
Сортировка по одному полю (по умолчанию по возрастанию):
@order=created_atУказание направления
Используйте `:asc` для возрастания или `:desc` для убывания:
@order=price:descМожно использовать короткие формы: `:d` вместо `:desc`
Множественная сортировка
Сортировка по нескольким полям через запятую:
@order=priority:desc,created_at:asc,nameЗаписи будут отсортированы сначала по приоритету (убывание), затем по дате создания (возрастание), затем по имени.
Сортировка JOIN полей
@order=users.created_at:desc,orders.total:descСортировка JSON полей
Используйте dot notation для JSON полей:
@order=profile.rating:desc,settings.priorityСлучайный порядок (@rand)
Для выборок list перемешивает строки результата. При указании @rand параметры @order и @sort для этого запроса не используются.
GET /api/list/dictionary?@rand=1&@limit=20В POST/JSON: "@rand": true. Включение: @rand=1, @rand=true, @rand=yes или параметр без значения. Выключение: @rand=0, @rand=false.
Нативная реализация: в MySQL добавляется ORDER BY RAND() (для запросов подсчёта записей сортировка не задаётся). В JSON-драйвере — shuffle() по отфильтрованному массиву. Проверка значения: apiFunc::isRandRequested() в api_functions.php.
Примечание
Можно использовать как @order, так и @sort - оба параметра работают одинаково.
Группировка и агрегация
Используйте `@group` для группировки результатов и агрегатные функции в `@return` (или в запасном `@select`, если `@return` не задан). Параметр `@having` фильтрует сгруппированные результаты. Модификатор `@supress` убирает массив записей на листе группы — остаются только итоги.
Простая группировка
Группировка по одному полю с подсчетом:
@group=category&@return=category,@count(id):total@supress — итоги без списка записей
Совместно с @group: на листьях группы вместо массива записей возвращается один объект с полями группировки и агрегатами. Удобно для отчётов «только счётчики/суммы», когда не нужен полный список строк внутри каждой группы.
@group=category&@return=category,@count(id):total&@supress=1В POST/JSON: "@supress": true. Включение: @supress=1, @supress=true, yes, on или параметр без значения. Выключение: @supress=0, @supress=false, no, off.
Без @supress лист группы — массив записей (с агрегатами, продублированными в каждой строке). С @supress — один объект-итог:
{
"CategoryA": { "category": "CategoryA", "total": 5 },
"CategoryB": { "category": "CategoryB", "total": 12 }
}Без агрегатов в проекции в итог попадает поле __records — число строк в группе. Работает в MySQL- и JSON-драйверах. Логика: apiFunc::isSuppressRequested(), агрегация — класс apiGroupResult в api_functions.php.
Сочетается с @having и вложенной группировкой — @supress применяется только на листьях, промежуточные уровни остаются объектами с ключами подгрупп:
@group=category,status&@return=category,status,@count(id):total&@supress=1&@having=total(gt)=5Агрегатные функции
| Функция | Описание | Пример |
|---|---|---|
| `@count(field)` | Количество записей | @count(id):total_users |
| `@sum(field)` | Сумма значений | @sum(amount):total_amount |
| `@avg(field)` | Среднее значение | @avg(price):avg_price |
| `@min(field)` | Минимальное значение | @min(price):min_price |
| `@max(field)` | Максимальное значение | @max(date):latest_date |
Множественная группировка
Группировка по нескольким полям:
@group=category,status&@return=category,status,@count(id):totalФильтрация с @having
Фильтруйте сгруппированные результаты по агрегатным значениям:
@group=category&@return=category,@count(id):total&@having=total(gt)=5Вернет только категории, в которых более 5 записей.
Комплексный пример
Статистика продаж по категориям и статусам:
@group=category,status
&@return=category,status,@count(id):total_orders,@sum(amount):total_sales,@avg(amount):avg_order
&@having=total_orders(gte)=10
&@order=total_sales:descВажно
При использовании @group, все поля в списке проекции (@return или запасной @select) должны быть либо в списке группировки, либо в агрегатных функциях.
Пагинация
Управляйте выводом данных с помощью `@page`/`@size` для постраничной навигации или `@limit`/`@offset` для прямого указания диапазона.
Постраничная пагинация
Используйте @page и @size для навигации по страницам:
@page=2&@size=10Возвращает 10 записей со второй страницы (записи 11-20).
Пагинация через LIMIT/OFFSET
@limit=20&@offset=40Возвращает 20 записей, начиная с 41-й записи.
Формат ответа с пагинацией
При использовании @page и @size, API возвращает расширенный объект:
{
"list": [...], // Массив записей
"count": 156, // Общее количество записей
"pages": 16, // Всего страниц
"page": 2, // Текущая страница
"pagination": [ // Массив для UI пагинации
{"label": "prev", "page": 1},
{"label": 1, "page": 1},
{"label": 2, "page": 2},
...
{"label": "next", "page": 3}
]
}Ограничения
По умолчанию API ограничивает результаты до 1000 записей. Для больших наборов данных используйте пагинацию.
Работа с JSON полями
API поддерживает специальное поле `_json` для хранения произвольных данных и автоматически обрабатывает вложенные структуры.
Автоматическое поднятие полей
Поля из `_json` автоматически становятся доступными на верхнем уровне:
// Структура в БД:
{
"id": "user123",
"name": "Иван",
"_json": {
"avatar": "http://...",
"bio": "Программист"
}
}
// API вернет:
{
"id": "user123",
"name": "Иван",
"avatar": "http://...",
"bio": "Программист"
}Dot notation для фильтрации
Используйте точечную нотацию для доступа к вложенным полям:
// Фильтр по вложенному полю
profile.settings.theme=dark
// Фильтр по полю в массиве
tags.0=importantDot notation в @set
При создании или обновлении используйте dot notation для вложенных структур:
POST /api/update/users/user123
{
"@set": {
"profile.avatar.url": "http://example.com/avatar.jpg",
"profile.avatar.size": 1024,
"settings.notifications.email": true
}
}Это создаст или обновит вложенную структуру в поле _json.
Выбор JSON полей в @return
@return=id,name,profile.avatar,settings.themeПримечание
Поля, которых нет в схеме таблицы, автоматически сохраняются в _json при CREATE/UPDATE операциях.
Комплексные примеры
Практические примеры использования API для решения реальных задач.
Пример 1: Поиск активных пользователей с JOIN
Получить список активных пользователей с их заказами, отсортированных по дате регистрации:
GET /api/list/users?status=active&@join=["left:orders[users.id=orders.user_id]"]&@return=users.id,users.name,users.email,orders.total:order_total&@order=users.created_at:desc&@page=1&@size=20Пример 2: Создание пользователя с вложенным профилем
Создать нового пользователя с профилем и настройками:
POST /api/create/users
Content-Type: application/json
{
"@set": {
"name": "Иван Иванов",
"email": "ivan@example.com",
"status": "active",
"profile.avatar": "https://example.com/avatar.jpg",
"profile.bio": "Разработчик",
"settings.theme": "dark",
"settings.notifications.email": true,
"settings.notifications.push": false
},
"@return": "id,name,email,profile,settings,created_at"
}Пример 3: Сложная фильтрация с логическими операциями
Найти заказы со сложными условиями:
POST /api/list/orders
Content-Type: application/json
{
"@and": [
{
"@or": [
{"status": "pending"},
{"status": "processing"}
]
},
{"total(gte)": 100},
{"created_at(gte)": "2025-01-01"}
],
"@order": "created_at:desc",
"@page": 1,
"@size": 50
}Пример 4: Статистика с группировкой
Получить статистику продаж по категориям:
GET /api/list/orders?@group=category,status&@return=category,status,@count(id):total_orders,@sum(total):revenue,@avg(total):avg_order_value&@having=total_orders(gte)=10&@order=revenue:descПример 4.1: Итоги по группам без списка записей (@supress)
Счётчики по типам записей — только агрегаты, без массива строк внутри группы:
GET /api/list/dictionary?@group=entry_type&@return=entry_type,@count(id):total&@supress=1Ответ: {"word": {"entry_type": "word", "total": 271}, "phrase": {...}}
Пример 5: Массовое обновление с условием (POST)
Обновить статус всех неактивных пользователей:
POST /api/update/users
{
"last_login(lt)": "2024-01-01",
"status": "active",
"@set": {
"status": "inactive",
"deactivated_at": "2025-11-11"
},
"@return": "id,name,email,status"
}Пример 5.1: Обновление через GET с @set
Быстрое обновление одной записи через GET запрос:
GET /api/update/users/user123?@set=status=verified&role=premium&last_seen=2025-11-11&@return=id,name,status,roleТо же самое с квадратными скобками (рекомендуется для читаемости):
GET /api/update/users/user123?@set=[status=verified&role=premium&last_seen=2025-11-11]&@return=id,name,status,roleОбновление токенов (реальный пример):
GET /api/update/users/user123?@set=[firebaseToken=abc123xyz&mobileFirebaseToken=mobile456def&webToken=web789ghi]&@return=id,name,firebaseTokenОбновление вложенных JSON полей через GET:
GET /api/update/users/user123?@set=[profile.avatar.url=https://cdn.example.com/avatar.jpg&profile.avatar.size=2048&settings.theme=dark]&@return=profile,settingsМассовое обновление с условиями через GET:
GET /api/update/orders?status=pending&created_at(lt)=2025-01-01&@set=[status=cancelled&cancelled_reason=Expired]&@return=id,status,cancelled_reason✅ Преимущества квадратных скобок:
- Чёткое визуальное отделение параметров @set от условий фильтрации
- Улучшенная читаемость при большом количестве полей
- Уменьшение ошибок при формировании URL
💡 GET запросы удобны для простых обновлений и могут быть легко использованы в URL, но для сложных операций рекомендуется POST.
Пример 6: Поиск по вложенным JSON полям
Найти пользователей с определенными настройками:
POST /api/list/users
{
"settings.theme": "dark",
"profile.verified": true,
"tags(in)": ["premium", "verified"],
"@return": "id,name,email,profile.avatar,settings.theme"
}Пример 7: Работа с пустыми значениями
Найти пользователей без аватара или биографии:
GET /api/list/users?@or=(profile.avatar(empty)=true&profile.bio(empty)=true)&status=active&@return=id,name,email,profileПример 8: Операция SAVE (создать или обновить)
Создать или обновить пользователя:
POST /api/save/users
{
"@set": {
"id": "user123",
"name": "Иван Иванов (обновлено)",
"email": "ivan.new@example.com",
"profile.updated_at": "2025-11-11"
},
"@return": "id,name,email,created_at,updated_at"
}Сохранение вложенного JSON-фрагмента (настройки модуля courses в записи settings/modules):
POST /api/save/settings/modules/courses
{
"courses": [{"id": 1, "name": "Курс A"}],
"expert": true,
"time": 60
}Если user123 существует — обновит, если нет — создаст. Для field в URL вложенный объект заменяется целиком.
Интерактивный конструктор запросов
Используйте эту форму, чтобы визуально построить ваш API-запрос. URL и команда cURL будут сгенерированы автоматически.
Фильтры
Сгенерированные запросы
GET-запрос (cURL с Bearer)
GET-запрос (URL без токена)
POST-запрос (cURL)