Введение

Этот документ описывает синтаксис для выполнения запросов к нашему API, позволяя вам динамически фильтровать, сортировать, группировать и пагинировать данные. Используйте навигацию слева для изучения различных возможностей.

Использование 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]'], '@select' => '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', '@select' => 'id,name,email,profile.avatar,settings.theme' ]); // Если id не указан, используется из маршрута (если доступен) $api->route = ['item' => 'user123', 'table' => 'users']; $user = $api->read(); ?>

➕ 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)

Вы можете объединять несколько условий с помощью операторов @or и @and для создания сложных запросов.

🔀 Использование @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']] ] ]); ?>

🔀🔗 Комбинирование @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()

Работа с драйверами

API поддерживает динамическое подключение различных драйверов баз данных:

Конфигурация драйвера в api.json:

{ "driver": "mysql", "drivers": { "mysql": { "host": "localhost", "port": 3306, "database": "mydb", "username": "user", "password": "pass" }, "postgresql": { "host": "localhost", "port": 5432, "database": "mydb", "username": "user", "password": "pass" } } }

💡 Как это работает:

  • • Драйвер определяется из настройки "driver" в api.json
  • • Файл драйвера загружается автоматически: drivers/{driver}.php
  • • Класс драйвера ищется в форматах: MysqlDriver, mysqlDriver
  • • Драйвер инициализируется при первом вызове CRUD метода (lazy loading)
  • • Экземпляр драйвера кэшируется для повторного использования

Практические примеры

Пример 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]'], '@select' => '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 вызовов
  • Автоматический парсинг - запросы парсятся автоматически
  • Динамические драйверы - легко переключаться между БД

Быстрый старт

Пошаговое руководство по подключению API к вашему проекту.

Шаг 1: Установка API

  1. Скопируйте папку api/ в корень вашего проекта
  2. Убедитесь, что веб-сервер имеет доступ к файлам API
  3. Проверьте права на запись для файла api.json (хранит настройки)

Структура файлов:

project/ ├── api/ │ ├── api.php # Точка входа │ ├── api_parser.php # Парсер запросов │ ├── drivers/ │ │ └── mysql.php # MySQL драйвер │ ├── api_router.php # Роутер │ ├── api_settings.php # Веб-интерфейс настроек │ ├── api_help.php # Эта документация │ ├── api.ini # Маршруты │ └── api.json # Настройки (создастся автоматически) └── index.php # Ваше приложение

Шаг 2: Подключение в вашем проекте

Добавьте следующий код в самое начало вашего основного файла (например, index.php):

require_once __DIR__ . '/api/api.php'; $api = new Api(); $api->run(); // Далее сод вашего приложения

💡 Важно!

  • • Код должен быть добавлен в самом начале файла, до любого вывода HTML
  • • API обрабатывает только запросы к /api/*
  • • Если запрос не к API, выполнение продолжается дальше в вашем коде
  • • Не нужен закрывающий тег ?> в конце файла

Шаг 3: Настройка через веб-интерфейс

  1. Откройте в браузере: http://ваш-сайт.com/api/settings
  2. При первом входе введите пароль для доступа к панели управления
  3. Настройте подключение к базе данных (MySQL):
    • Host (обычно localhost)
    • Username (пользователь БД)
    • Password (пароль БД)
    • Database (имя базы данных)
    • Port (обычно 3306)
  4. Нажмите кнопку "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

✅ Готово!

Теперь ваш API полностью настроен и готов к использованию. Перейдите к разделу "Управление токенами" для настройки безопасности.

Аутентификация

Для доступа к защищенным ресурсам API требуется передать токен аутентификации. Это можно сделать двумя способами:

1. Bearer Token (рекомендуется)

Передайте токен в заголовке Authorization:

Authorization: Bearer YOUR_SECRET_TOKEN

2. Параметр @token

Передайте токен как параметр запроса:

@token=YOUR_SECRET_TOKEN

Управление токенами

Токены обеспечивают безопасный доступ к API и позволяют гибко управлять правами доступа.

Создание токена через веб-интерфейс

  1. Откройте панель управления:
    http://ваш-сайт.com/api/settings
  2. Перейдите в раздел "Tokens" в боковом меню
  3. Включите защиту API (переключатель "Protect API access")

    Если защита отключена, API будет доступен без токена

  4. Нажмите "+ Add Token" для создания нового токена
  5. Заполните параметры токена:
    • Token name - имя для идентификации токена (например, "Mobile App", "Frontend")
    • Token - сам токен (нажмите 🔄 для автогенерации)
    • Tables - список таблиц, к которым разрешен доступ (оставьте пустым для доступа ко всем)
    • Permissions - отметьте нужные разрешения:
      • C - Create (создание записей)
      • R - Read (чтение записей)
      • U - Update (обновление записей)
      • D - Delete (удаление записей)
      • S - Save (создание или обновление)
      • L - List (получение списков)
  6. Нажмите "Save Settings" для сохранения изменений

💡 Пример настройки токена:

Имя: "Mobile App Token"

Токен: "abc123xyz456def789..." (50 символов)

Таблицы: users, orders, products

Разрешения: R, 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

Использование токена в запросах

Метод 1: Bearer Token (рекомендуется)

curl -H "Authorization: Bearer YOUR_SECRET_TOKEN" \ http://ваш-сайт.com/api/list/users

Метод 2: Параметр @token

GET http://ваш-сайт.com/api/list/users?@token=YOUR_SECRET_TOKEN

Метод 3: В теле POST запроса

POST http://ваш-сайт.com/api/list/users Content-Type: application/json { "@token": "YOUR_SECRET_TOKEN", "status": "active" }

Ограничение доступа к таблицам

Токены можно ограничить конкретными таблицами для повышения безопасности:

✅ Токен с доступом к 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

🔐 Безопасность токенов

  • Храните токены в безопасном месте (переменные окружения, защищенные конфиги)
  • Никогда не передавайте токены в URL на production (используйте Bearer Token)
  • Регулярно меняйте токены для критичных систем
  • Используйте разные токены для разных приложений
  • Настраивайте минимальные необходимые разрешения (принцип наименьших привилегий)

Действия (CRUD операции)

API поддерживает полный набор CRUD операций для работы с данными.

LIST - Получение списка

Получить список записей с фильтрацией, сортировкой и пагинацией.

GET /api/list/users?status=active&@page=1&@size=10

READ - Чтение одной записи

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

GET /api/read/users/user123

CREATE - Создание записи

Создать новую запись. Данные передаются через параметр @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

DELETE - Удаление записи

Удалить запись по ID или по условию.

DELETE /api/delete/users/user123

Для массового удаления используйте POST с условиями фильтрации.

SAVE - Создание или обновление

Автоматически создает запись, если ID не существует, или обновляет существующую.

POST /api/save/users { "@set": { "id": "user123", "name": "Обновленное имя" } }

Условия

Вы можете фильтровать данные, указывая условия для отдельных полей. Условия можно передавать как в 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"]
`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%"

Полные примеры запросов

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`. Синтаксис отличается для GET и POST запросов для удобства.

GET-запросы (функциональная нотация)

Условия перечисляются через запятую внутри круглых скобок. Удобно для создания URL вручную.

http://.../users?@or=(status=active,role=admin)&department=IT

POST-запросы (JSON-массив)

Используется JSON-массив объектов, что позволяет создавать сложные вложенные структуры.

{
  "@and": [
    {
      "@or": [
        {"users.status": "active"},
        {"users.role": "admin"}
      ]
    },
    {"users.department": "IT"}
  ]
}

Объединения (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]"]&@select=orders.id,users.name:customer_name,products.name:product_name

POST запрос (рекомендуется для сложных 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]" ], "@select": "orders.id,users.name:customer,products.name:product,categories.name:category", "@return": "id,customer,product,category,orders.total" }

Результат: Заказы с данными пользователя, продукта и категории в одном запросе

Практические примеры

📱 Пример 1: Заказы с пользователями

Получить все заказы со статусом "pending" и информацией о пользователях:

GET /api/list/orders?status=pending&@join=["left:users[orders.user_id=users.id]"]&@select=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]" ], "@select": "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]" ], "@select": "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]" ], "@select": "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", "@select": "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", "@select": "products.name:product,@count(orders.id):total_orders,@sum(orders.total):revenue", "@order": "revenue:desc" }

Выбор полей при использовании JOIN

Выбрать все поля из основной таблицы:

@select=orders.*,users.name,users.email

Выбрать все поля из всех таблиц:

@select=orders.*,users.*,products.*

⚠️ Не рекомендуется - возвращает много данных

Выбрать конкретные поля с псевдонимами:

@select=orders.id:order_id,orders.total,users.name:customer_name,users.email:customer_email,products.name:product_title

✅ Рекомендуется - явное указание нужных полей

Если @select не указан:

API автоматически вернет все поля из всех таблиц (основной + все JOIN)

❌ Частые ошибки при работе с JOIN

1. Неправильный формат условия связи

❌ Неверно: @join=["left:users[user_id=id]"]

✅ Верно: @join=["left:users[orders.user_id=users.id]"]

Нужно указывать таблицу для каждого поля

2. Забыли указать @select

Без @select вернутся ВСЕ поля из всех таблиц, что может быть избыточно

3. Неправильный порядок JOIN

Порядок JOIN важен! Сначала присоединяйте таблицы первого уровня, потом второго

4. Дублирование имен полей

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

@select=orders.id:order_id,users.id:user_id

⚡ Советы по производительности

  • ✅ Используйте @select для выбора только нужных полей
  • ✅ Добавляйте индексы на поля, используемые в условиях JOIN
  • ✅ Используйте фильтрацию для уменьшения количества данных до JOIN
  • ✅ Предпочитайте INNER JOIN, если не нужны записи без совпадений
  • ✅ Ограничивайте результаты с помощью @limit или @page/@size
  • ⚠️ Избегайте JOIN более 4-5 таблиц в одном запросе
  • ⚠️ Не используйте table.* для всех JOIN таблиц одновременно

Фильтр полей

Используйте `@select` и `@return` для управления тем, какие поля возвращаются в ответе API. Параметр `@select` указывает, какие поля извлекать из базы данных (влияет на SQL запрос), а `@return` фильтрует уже полученные данные перед возвратом клиенту (постобработка).

Основной синтаксис

@select=id,name,email,created_at

Псевдонимы полей

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

@select=id,name:full_name,email:contact_email

Поля из JOIN таблиц

@select=orders.id,users.name:user_name,products.name:product_name

Агрегатные функции

Используйте @ перед именем функции:

@select=category,@count(id):total,@sum(amount):total_amount,@avg(price):avg_price

Доступные функции: @count, @sum, @avg, @min, @max

Выбор всех полей таблицы

@select=users.*,orders.id,orders.total

Параметр @return

Параметр `@return` позволяет указать, какие поля должны быть возвращены после операций CREATE, UPDATE, DELETE и в запросах LIST. В отличие от `@select`, который влияет на SQL запрос, `@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

Формат значения

Поля перечисляются через запятую:

@return=id,name,email,profile.avatar,created_at

Разница между @select и @return

  • @select - указывает, какие поля извлекать из базы данных (влияет на SQL запрос)
  • @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

Группировка и агрегация

Используйте `@group` для группировки результатов и агрегатные функции в `@select`. Параметр `@having` фильтрует сгруппированные результаты.

Простая группировка

Группировка по одному полю с подсчетом:

@group=category&@select=category,@count(id):total

Агрегатные функции

Функция Описание Пример
`@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&@select=category,status,@count(id):total

Фильтрация с @having

Фильтруйте сгруппированные результаты по агрегатным значениям:

@group=category&@select=category,@count(id):total&@having=total(gt)=5

Вернет только категории, в которых более 5 записей.

Комплексный пример

Статистика продаж по категориям и статусам:

@group=category,status &@select=category,status,@count(id):total_orders,@sum(amount):total_sales,@avg(amount):avg_order &@having=total_orders(gte)=10 &@order=total_sales:desc

Работа с 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=important

Dot 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 полей в @select

@select=id,name,profile.avatar,settings.theme

Комплексные примеры

Практические примеры использования API для решения реальных задач.

Пример 1: Поиск активных пользователей с JOIN

Получить список активных пользователей с их заказами, отсортированных по дате регистрации:

GET /api/list/users?status=active&@join=["left:orders[users.id=orders.user_id]"]&@select=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&@select=category,status,@count(id):total_orders,@sum(total):revenue,@avg(total):avg_order_value&@having=total_orders(gte)=10&@order=revenue:desc

Пример 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"], "@select": "id,name,email,profile.avatar,settings.theme", "@return": "id,name,email,profile,settings" }

Пример 7: Работа с пустыми значениями

Найти пользователей без аватара или биографии:

GET /api/list/users?@or=(profile.avatar(empty)=true&profile.bio(empty)=true)&status=active&@select=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" }

Если user123 существует - обновит, если нет - создаст новую запись.

Интерактивный конструктор запросов

Используйте эту форму, чтобы визуально построить ваш API-запрос. URL и команда cURL будут сгенерированы автоматически.

Фильтры

Сгенерированные запросы

GET-запрос (URL)

POST-запрос (cURL)

1