IO v7. Api model и работа с ними
Описание
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...