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

    • О фреймворке
    • Что изменилось в 7 версии
    • Структура
    • Доступ к участкам проекта
    • Разворачивание нового проекта
  • Backend

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

    • Twig шаблонизатор и работа с ним
    • Twig функции
    • Twig фильтры
    • Twig контекст
    • Настройка NPM
    • Сборка Frontend составляющей
    • Обращение к Api через JS

IO v7. Api model и работа с ними

  • Описание
  • Содержимое файла
    • IO\Api\CoreApi
    • IO\Api\CrudApi
  • ApiResult функции
    • toArray()
    • assign()
    • showResult()
    • showSuccess()
    • showException()
    • errorByCode()
    • errorNoPermissions()
    • offsetExists()
    • offsetUnset()
    • offsetGet()
    • offsetSet()
  • Вызов api функции
    • В route и api
    • В Twig
    • Через URL
  • Доступные функции CoreApi
    • rules()
    • showResult()
    • showSuccess()
    • permission()
    • permissions()
    • onInit()
    • onBefore()
    • onAfter()
  • Доступные функции CrudApi
    • struct()
    • tablename()
    • onSearchFilter()
    • onSearchParams()
    • onUpdateData()
    • onUpdateItem()
    • getSearchFilter()
    • getItemByID()
    • saveItem()
    • parseApiFilterKey()
    • convertSearchFilterToDb()
    • doGetByID()
    • doSearch()
    • doCreate()
    • doSave()
    • doDelete()
  • Прочее

Описание

Api model (модель) - файл логики, работающий (чаще всего) в связке с class'ом таблицы базы данных.

Модель формирует API приложения.

Содержимое файла

У данной версии фреймворка есть 2 варианта наследования:

  • IO\Api\CoreApi - базовый класс моделей без привязки к class.
  • IO\Api\CrudApi - класс моделей на основе IO\Api\CoreApi, с привязкой к class и поддержкой CRUD операций

IO\Api\CoreApi

<?php

namespace App\Api;

use IO\Api\CoreApi;

class ExampleApi extends CoreApi
{
    /**
     * Разрешения на выполнение методов модели
     */
    public static function rules()
    {
        $rules = parent::rules();
        
        $rules['static']['doAbc'] = 1;
        
        return $rules;
    }
    
    /**
     * Инициализация
     */
    public function onInit()
    {
        global $ioSession;
        
        if (!$ioSession->isAuth()) return EIO_DENY;
            
        $cabinet_pkid = $ioSession->getCurrentCabinetPkid();
        if ($cabinet_pkid == null) return EIO_DENY;
        
        // if (!$ioSession->permission('cluster_opt.trade.add')) return EIO_DENY;
        
        return EIO_OK;
    }
    
    /**
     * Перед выполнением запроса
     */
    public function onBefore()
    {
        // ...
    }
    
    /**
     * После выполнения запроса
     */
    public function onAfter()
    {
        if($this->result->error_code != EIO_OK)
        {
            return;
        }
        
        if(in_array($this->action, ['abc']))
        {
            // ...
        }
    }
    
    /**
     * Пример пользовательской функции
     */
    public function doAbc($result, $params)
    {
        $ret_params = $params;
        $a = xarr($params, 'a', 456);
        
        return $result->showSuccess([
            'ret_params' => $params,
            'a' => $a,
        ]);
    }
}

IO\Api\CrudApi

<?php

namespace App\Api;

use IO\Api\CrudApi;
use App\Classes\Example;

class ExampleApi extends CrudApi
{
    /**
     * Разрешения на выполнение методов модели
     */
    public static function rules()
    {
        $rules = parent::rules();
        
        $rules['static']['doGetByID'] = 1;
        $rules['static']['doSearch'] = 1;
        $rules['static']['doCreate'] = 1;
        $rules['static']['doSave'] = 1;
        $rules['static']['doDelete'] = 1;
        
        $rules['static']['doAbc'] = 1;
        
        return $rules;
    }
    
    /**
     * Структура модели
     */
    public static function struct()
    {
        $struct = parent::struct();
        
        $struct['class'] = Example::class;
        $struct['fields'] = [
            'pkid' => [
                'datatype'=> 'integer',
                'label' => 'ID записи',
                'readonly'=> true,
            ],
            'typeString' => [
                'datatype'=> 'string',
                'label' => 'Строчная переменная',
            ],
            'typeVirtual' => [
                'virtual' => true,
            ],
        ];
        $struct['primary'] = [
            'pkid',
        ];
        
        return $struct;
    }
    
    /**
     * Инициализация
     */
    public function onInit()
    {
        global $ioSession;
        
        if (!$ioSession->isAuth()) return EIO_DENY;
            
        $cabinet_pkid = $ioSession->getCurrentCabinetPkid();
        if ($cabinet_pkid == null) return EIO_DENY;
        
        // if (!$ioSession->permission('cluster_opt.trade.add')) return EIO_DENY;
        
        return EIO_OK;
    }
    
    /**
     * Перед выполнением запроса
     */
    public function onBefore()
    {
        // ...
    }
    
    /**
     * После выполнения запроса
     */
    public function onAfter()
    {
        if($this->result->error_code != EIO_OK)
        {
            return;
        }
        
        if(in_array($this->action, ['search', 'getByID']))
        {
            if($this->action == 'search') $goods_items = $this->result->items;
            elseif($this->action == 'getByID') $goods_items = [ $this->result->item ];
            
            /* Загрузка ед измерения */
            $goods_items = $this->loadUnits($goods_items);
            
            /* Загрузка типов товара */
            $goods_items = $this->loadTypes($goods_items);
            
            /* Загрузка параметров товара  */
            $goods_items = $this->loadParams($goods_items);
            
            /* Загрузка фото товара  */
            $goods_items = $this->loadPhotos($goods_items);
            
            /* Загрузка категории товара */
            $goods_items = $this->loadCategories($goods_items);
            
            /* Загрузка категории товара */
            $goods_items = $this->loadOffersCount($goods_items);
            
            /* To Array */
            $goods_items = dbToArray($goods_items);
            
            if($this->action == 'search') $this->result->items = $goods_items;
            elseif($this->action == 'getByID') $this->result->item = $goods_items[0];
        }
        
        elseif(in_array($this->action, ['save']))
        {
            if($this->item == null) return;
            
            /* Сохранение параметров товара */
            $this->saveParams();
            
            /* Сохранение категории товара */
            $this->saveCategories();
            
            /* Загрузка фото товара */
            $this->savePhotos();
        }
    }
    
    /**
     * Search filter
     */
    public function onSearchFilter($search_filter)
    {
        global $ioSession;
        
        $cabinet_pkid = $ioSession->getCurrentCabinetPkid();
        
        $search_filter['cabinet_pkid'] = $cabinet_pkid;
        $search_filter['is_deleted'] = 0;
        
        $search_filter = parent::onSearchFilter($search_filter);
        return $search_filter;
    }
    
    /**
     * Search params
     */
    public function onSearchParams($search_params)
    {
        $search_params['fields'] = ['*'];
        $search_params['order'] = [
            'pkid' => 'desc',
        ];
        
        $search_text = isset($params['search_text']) ? $params['search_text'] : '';
        if (strlen($search_text) > 0)
        {
            $search_params['filter']['~search'] = $search_text;
            $search_params['fields'][] = "#MATCH (search) AGAINST (\"" .
                \IO\IO_MYSQL_PDO::escape($search_text) . "\" IN BOOLEAN MODE) as full_text";
            $search_params['order'] = [
                'full_text' => 'desc',
                'pkid' => 'desc',
            ];
        }
        
        $search_params = parent::onSearchParams($search_params);
        return $search_params;
    }
    
    /**
     * Update data event
     */
    public function onUpdateData($save_data, $update_data)
    {
        return $update_data;
    }
    
    /**
     * Update item event
     */
    public function onUpdateItem($save_data, $update_data)
    {
        global $ioSession, $iodb;
        
        $item = $this->item;
        
        /* Если товар создается */
        if ($this->action == 'create')
        {
            /* Type ID */
            $type_id = xarr($save_data, ['type_id']);
            $item->type_id = $type_id;
            
            /* Cabinet pkid */
            $cabinet = $ioSession->getCurrentCabinet();
            $cabinet_pkid = xarr($cabinet, 'cabinet_pkid', 0);
            $cabinet_number = xarr($cabinet, 'cabinet_number', 0);
            $item->cabinet_pkid = $cabinet_pkid;
            $item->cabinet_number = $cabinet_number;
            
            /* Код товара */
            $q = "
                SELECT code_good + 1 AS new_code_good
                FROM trade_goods WHERE `cabinet_pkid`=:cabinet_pkid
                order by code_good desc limit 1
            ";
            $new_code_good = $iodb->get_var('new_code_good', $q, [
                ':cabinet_pkid' => $cabinet_pkid
            ]);
            $item->code_good = $new_code_good;
        }
        
        /* Строка поиска */
        $search_text = [
            xarr($save_data, ['meta', 'name', 'en']),
            xarr($save_data, ['meta', 'name', 'ru']),
            xarr($save_data, ['meta', 'name', 'kz']),
        ];
        //$search_text = array_filter($search_text, mb_trim);
        $item->search = implode(' ', $search_text);
        
        /* Мета информация */
        $item->meta = [
            'name' => [
                'en' => xarr($save_data, ['meta', 'name', 'en']),
                'ru' => xarr($save_data, ['meta', 'name', 'ru']),
                'kz' => xarr($save_data, ['meta', 'name', 'kz']),
            ],
            'description' => [
                'en' => xarr($save_data, ['meta', 'description', 'en']),
                'ru' => xarr($save_data, ['meta', 'description', 'ru']),
                'kz' => xarr($save_data, ['meta', 'description', 'kz']),
            ],
        ];
        
        /* Ед измерения */
        $item->unit_type_pkid = xarr($save_data, ['unit_type_pkid']);
        $item->unit_pkid_default = xarr($save_data, ['unit_pkid_default']);
        
        /* Главная фото */
        $new_photos = xarr($this->params, ['item', 'photos'], []);
        if ($new_photos && count($new_photos) > 0)
        {
            $main_photo = $new_photos[0];
            $item->main_photo_pkid = $main_photo['pkid'];
        }
        else
        {
            $item->main_photo_pkid = null;
        }
    }
    
    /**
     * Пример пользовательской функции
     */
    public function doAbc($result, $params)
    {
        $ret_params = $params;
        $a = xarr($params, 'a', 456);
        
        return $result->showSuccess([
            'ret_params' => $params,
            'a' => $a,
        ]);
    }
}

ApiResult функции

В пользовательских do функциях есть обязательный аргумент $result. Это объект экземпляра класса IO\Api\ApiResult.

toArray()

toArray(): array

assign()

assign(
  array $data
): object(IO\Api\ApiResult $this)

showResult()

showResult(
  array $result = [],
  string $error_str = '',
  int $error_code = EIO_UNKNOWN
): object(IO\Api\ApiResult $this)

showSuccess()

showSuccess(
  array $result = [],
  string $error_str = ''
): object(IO\Api\ApiResult $this)

showException()

showException(
  array $result = [],
  object(Exception) $e,
  int $error_code = EIO_UNKNOWN
): object(IO\Api\ApiResult $this)

errorByCode()

errorByCode(
  int $error_code,
  array $arr = []
): object(IO\Api\ApiResult $this)

errorNoPermissions()

errorNoPermissions(): object(IO\Api\ApiResult $this)

offsetExists()

offsetExists(
  string $key
): bool

offsetUnset()

offsetUnset(
  string $key
): void

offsetGet()

offsetGet(
  string $key
): string|null

offsetSet()

offsetSet(
  string $key,
  mixed $value
): void

Вызов api функции

В route и api

$ret = IOCore::callAction(
    'app.api.example.abc', // или по старому 'app.model.example.abc'
    [
        'a' => 123,
    ]
);
if(xarr($ret, 'error_code', EIO_FALSE) == EIO_OK)
{
    $ret_params = xarr($ret, 'ret_params', []);
    $recipientEmail = xarr($ret, 'recipient_email');
    $a = xarr($ret, 'a');
    
    v_dump($ret_params);
    v_dump($recipientEmail);
    v_dump($a);
}
else
{
    echo 'error ' . xarr($ret, 'error_code', EIO_FALSE) . ': ' . xarr($ret, 'error_str', '');
}
v_dump($ret);

В Twig

{% set r = ioCallAction(
    'app.api.example.abc', // или по старому 'app.model.example.abc'
    {
        'a' => 123,
    }
) %}
{{v_dump(r)}}

Через URL

Нужно прописать в браузере путь до нашей модели по типу
https://site.kz/entity/app.api.example.abc или
https://site.kz/entity/app.model.example.abc
где .abc это пользовательская функция

Чтобы получить результат в формате JSON, нужно добавить GET параметр &resultType=json в конце URL.

Доступные функции CoreApi

rules()

static rules(): array

showResult()

static showResult(
  array $params = [],
  string  $error_str = '',
  int $error_code = EIO_UNKNOWN
): array

showSuccess()

static showSuccess(
  array $params = [],
  string  $error_str = ''
): array

permission()

static permission(
  string $permission,
  int $account = null
): bool

permissions()

static permissions(
  array $permission = [],
  int $account = null
): bool

onInit()

onInit(): int

onBefore()

onBefore()

onAfter()

onAfter()

Доступные функции CrudApi

Класс CrudApi наследуется от CoreApi.

struct()

Структура Api

static struct(): array

tablename()

Return table name

static tablename(): string

onSearchFilter()

Search filter

onSearchFilter(): array

onSearchParams()

Search params

onSearchParams(): array

onUpdateData()

Update data event

onUpdateData(
  array $save_data,
  array $update_data
): array

onUpdateItem()

Update item event

onUpdateItem(
  array $save_data,
  array $update_data
): array

getSearchFilter()

Returns search filter

getSearchFilter(
  array $api_filter
): array

getItemByID()

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

getItemByID(
  int|string $pkid
): array|null

saveItem()

Сохранить данные item в базе данных

saveItem(
  array $save_data
)

parseApiFilterKey()

Parse api filter key

static parseApiFilterKey(
  string $key
): array

convertSearchFilterToDb()

Convert api filter to DB

static convertSearchFilterToDb(
  array $filter
): array

doGetByID()

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

doGetByID(
  object(IO\Api\ApiResult) $result,
  array $params
): array

doSearch()

Поиск записей

doSearch(
  object(IO\Api\ApiResult) $result,
  array $params
): array

doCreate()

Добавление объекта

doCreate(
  object(IO\Api\ApiResult) $result,
  array $params
  ): array

doSave()

Редактирование объекта

doSave(
  object(IO\Api\ApiResult) $result,
  array $params
): array

doDelete()

Удаление объекта

doDelete(
  object(IO\Api\ApiResult) $result,
  array $params
): array

Прочее

event функции нет, там onInit, onUpdate, onSearch...

Prev
Class и работа с ними
Next
Template и работа с ними