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

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

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

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

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

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

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

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

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

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

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

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

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

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

    • Базовый UI

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

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

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

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

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

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

Создание API в IO7

Внимание

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

  • Базовый API (CoreApi)
  • CRUD API (CrudApi)
  • Жизненный цикл action
  • Правила доступа (rules)
  • Доступ к сервисам
  • Межсерверные вызовы
  • См. также

Базовый API (CoreApi)

Создайте класс, наследующий IO\Api\CoreApi:

namespace App\Api;

use IO\Api\CoreApi;
use IO\Api\ApiResult;

class NotificationApi extends CoreApi
{
    /**
     * Разрешения для вызова через IO\Core::callAction()
     */
    public static function rules(): array
    {
        return [
            'static' => [
                'actionSend'   => 1,
                'actionList'   => 1,
            ],
            'object' => [],
        ];
    }

    /**
     * Инициализация (вызывается перед каждым action).
     * Верните не-EIO_OK для прерывания.
     */
    public function onInit(): int
    {
        $session = $this->app()->session;
        if (!$session || !$session->isAuth()) {
            return EIO_DENY;
        }
        return EIO_OK;
    }

    /**
     * Отправка уведомления
     */
    public function doSend(ApiResult $result, array $params): ApiResult
    {
        $to = $params['to'] ?? '';
        $message = $params['message'] ?? '';

        if (empty($to) || empty($message)) {
            return $result->showResult([], 'Обязательные поля: to, message', EIO_VALIDATION);
        }

        NotificationService::send($to, $message);

        return $result->showSuccess(['sent' => true]);
    }

    /**
     * Список уведомлений
     */
    public function doList(ApiResult $result, array $params): ApiResult
    {
        $items = Notification::search([
            'filter' => ['user_id' => $this->app()->session->getUserID()],
            'order'  => ['pkid' => 'desc'],
            'limit'  => $params['limit'] ?? 20,
        ]);

        return $result->showSuccess([
            'items' => $items['res'],
            'total' => $items['count'],
        ]);
    }
}

Вызов:

// Отправка
$result = \IO\Core::callAction('app.api.notification.send', [
    'to'      => 'user@example.com',
    'message' => 'Привет!',
]);

// Список
$result = \IO\Core::callAction('app.api.notification.list', [
    'limit' => 10,
]);

CRUD API (CrudApi)

Наследуйтесь от IO\Api\CrudApi для стандартных операций:

namespace App\Api;

use IO\Api\CrudApi;
use IO\Api\ApiResult;

class ProductApi extends CrudApi
{
    public static function struct(): array
    {
        return [
            'class' => \App\Models\Product::class,
            'fields' => [
                'pkid'         => ['type' => 'int'],
                'name'         => ['type' => 'string', 'label' => 'Название'],
                'price'        => ['type' => 'float', 'label' => 'Цена'],
                'category_id'  => ['type' => 'int', 'label' => 'Категория'],
                'description'  => ['type' => 'string', 'label' => 'Описание'],
                'is_active'    => ['type' => 'int'],
                'is_deleted'   => ['type' => 'int', 'virtual' => true],
                'gmtimeAdd'    => ['type' => 'string', 'readonly' => true],
                'gmtimeChange' => ['type' => 'string', 'readonly' => true],
            ],
            'primary' => ['pkid'],
        ];
    }

    public static function rules(): array
    {
        return [
            'static' => [
                'actionSearch'  => 1,
                'actionGetByID' => 1,
                'actionCreate'  => 1,
                'actionSave'    => 1,
                'actionDelete'  => 1,
            ],
            'object' => [],
        ];
    }

    public function onSearchFilter(array $search_filter): array
    {
        $search_filter['is_deleted'] = 0;
        return $search_filter;
    }

    public function onSearchParams(array $search_params): array
    {
        $search_params['join'][] = 'LEFT JOIN categories ON products.category_id = categories.pkid';
        return $search_params;
    }

    public function onUpdateData(array $save_data, array $update_data): array
    {
        if (!isset($update_data['gmtimeChange'])) {
            $update_data['gmtimeChange'] = iogetdbtimeutc(time());
        }
        return $update_data;
    }

    public function doUpdatePrices(ApiResult $result, array $params): ApiResult
    {
        $category_id = $params['category_id'] ?? 0;
        $multiplier = $params['multiplier'] ?? 1.0;

        if ($category_id <= 0 || $multiplier <= 0) {
            return $result->showResult([], 'Невалидные параметры', EIO_VALIDATION);
        }

        \IO\Core::call('app.class.product.updatePricesByCategory', [
            'category_id' => $category_id,
            'multiplier'  => $multiplier,
        ]);

        return $result->showSuccess(['updated' => true]);
    }
}

Вызов CRUD:

// Поиск
$result = \IO\Core::callAction('app.model.product.search', [
    'filter' => ['category_id' => 5],
    'limit'  => 20,
]);

// Получение по ID
$result = \IO\Core::callAction('app.model.product.getByID', ['pkid' => 42]);

// Создание
$result = \IO\Core::callAction('app.model.product.create', [
    'item' => [
        'name'        => 'Товар',
        'price'       => 1500.00,
        'category_id' => 5,
    ],
]);

// Обновление
$result = \IO\Core::callAction('app.model.product.save', [
    'pkid' => 42,
    'item' => ['price' => 2000.00],
]);

// Удаление
$result = \IO\Core::callAction('app.model.product.delete', ['pkid' => 42]);

// Кастомный action
$result = \IO\Core::callAction('app.model.product.updatePrices', [
    'category_id' => 5,
    'multiplier'  => 1.1,
]);

Жизненный цикл action

1. onBefore()         ← логирование, подготовительные операции
2. onInit()           ← проверка прав, валидация
3. doXxx()            ← основная логика
4. onAfter()          ← уведомления, очистка кеша
public function onInit(): int
{
    $this->user = $this->app()->session->getUserInfo();
    if (!$this->user) {
        return EIO_DENY;
    }
    return EIO_OK;
}

public function onBefore(): void
{
    error_log("Action started: {$this->action}");
}

public function onAfter(): void
{
    $this->app()->cache->delete("product_list");
}

Правила доступа (rules)

public static function rules(): array
{
    return [
        'static' => [
            '*' => 1,                    // все методы разрешены
            'actionSearch' => 1,         // конкретный метод
        ],
        'object' => [],                  // методы экземпляра (не используются)
    ];
}

Доступ к сервисам

Внутри API доступ к сервисам через $this->app():

$db = $this->app()->iodb;

$this->app()->cache->set('key', 'value', 3600);
$value = $this->app()->cache->get('key');

$session = $this->app()->session;
$user_id = $session->getUserID();

$html = $this->app()->twig->render('@app/email.twig', ['user' => $user]);

Межсерверные вызовы

API автоматически поддерживают вызовы между серверами:

// Если 'product' зарегистрирован в $ioProjects как отдельный сервер,
// вызов будет отправлен через HTTP
$result = \IO\Core::callAction('product.model.product.search', [
    'filter' => ['is_active' => 1],
]);

См. также

  • Обзор API
  • IO\Core::call() и IO\Core::callAction()
  • CRUD операции
Prev
IOCore::call() и IOCore::callAction()