IO v6. Class и работа с ними
Описание
Class - инструмент для управления записями в таблицах из баз данных.
В данной версии фреймворка в каждом проекте используется 2 базы данных: MySQL и MongoDB.
В MySQL находятся:
- данные cron планировщика.
- кеш данные.
- даннные, определенные проектом.
- данные для "общения проектов" (актуально для версии ниже IO6).
В MongoDB хранятся даннные, определенные проектом. В большинстве существующих проектов, почти все основные данные хранятся именно в этой базе данных.
Каждый class в системе обладает уникальным именем. Из любой части кода, без разницы находится ли код в проекте, или в другом, существует возможность обратиться к методам этого class'а. Для этого необходимо правильно задать имя.
Имя class'а состоит из следующих частей:
<project name>.class[.<path>].<className>
Подробнее о доступе к классам и не только
Примеры имен:
com.class.user- class пользователей, которые находится в проекте Кабинет, который отвечает за авторизацию, регистрацию пользователей.com.class.crm.client- class в CRM, который позволяет зарегистрировать клиента.app.class.test- Тестовый class, который находится в том же проекте, где осуществляется к нему обращение.
Class файлы проекта находятся в папке proj/app/class. Class файл должен начинаться с маленькой буквы и иметь постфикс .php (пример: example.php). Имя класса должно быть таким же, как и название файла, но с большой буквы и без формата файла .php (пример: Example). Наслеодование class устанавливается в зависимости от используемой базы данных.
IODBObject- для работы с MySQL таблицейIOMongoObject- для работы с MongoDB коллекцией (таблицей)IOMongoObject_Array- для работы с дополненной MongoDB коллекцией (таблицей)IODataObject- для работы с динамическими данными без привязки к таблице
Содержимое файла
Кроме описания class в этом файле ничего не должно быть. Закрывать ?> не требуется.
Class MySQL таблицы
Пример class'а для работы с MySQL таблицей:
<?php
class Example extends IODBObject
{
/**
* Разрешения на выполнение методов класса
*/
public static function rcp_rules()
{
$arr = parent::rcp_rules();
//$arr['static']['dbsearch2'] = 1;
//$arr['static']['examplefn'] = 1;
return $arr;
}
/**
* Название таблицы в базе данных
*/
public function tablename()
{
return "`".MYSQL_DB."`.`example`";
}
/**
* Структура таблицы
*/
public function struct()
{
return [
'fields' => [
/*
type:
- sql (поле в бд)
- property (динамическое поле, не записывается в базу)
datatype:
- int, integer, long
- double, float, real
- bool, boolean
- string
- nohtml
- date
- datetime
default: - значение по умолчанию
func: - функция динамического поля
*/
'id' => [ // autoincrement from db
'type' => 'sql',
'datatype' => 'long',
],
'pkid' => [ // autoincrement from function pkid()
'type' => 'sql',
'func' => 'pkid',
'datatype' => 'long',
],
'company_pkid' => [
'type' => 'sql',
'datatype' => 'long',
],
'typeInt' => [
'type' => 'sql',
'datatype' => 'int',
'default' => 0,
],
'typeLong' => [
'type' => 'sql',
'datatype' => 'long',
'default' => 0,
],
'typeDouble' => [
'type' => 'sql',
'datatype' => 'double',
'default' => 0,
],
'typeBool' => [
'type' => 'sql',
'datatype' => 'boolean',
'default' => false,
],
'typeString' => [
'type' => 'sql',
'datatype' => 'string',
],
'typeDate' => [
'type' => 'sql',
'datatype' => 'date',
],
'typeProperty1' => [ // value from function property1()
'type' => 'sql',
'datatype' => 'long',
'func' => 'property1',
],
'typeProperty2' => [ // value from function property2()
'type' => 'sql',
'datatype' => 'long',
'func' => 'property2',
],
'isDeleted' => [
'type' => 'sql',
'datatype' => 'boolean',
],
'gmtimeAdd' => [ // value from function gmtimeAdd()
'type' => 'sql',
'datatype' => 'nohtml',
'func' => 'gmtimeAdd',
],
'gmtimeChange' => [ // value from function gmtimeChange()
'type' => 'sql',
'datatype' => 'nohtml',
'func' => 'gmtimeChange',
],
'ugmtimeAdd' => [
'type' => 'sql',
'datatype' => 'long',
],
'ugmtimeChange' => [
'type' => 'sql',
'datatype' => 'long',
],
],
'primary' => [
//0 => 'id',
0 => 'pkid',
],
];
}
// custom property function
public function property1($method, $name, $value)
{
if($method == 'set')
{
if(!isset($this->__data[$name])) $this->__data[$name] = $value;
else $this->__data[$name] += $value;
}
elseif($method == 'get')
{
// Ничего не делаем, пусть значение будет то же
}
}
// custom property function
public function property2($method, $name, $value)
{
if($method == 'set')
{
// Ничего не делаем, пусть значение будет то же
}
elseif($method == 'get')
{
$this->__data[$name] = $this->typeProperty1 * 2;
}
}
// custom function
public static function examplefn($params)
{
return [
'hello' => $params,
];
}
// example redeclare function create
public function create($params = null)
{
global $capsuledb;
// реализация смешанного автоинкремента
// когда автоинкремент не общий, а например для каждой компании свой
if(!$this->typeInt)
{
$r = $capsuledb->table('io_sequence')->updateOrInsert(
[
'table' => 'example',
'field' => 'typeInt',
'company_pkid' => intval($this->company_pkid),
],
[
'seq' => $capsuledb::raw('`seq` + 1'),
]
);
$r = $capsuledb->table('io_sequence')->where([
['table', '=', 'example'],
['field', '=', 'typeInt'],
['company_pkid', '=', intval($this->company_pkid)],
])->first();
$typeInt = xarr($r, 'seq');
$this->typeInt = $typeInt;
}
return parent::create($params);
}
// example redeclare function update
public function update($params = null)
{
return parent::update($params);
}
// example redeclare function delete
public function delete($params = null)
{
return parent::delete($params);
}
}

Обязательные методы при написания class'а:
rcp_rules()- возращает разрешенные функции, которые можно запускать удаленно с других проектов.tablename()- возращает имя таблицы базы данных.struct()- возращает структуру таблицы базы данных.
Обязательные для объявления поля:
pkidтип long.isDeletedтип boolean.gmtimeAddтип nohtml, хранит значение в формате rfc822.gmtimeChangeтип nohtml, хранит значение в формате rfc822.ugmtimeAddтип long, хранит значения в unix timestamp.ugmtimeChangeтип long, хранит значения в unix timestamp.
Каждое поле задается следующим описанием характеристик:
type- тип поля. Различаютsqlиproperty.default- значение по умолчанию.readonly- только чтение, запрещено редактирование и создание.nocreate- запрещена инициализация переменной при ее создании.noedit- запрещено редактирование переменной, но при создании ее можно инициировать.datatype- тип данных поля.func- название функции-обработчика значения переменной.
Поддерживаемые типы данных:
- Целочисленные
int,integer– 32-битное знаковое целое.long– 64-битное знаковое целое.
- Вещественные
long– действительное число.double,float,real– число с плавающей запятой.
- Логические
bool,booleanлогический тип.
- Строки
string– строка текста.html– строка, обработанная командой purify (безопасная для хранения html данные).nohtml– строка из которой вырезаны все html теги.htmlescape– строка в которой экранированы все html теги.
- Дата
date– строка, в которой сохранена дата, без времени и внеменной зоны.datetime– строка, в которой сохранены дата, время и временная зона.
Class MongoDB коллекции (таблицы)
Пример class'а для работы с MongoDB коллекцией (таблицей):
<?php
class Example extends IOMongoObject
{
/**
* Разрешения на выполнение методов класса
*/
public static function rcp_rules()
{
$arr = parent::rcp_rules();
//$arr['static']['dbsearch2'] = 1;
//$arr['object']['getPage'] = 1;
return $arr;
}
/**
* Название таблицы в базе данных
*/
public function tablename()
{
return MONGO_DATABASE.'.example';
}
/**
* Структура коллекции (таблицы)
*/
public function struct()
{
return [
'fields' => [
/*
type:
- sql (поле в бд)
- property (динамическое поле, не записывается в базу)
datatype:
- int, integer, long
- double, float, real
- bool, boolean
- string
- nohtml
- date
- datetime
- array
- collection
- money
default: - значение по умолчанию
func: - функция динамического поля
*/
'pkid' => [
'type' => 'sql',
'func' => 'pkid',
'datatype' => 'long',
],
'company_pkid' => [
'type' => 'sql',
'datatype' => 'long',
],
'typeInt' => [
'type' => 'sql',
'datatype' => 'int',
'default' => 0,
],
'typeLong' => [
'type' => 'sql',
'datatype' => 'long',
'default' => 0,
],
'typeDouble' => [
'type' => 'sql',
'datatype' => 'double',
'default' => 0,
],
'typeBool' => [
'type' => 'sql',
'datatype' => 'boolean',
'default' => false,
],
'typeString' => [
'type' => 'sql',
'datatype' => 'string',
],
'typeNohtml' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'typeDate' => [
'type' => 'sql',
'datatype' => 'date',
],
'typeCollection' => [
'type' => 'sql',
'datatype' => 'collection',
],
'typeArray' => [
'type' => 'sql',
'datatype' => 'array',
'struct' => 'long',
'noKeys' => 1,
],
'typeArray2' => [
'type' => 'sql',
'datatype' => 'array',
'default' => [],
'struct' => [
'fieldLong' => [
'datatype' => 'long',
'default' => 0,
],
'fieldArray' => [
'datatype' => 'array',
'struct' => 'long',
'noKeys' => 1,
'default' => [1, 2, 3],
],
'fieldMoney' => [
'datatype' => 'money',
'default' => [
'value' => 0,
'currency' => 'KZT',
],
],
'fieldString' => [
'datatype' => 'nohtml',
'default' => 'строка по умолчанию',
],
],
'noKeys' => 1,
],
'typeProperty1' => [ // value from function property1()
'type' => 'sql',
'datatype' => 'long',
'func' => 'property1',
],
'typeProperty2' => [ // value from function property2()
'type' => 'sql',
'datatype' => 'long',
'func' => 'property2',
],
'typeMoney' => [
'type' => 'sql',
'datatype' => 'money',
],
'isDeleted' => [
'type' => 'sql',
'datatype' => 'boolean',
],
'gmtimeAdd' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'gmtimeChange' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'ugmtimeAdd' => [
'type' => 'sql',
'datatype' => 'long',
],
'ugmtimeChange' => [
'type' => 'sql',
'datatype' => 'long',
],
],
'primary' => [
0 => 'pkid',
],
];
}
// custom value function
public function property1($method, $name, $value)
{
if($method == 'set')
{
if(!isset($this->__data[$name])) $this->__data[$name] = $value;
else $this->__data[$name] += $value;
}
elseif($method == 'get')
{
// Ничего не делаем, пусть значение будет то же
}
}
// custom value function
public function property2($method, $name, $value)
{
if($method == 'set')
{
// Ничего не делаем, пусть значение будет то же
}
elseif($method == 'get')
{
$this->__data[$name] = $this->typeProperty1 * 2;
}
}
// custom function
public function valid()
{
$this->typeString = '/'.rtrim(ltrim($this->typeString, '/'), '/');
return 1;
}
// example redeclare function create
public function create($params = null)
{
if(!$this->typeInt)
{
$database = MONGO_DATABASE;
$collection = 'io_sequence';
$iomongo = ioGetMongoConnection($database, 'write', $err);
if($iomongo == null)
{
$this->error_str = 'IO mongo is null';
return 0;
}
$col = $iomongo->$database->$collection;
$r = $col->findAndModify(
[
'table' => 'example',
'field' => 'typeInt',
'company_pkid' => intval($this->company_pkid),
],
['$inc' => ['seq' => 1]],
null,
[
'new' => true,
'upsert' => true, // если записи нет, то создать
]
);
$typeInt = xarr(xarr($r, 'seq', []), 'value');
$this->typeInt = $typeInt;
}
return parent::create($params);
}
// example redeclare function update
public function update($params = null)
{
return parent::update($params);
}
// example redeclare function delete
public function delete($params = null)
{
return parent::delete($params);
}
}

Обязательные методы при написания class'а:
rcp_rules()- возращает разрешенные функции, которые можно запускать удаленно с других проектов.tablename()- возращает имя коллекции (таблицы) базы данных.struct()- возращает структуру коллекции (таблицы) базы данных.
Обязательные для объявления поля:
pkidтип long.isDeletedтип boolean.gmtimeAddтип nohtml, хранит значение в формате rfc822.gmtimeChangeтип nohtml, хранит значение в формате rfc822.ugmtimeAddтип long, хранит значения в unix timestamp.ugmtimeChangeтип long, хранит значения в unix timestamp.
Каждое поле задается следующим описанием характеристик:
type- тип поля. Различаютsqlиproperty.default- значение по умолчанию.readonly- только чтение, запрещено редактирование и создание.nocreate- запрещена инициализация переменной при ее создании.noedit- запрещено редактирование переменной, но при создании ее можно инициировать.datatype- тип данных поля.struct- структура поля (используется для массивов).noKeys- сохранять массив без сохранения ключей (для type = array).func- название функции-обработчика значения переменной.
Поддерживаемые типы данных:
- Целочисленные
int,integer– 32-битное знаковое целое.long– 64-битное знаковое целое.
- Вещественные
long– действительное число.double,float,real– число с плавающей запятой.
- Логические
bool,booleanлогический тип.
- Строки
string– строка текста.html– строка, обработанная командой purify (безопасная для хранения html данные).nohtml– строка из которой вырезаны все html теги.htmlescape– строка в которой экранированы все html теги.
- Дата
date– строка, в которой сохранена дата, без времени и внеменной зоны.datetime– строка, в которой сохранены дата, время и временная зона.
- Массивы
array– структурированный массив.collection– не структурированный массив.
- Деньги
money- деньги (массив с 3мя ключами: value - (double) значение, currency - (string(3)) валюта, pay_type - (int) способ оплаты).
Class MongoDB дополнительной коллекции (таблицы)
Пример class'а для работы с дополнительной коллекцией (таблицей) (дополняющей основную) в MongoDB (аналог join):
<?php
class CategoryFieldsListData extends IOMongoObject_Array
{
/**
* Параметры класса
*/
public function params()
{
return [
'class' => 'app.class.categoryFieldsList',
'field' => 'data',
];
}
/**
* Структура дополнительной коллекции (таблицы)
*/
public function struct()
{
return [
'fields' => [
'foreignPkid' => [
'type' => 'sql',
'datatype' => 'long',
],
'pos' => [
'type' => 'sql',
'datatype' => 'long',
'func' => 'pkid',
],
'name_ru' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'name_kz' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'name_en' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'isDeleted' => [
'type' => 'sql',
'datatype' => 'bool',
'default' => false,
],
'gmtimeAdd' => [
'type' => 'sql',
'datatype' => 'nohtml',
'func' => 'gmtimeAdd'
],
'gmtimeChange' => [
'type' => 'sql',
'datatype' => 'nohtml',
'func' => 'gmtimeChange'
],
],
'primary' => [
0 => 'foreignPkid',
1 => 'pos',
],
];
}
}
Обязательные методы при написания class'а:
params()- возращает имя связываемого class'а и связываемого с ним поля.struct()- возращает структуру поля коллекции (таблицы) базы данных.
Обязательные для объявления поля:
pkidтип long.isDeletedтип boolean.gmtimeAddтип nohtml, хранит значение в формате rfc822.gmtimeChangeтип nohtml, хранит значение в формате rfc822.ugmtimeAddтип long, хранит значения в unix timestamp.ugmtimeChangeтип long, хранит значения в unix timestamp.
Каждое поле задается следующим описанием характеристик:
type- тип поля. Различаютsqlиproperty.default- значение по умолчанию.readonly- только чтение, запрещено редактирование и создание.nocreate- запрещена инициализация переменной при ее создании.noedit- запрещено редактирование переменной, но при создании ее можно инициировать.datatype- тип данных поля.struct- структура поля (используется для массивов).noKeys- сохранять массив без сохранения ключей (для type = array).func- название функции-обработчика значения переменной.
Поддерживаемые типы данных:
- Целочисленные
int,integer– 32-битное знаковое целое.long– 64-битное знаковое целое.
- Вещественные
long– действительное число.double,float,real– число с плавающей запятой.
- Логические
bool,booleanлогический тип.
- Строки
string– строка текста.html– строка, обработанная командой purify (безопасная для хранения html данные).nohtml– строка из которой вырезаны все html теги.htmlescape– строка в которой экранированы все html теги.
- Дата
date– строка, в которой сохранена дата, без времени и внеменной зоны.datetime– строка, в которой сохранены дата, время и временная зона.
- Массивы
array– структурированный массив.collection– не структурированный массив.
- Деньги
money- деньги (массив с 3мя ключами: value - (double) значение, currency - (string(3)) валюта, pay_type - (int) способ оплаты).
Class динамических данных
Пример class'а для работы с динамическими данными, когда данные формируются из разных таблиц, и класс не привязан ни к одной конкретной таблице, возможно даже что данные берутся из solr или sphinx:
<?php
class Langs extends IODataObject
{
/**
* Разрешения на выполнение методов класса
*/
public static function rcp_rules()
{
$arr = parent::rcp_rules();
//$arr['static']['dbsearch2'] = 1;
//$arr['object']['getPage'] = 1;
return $arr;
}
/**
* Структура динамической таблицы
*/
public function struct()
{
return [
'fields' => [
'site_pkid' => [
'type' => 'sql',
'datatype' => 'long',
],
'code' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'lang' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'isDeleted' => [
'type' => 'sql',
'datatype' => 'boolean',
],
'gmtimeAdd' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'gmtimeChange' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'ugmtimeAdd' => [
'type' => 'sql',
'datatype' => 'long',
],
'ugmtimeChange' => [
'type' => 'sql',
'datatype' => 'long',
],
],
'primary' => [
0 => 'site_pkid',
1 => 'code',
],
];
}
public function create($params = null)
{
$arr = IOCore::call(
'io.class.cms20.site.dbsearch2',
[
'filter' => [
'pkid' => $this->site_pkid,
]
]
);
$res = xarr($arr, 'res', []);
$site = array_shift($res);
$config = @unserialize($site->config);
if(!isset($config['languages'][$this->code]))
{
$config['languages'][$this->code] = $this->lang;
$site->config = serialize($config);
$site->update();
$this->error_code = EIO_OK;
}
else
{
$this->error_code = EIO_RECORD_EXISTS;
}
}
public function delete($params = null)
{
$arr = IOCore::call(
'io.class.cms20.site.dbsearch2',
[
'filter' => [
'pkid' => $this->site_pkid,
]
]
);
$res = xarr($arr, 'res', []);
$site = array_shift($res);
$config = @unserialize($site->config);
//n_dump($arr);
//n_dump($site->config);
if(isset($config['languages'][$this->code]))
{
unset($config['languages'][$this->code]);
$site->config = serialize($config);
$site->update();
$this->error_str = '';
$this->error_code = EIO_OK;
}
else
{
$this->error_str = $this->code;
$this->error_code = EIO_NOTFOUND_OBJECT;
}
}
public static function dbsearch2($arr, $outclass = null, $tag = null)
{
$filter = xarr($arr, 'filter', []);
$start = xarr($arr, 'start', 0);
$limit = xarr($arr, 'limit', 1000);
$order = xarr($arr, 'order');
$out = xarr($arr, 'out', 'object');
$res = [];
$res['res'] = [];
$res['count'] = 0;
$site_pkid = xarr($filter, 'site_pkid', 0);
$code = xarr($filter, 'code');
$arr = IOCore::call(
'io.class.cms20.site.dbsearch2',
[
'filter' => [
'pkid' => $site_pkid,
],
]
);
//v2_dump($arr);
$rrr = xarr($arr, 'res', []);
$site = array_shift($rrr);
$languages = $site->languages;
//v_dump($site->languages);
//v_dump(xarr(unserialize($site->config), 'languages'));
if(count($languages) > 0)
{
if(gettype($languages) == 'array')
{
foreach($languages as $lang => $name)
{
if($code == null or $code == $lang)
{
if($out == 'array')
{
$res['res'][] = [
'info' => '',
'code' => $lang,
'lang' => $name,
'site_pkid' => $site_pkid,
];
}
elseif($out == 'object')
{
$obj = new Langs();
$obj->assign_arr([
'info' => '',
'code' => $lang,
'lang' => $name,
'site_pkid' => $site_pkid,
]);
$res['res'][] = $obj;
}
$res['count']++;
}
}
}
}
return $res;
}
}
Обязательные методы при написания class'а:
struct()- возращает структуру виртуальной таблицы с данными.
Обязательные для объявления поля:
pkidтип long.isDeletedтип boolean.gmtimeAddтип nohtml, хранит значение в формате rfc822.gmtimeChangeтип nohtml, хранит значение в формате rfc822.ugmtimeAddтип long, хранит значения в unix timestamp.ugmtimeChangeтип long, хранит значения в unix timestamp.
Каждое поле задается следующим описанием характеристик:
type- тип поля. Различаютsqlиproperty.default- значение по умолчанию.readonly- только чтение, запрещено редактирование и создание.nocreate- запрещена инициализация переменной при ее создании.noedit- запрещено редактирование переменной, но при создании ее можно инициировать.datatype- тип данных поля.struct- структура поля (используется для массивов).noKeys- сохранять массив без сохранения ключей (для type = array).func- название функции-обработчика значения переменной.
Поддерживаемые типы данных:
- Целочисленные
int,integer– 32-битное знаковое целое.long– 64-битное знаковое целое.
- Вещественные
long– действительное число.double,float,real– число с плавающей запятой.
- Логические
bool,booleanлогический тип.
- Строки
string– строка текста.html– строка, обработанная командой purify (безопасная для хранения html данные).nohtml– строка из которой вырезаны все html теги.htmlescape– строка в которой экранированы все html теги.
- Дата
date– строка, в которой сохранена дата, без времени и внеменной зоны.datetime– строка, в которой сохранены дата, время и временная зона.
- Массивы
array– структурированный массив.collection– не структурированный массив.
- Деньги
money- деньги (массив с 3мя ключами: value - (double) значение, currency - (string(3)) валюта, pay_type - (int) способ оплаты).
Методы класса
Метод rcp_rules()
Данный метод возращает разрешенные методы, которые можно запускать удаленно с других проектов.
Используется в class'ах, наследуемых от IODBObject, IOMongoObject и IODataObject.
/**
* Разрешения на выполнение методов класса
*/
public static function rcp_rules()
{
$arr = parent::rcp_rules();
//$arr['static']['dbsearch2'] = 1;
//$arr['object']['getPage'] = 1;
return $arr;
}
Метод tablename()
При наследовании от IODBObject, данный метод возращает имя таблицы базы данных.
При наследовании от IOMongoObject, данный метод возращает имя коллекции (таблицы) базы данных.
Используется в class'ах, наследуемых от IODBObject и IOMongoObject.
/**
* Название таблицы в базе данных
*/
public function tablename()
{
// для class'а, наследуемого от IODBObject
return "`".MYSQL_DB."`.`example`";
// для class'а, наследуемого от IOMongoObject
return MONGO_DATABASE.'.example';
}
Метод struct()
При наследовании от IODBObject, данный метод возращает структуру таблицы.
При наследовании от IOMongoObject, данный метод возращает структуру коллекции (таблицы).
При наследовании от IOMongoObject_Array, данный метод возращает структуру поля коллекции (таблицы) базы данных.
При наследовании от IODataObject, данный метод возращает структуру виртуальной таблицы с данными.
/**
* Структура таблицы
*/
public function struct()
{
return [
'fields' => [
/*
type:
- sql (поле в бд)
- property (динамическое поле, не записывается в базу)
datatype:
- int, integer, long
- double, float, real
- bool, boolean
- string
- nohtml
- date
- datetime
- array
- collection
- money
default: - значение по умолчанию
func: - функция динамического поля
*/
'pkid' => [
'type' => 'sql',
'func' => 'pkid',
'datatype' => 'long',
],
'company_pkid' => [
'type' => 'sql',
'datatype' => 'long',
],
'typeInt' => [
'type' => 'sql',
'datatype' => 'int',
'default' => 0,
],
'typeLong' => [
'type' => 'sql',
'datatype' => 'long',
'default' => 0,
],
'typeDouble' => [
'type' => 'sql',
'datatype' => 'double',
'default' => 0,
],
'typeBool' => [
'type' => 'sql',
'datatype' => 'boolean',
'default' => false,
],
'typeString' => [
'type' => 'sql',
'datatype' => 'string',
],
'typeNohtml' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'typeDate' => [
'type' => 'sql',
'datatype' => 'date',
],
'typeCollection' => [
'type' => 'sql',
'datatype' => 'collection',
],
'typeArray' => [
'type' => 'sql',
'datatype' => 'array',
'struct' => 'long',
'noKeys' => 1,
],
'typeArray2' => [
'type' => 'sql',
'datatype' => 'array',
'default' => [],
'struct' => [
'fieldLong' => [
'datatype' => 'long',
'default' => 0,
],
'fieldArray' => [
'datatype' => 'array',
'struct' => 'long',
'noKeys' => 1,
'default' => [1, 2, 3],
],
'fieldMoney' => [
'datatype' => 'money',
'default' => [
'value' => 0,
'currency' => 'KZT',
],
],
'fieldString' => [
'datatype' => 'nohtml',
'default' => 'строка по умолчанию',
],
],
'noKeys' => 1,
],
'typeProperty1' => [ // value from function property1()
'type' => 'sql',
'datatype' => 'long',
'func' => 'property1',
],
'typeProperty2' => [ // value from function property2()
'type' => 'sql',
'datatype' => 'long',
'func' => 'property2',
],
'typeMoney' => [
'type' => 'sql',
'datatype' => 'money',
],
'isDeleted' => [
'type' => 'sql',
'datatype' => 'boolean',
],
'gmtimeAdd' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'gmtimeChange' => [
'type' => 'sql',
'datatype' => 'nohtml',
],
'ugmtimeAdd' => [
'type' => 'sql',
'datatype' => 'long',
],
'ugmtimeChange' => [
'type' => 'sql',
'datatype' => 'long',
],
],
'primary' => [
0 => 'pkid',
],
];
}
У каждого объекта есть обязательные параметры, которые не переопределить функцией struct():
isDeleted(bool).isDraft(bool).txVersion(long) – версия документа, при каждом изменении она увеличивается на единицу. Запретить изменение можно через параметрchangeVersion.gmtimeAdd(nohtml).gmtimeChange(nohtml).ugmtimeChange(int).ugmtimeAdd(int).
Массивы
В приведенном ниже коде описывается массив, элементами которого будут целочисленные 64-битные знаковые числа. Если массив не задан, то по умолчанию сохранится null.
'typeArray' => [
'type' => 'sql',
'datatype' => 'array',
'struct' => 'long',
'default' => null,
],
Параметр noKeys
Если указать параметр noKeys, то ключи массива сохранятся не будут.
'typeArray' => [
'type' => 'sql',
'datatype' => 'array',
'struct' => 'long',
'noKeys' => 1,
'default' => null,
],
Вместо значений a, b, c, d в базе сохранятся значения 0, 1, 2, 3.
// Массив из чисел
$c->typeArray = [
'a' => 1,
'b' => 2,
'c' => 3,
'd' => 4,
];
/*
В базе будет
"typeArray": {
"0": NumberLong(1),
"1": NumberLong(2),
"2": NumberLong(3),
"3": NumberLong(4),
}
*/
Подмассивы
Фреймворк может хранить подмассивы как элементы массива. Это задается с помощью параметра struct при описании массива.
К примеру структура данных выглядит следующим образом:
'typeArray2' => [
'type' => 'sql',
'datatype' => 'array',
'struct' => [
'fieldLong' => [
'datatype' => 'long',
'default' => 0,
],
'fieldArray' => [
'datatype' => 'array',
'struct' => 'long',
'noKeys' => 1,
'default' => [1, 2, 3],
],
'fieldMoney' => [
'datatype' => 'money',
'default' => [
'value' => 0,
'currency'=>'KZT',
],
],
'fieldString' => [
'datatype' => 'nohtml',
'default' => 'строка по умолчанию',
],
],
'noKeys' => 1,
],
Если сохранить данные в массив:
$c->typeArray2 = [
[
'fieldString' => 'Это строка <br/>!',
'fieldMoney' => [
'value' => 10,
'currency' => 'KZT',
],
'fieldLong' => 10,
'fieldArray' => [1, 2, 3, 4, 5],
],
'second' => [
'fieldArray' => [
'a' => 1,
],
],
[],
];
То в mongo сохранятся следующие данные:
/*
"typeArray2": {
"0": {
"fieldLong": NumberLong(10),
"fieldArray": {
"0": NumberLong(1),
"1": NumberLong(2),
"2": NumberLong(3),
"3": NumberLong(4),
"4": NumberLong(5)
},
"fieldMoney": {
"value": NumberInt(10),
"currency": "KZT"
},
"fieldString": "Это строка !"
},
"1": {
"fieldLong": NumberLong(0),
"fieldArray": {
"0": NumberLong(1)
},
"fieldMoney": {
"value": NumberInt(0),
"currency": "KZT"
},
"fieldString": "строка по умолчанию"
},
"2": {
"fieldLong": NumberLong(0),
"fieldArray": {
"0": NumberLong(1),
"1": NumberLong(2),
"2": NumberLong(3)
},
"fieldMoney": {
"value": NumberInt(0),
"currency": "KZT"
},
"fieldString": "строка по умолчанию"
}
},
*/
Свойства (type property)
'typeProperty1' => [
'type' => 'property',
'datatype' => 'long',
'func' => 'property1',
],
Метод params()
Данный метод возращает имя связываемого class'а и связываемого с ним поля.
Используется в class'ах, наследуемых от IOMongoObject_Array.
/**
* Параметры класса
*/
public function params()
{
return [
'class' => 'app.class.categoryFieldsList',
'field' => 'data',
];
}
create()
Добавление записи в базу данных.
// обращение к классу
$c = IOCore::instance('app.class.example');
// NumberInt(10)
$c->typeInt = 10;
// NumberLong(10)
$c->typeLong = 10;
// 10
$c->typeDouble = 10;
// true
$c->typeBool = true;
// string("10")
$c->typeString = 10;
// string("i am a nohtml param")
$c->typeNohtml = 'i am a nohtml param';
// "10"
$c->typeDate = time();
// Сохранить время в поясе 'Asia/Almaty'
//ISODate("2014-02-02T06:00:00.0Z")
$c->typeDate = iostrtodate(
DATE_RFC822,
'2014-02-02 12:00:00',
'Asia/Almaty',
date_default_timezone_get()
);
// Сохранить текущее время по центральному европейскому времени
//ISODate("2014-02-02T06:00:00.0Z"
$c->typeDate = iostrtodate(
DATE_RFC822,
'2014-02-02 12:00:00',
'CET',
date_default_timezone_get()
);
// Сохранить текущее время по гринвичу
//ISODate("2014-02-02T06:00:00.0Z")
$c->typeDate = iostrtodate(
DATE_RFC822,
'2014-02-02 12:00:00',
'UTC',
date_default_timezone_get()
);
// Коллекция (для mongodb и динамической таблицы)
$c->typeCollection = [
'ru' => 'Russian',
'kz' => 'Kazakh',
'en' => 'English',
'numeric' => 123,
];
/*
В базе будет
"typeCollection": {
"ru": string(1),
"kz": string(2),
"en": string(3),
"numeric": NumberLong(123)
}
*/
// Массив из чисел (для mongodb и динамической таблицы)
$c->typeArray = [1, 2, 3, 4, 5];
/*
В базе будет
"typeArray": {
"0": NumberLong(1),
"1": NumberLong(2),
"2": NumberLong(3),
"3": NumberLong(4),
"4": NumberLong(5)
}
*/
// Массив с параметром noKeys=1 в структуре (для mongodb)
$c->typeArray = [
'a' => 1,
'b' => 2,
'c' => 3,
'd' => 4,
];
/*
При noKeys=1 вместо ключей a, b, c, d в базе сохранятся ключи 0, 1, 2, 3
В базе будет
"typeArray": {
"0": NumberLong(1),
"1": NumberLong(2),
"2": NumberLong(3),
"3": NumberLong(4)
}
*/
// Массив строк (для mongodb и динамической таблицы)
$c->typeArray = ['ru', 'kz', 'en'];
/*
В базе будет
"typeArray": {
"0": string("ru"),
"1": string("kz"),
"2": string("en")
}
*/
// Структурированный массив (для mongodb и динамической таблицы)
$c->typeArray2 = [
[
'fieldLong' => 1,
],
'second' => [
'fieldLong' => 2,
'fieldArray' => [4, 5],
'fieldMoney' => [
'value' => 100,
'currency' => 'KZT',
],
'fieldString' => 'hello',
],
[],
];
/*
В базе будет
"typeArray2": {
"0": {
"fieldLong": NumberLong(1),
"fieldArray": {
"0": NumberLong(1),
"1": NumberLong(2),
"2": NumberLong(3)
},
"fieldMoney": {
"value": NumberLong(0),
"currency": string("KZT"),
"pay_type": NumberLong(0)
},
"fieldString" => string("строка по умолчанию")
},
"1": {
"fieldLong": NumberLong(2),
"fieldArray": {
"0": NumberLong(4),
"1": NumberLong(5)
},
"fieldMoney": {
"value": NumberLong(100),
"currency": string("KZT"),
"pay_type": NumberLong(0)
},
"fieldString" => string("hello")
},
"2": {
"fieldLong": NumberLong(0),
"fieldArray": {
"0": NumberLong(1),
"1": NumberLong(2),
"2": NumberLong(3)
},
"fieldMoney": {
"value": NumberLong(0),
"currency": string("KZT"),
"pay_type": NumberLong(0)
},
"fieldString" => string("строка по умолчанию")
}
}
*/
// Денежный тип (для mongodb и динамической таблицы)
$c->typeMoney = [
'value' => 10,
'currency' => 'KZT',
];
/*
В базе будет
"typeMoney": {
"value": "10",
"currency": "KZT",
"pay_type": 0
}
*/
$r = $c->create();
v_dump($r);
v_dump($c->error_code);
v_dump($c->error_str);
v_dump($c->__mongo_data); // для mongo class
Код (номер) ошибки будет сохранен в переменной $c->error_code. Подробнее о кодах ошибок.
Текст ошибки будет сохранен в переменной $c->error_str.
В mongo class данные, которые были отправлены в базу, будут сохранены в переменной $c->__mongo_data.
По умолчанию поля gmtimeAdd, gmtimeChange, ugmtimeAdd, ugmtimeChange генерируются автоматически и не дают возможности их переопределить, указав свои данные. Но если это необходимо, то можно воспользоваться следующей конструкцией:
$c->create(['w' => 1]);
Метод create может принимать следующие параметры:
| Название | Описание | По умолчанию |
|---|---|---|
w | На сколько реплик записать запрос. Если равен нулю, то запрос отправляется в монго и система не ждет подтверждения записи | 1 |
j | Журналировать запрос | true |
gmtimeAdd | Переписать дату создания объекта | true |
gmtimeChange | Переписать дату изменения объекта | true |
safe | Читайте в официальной документации по MongoDB | true |
changeVersion | Менять версию объекта или нет | true |
insert_or_update | Параметр метода update. Если нет элемента, создать его? | 0 |
Метод dbsearch2()
У каждого класса есть данная предустановленная функция поиска по его таблице/коллекции.
Параметры функции:
filterorderlimitposout
Параметр filter
Массив параметров фильтра.
В фильтре можно указывать операторы сравнения. Они указываются в ключе фильтра в качестве префикса:
=- равно (по умолчанию)!=- не равно>- больше>=- больше или равно<- меньше<=- меньше или равно~- is null!~- is not null%- содержит
Пример:
[
'filter' => [
'%text' => 'hel',
],
]
Также можно разделять фильтр на or и and.
Пример:
[
'filter' => [
'$or' => [
[
'%text' => 'hel',
],
[
'%text' => 'lo',
],
],
],
]
| Запрос | Аналог mysql |
|---|---|
| [ ‘a’ => 2, ] | select * from table where a = 2 |
| [ ‘!=a’ => 2, ] | select * from table where a != 2 |
| [ ‘a’ => [1, 2, 3, 4], ] | select * from table where a in (1, 2, 3, 4) |
| [ ‘!=a’ => [1, 2, 3, 4], ] | select * from table where not (a in (1, 2, 3, 4)) |
| [ '$or' => [ ['typeInt' => 2,], ['typeInt' => 1,], ], ] | select * from table where typeInt = 2 or typeInt = 1 |
| [ '$and' => [ [ '$or' => [ ['typeInt' => 2,], ['typeInt' => 1,], ], ], [ '$or' => [ ['typeDouble' => 3,], ['typeDouble' => 2,], ], ], ], ] | select * from table where (typeInt = 2 or typeInt = 1) and (typeDouble = 3 or typeDouble = 2) |
Параметр order
Массив параметров порядка сортировки, где ключ - это сортируемое поле, значение - asc (по возрастанию), desc (по убыванию).
Пример:
[
'order' => [
'pkid' => 'asc',
'text' => 'desc',
],
]
Параметр limit
Лимит записей (по умолчанию 1000). Сколько вывести записей.
Пример:
[
'limit' => 25,
]
Параметр start
Позиция поиска (по умолчанию 0). Откуда начинать.
[
'start' => 25,
]
Параметр out
Тип возвращаемых данных.
Есть 2 значения этого поля:
array- записи в виде массива.object- записи в виде объекта экземпляра класса (по умолчанию).
[
'out' => 'array',
]
Property методы (свойства)
Свойства – это специальные переменные, которые реально значения не хранят, и формируются на основе данных class'а.
Пример:
Объявим в структуре class'а новое поле:
'typeProperty1' => [
'type' => 'property',
'datatype' => 'long',
'func' => 'property1',
],
'typeProperty2' => [
'type' => 'property',
'datatype' => 'long',
'func' => 'property2',
],
И методы в class'е:
public function property1($method, $name, $value)
{
v_dump($method . " " . $name . " " .$value );
if($method == 'set')
{
if(!isset($this->__data[$name])) $this->__data[$name] = $value;
else $this->__data[$name] += $value;
}
elseif($method == 'get')
{
// Ничего не делаем, пусть значение будет то же
}
}
public function property2($method, $name, $value)
{
v_dump($method . " " . $name . " " .$value );
if($method == 'set')
{
// Ничего не делаем, пусть значение будет то же
}
elseif($method == 'get')
{
$this->__data[$name] = $this->typeProperty1 * 2;
}
}
Если выполнить следующие команды:
$c->typeProperty1 = 1; // в typeProperty1 будет 1
$c->typeProperty1 = 2; // в typeProperty1 будет 3
$c->typeProperty1 = 3; // в typeProperty1 будет 4
v_dump($c->typeProperty1); // Выведет 6
v_dump($c->typeProperty2); // Выведет 12
При выполнении этих команд будет постоянно вызываться метод property1 class'а. При сохранении значения, старое значение будет увеличиваться на величину нового значение. При получении $c->typeProperty2 вызовется метод property2 и установит новое значение для поля $c->typeProperty2.
При установке нового значения вызовется метод property1 с параметрами $method = 'set', $name = 'typeProperty1'. Это означает, что идет установка значения поля $c->typeProperty1, При получении, аналогично вызовется метод property1, только с параметрами $method = 'get'. Т.к. функция ничего не устанавливает, на экран выведется null.
Объявим в class'е поля, но вместо type = 'property' запишем type = 'sql'. Теперь новые значения будут сохранятmся в базе данных. Но метод set в функциях вызываться не будет, только метод get.
'typeProperty1' => [
'type' => 'sql',
'datatype' => 'long',
'func' => 'property1',
],
'typeProperty2' => [
'type' => 'sql',
'datatype' => 'long',
'func' => 'property2',
],
Выполним команды:
$c->typeProperty1 = 1; // в typeProperty1 будет 1
$c->typeProperty1 = 6; // в typeProperty1 будет 6
v_dump($c->typeProperty1); // Выведет 6
v_dump($c->typeProperty2); // Выведет 12
Операции с class
Получение записей запроса в виде объектов
$r = IOCore::call(
'app.class.example.dbsearch2',
[
'filter' => [
'pkid' => 1,
'isDeleted' => false,
],
'limit' => 1000,
]
);
$res = xarr($r, 'res', []);
foreach($res as $obj)
{
v2_dump($obj);
}
Получение записей запроса в виде массивов
$r = IOCore::call(
'app.class.example.dbsearch2',
[
'filter' => [
'pkid' => 1,
'isDeleted' => false,
],
'limit' => 1000,
'out' => 'array',
]
);
$res = xarr($r, 'res', []);
foreach($res as $obj)
{
v_dump($obj);
}
Получение записи запроса в виде объекта
$r = IOCore::call(
'app.class.example.dbsearch2',
[
'filter' => [
'pkid' => 1,
'isDeleted' => false,
],
'limit' => 1,
]
);
$res = xarr($r, 'res', []);
$obj = array_shift($res);
v2_dump($obj);
Получение записи запроса в виде массива
$r = IOCore::call(
'app.class.example.dbsearch2',
[
'filter' => [
'pkid' => 1,
'isDeleted' => false,
],
'limit' => 1,
'out' => 'array',
]
);
$res = xarr($r, 'res', []);
$obj = array_shift($res);
v_dump($obj);
Обновление записей запроса через объекты
$r = IOCore::call(
'app.class.example.dbsearch2',
[
'filter' => [
'pkid' => 1,
'isDeleted' => false,
],
'limit' => 1000,
]
);
$res = xarr($r, 'res', []);
foreach($res as $obj)
{
$bj->param_string = 'hi garden!';
$obj->update();
}
По умолчанию поля gmtimeAdd, gmtimeChange, ugmtimeAdd, ugmtimeChange генерируются автоматически и не дают возможности их переопределить, указав свои данные. Но если это необходимо, то можно воспользоваться следующей конструкцией:
$c->update(['w' => 1]);
Обновление записи запроса через объект
$r = IOCore::call(
'app.class.example.dbsearch2',
[
'filter' => [
'pkid' => 1,
'isDeleted' => false,
],
'limit' => 1,
]
);
$res = xarr($r, 'res', []);
$obj = array_shift($res);
$bj->param_string = 'hi garden!';
$obj->update();
По умолчанию поля gmtimeAdd, gmtimeChange, ugmtimeAdd, ugmtimeChange генерируются автоматически и не дают возможности их переопределить, указав свои данные. Но если это необходимо, то можно воспользоваться следующей конструкцией:
$c->update(['w' => 1]);
Удаление записей запроса через объекты
$r = IOCore::call(
'app.class.example.dbsearch2',
[
'filter' => [
'pkid' => 1,
'isDeleted' => false,
],
'limit' => 1000,
]
);
$res = xarr($r, 'res', []);
foreach($res as $obj)
{
$obj->delete();
}
Удаление записи запроса через объект
$r = IOCore::call(
'app.class.example.dbsearch2',
[
'filter' => [
'pkid' => 1,
'isDeleted' => false,
],
'limit' => 1,
]
);
$res = xarr($r, 'res', []);
$obj = array_shift($res);
$obj->delete();
Получение количества записей запроса
$r = IOCore::call(
'app.class.example.dbsearch2',
[
'filter' => [
'pkid' => 1,
'isDeleted' => false,
],
'limit' => 1,
'out' => 'array',
]
);
$count = xarr($r, 'count', 0);
v_dump($count);
Прочие методы класса
Некоторые методы работают только в MongoDB...
| Название | Тип | Описание |
|---|---|---|
| create | dynamic | Создать объект. |
| update | dynamic | Обновить объект. |
| delete | dynamic | Удалить объект. |
| setDeleted | dynamic | Установить isDeleted объекта в true и обновить запись. |
| setRestored | dynamic | Установить isDeleted объекта в false и обновить запись. |
| dbUpdate | static | Обновить записи в MongoDB. Атомарная операция. |
| dbDelete | static | Удалить записи массово. |
| findAndModify | static | Поиск записей в MongoDB, изменение и возврат их в качестве результата. Обычно происходит поиск одной записи. Атомарная операция. |
| dbGroupBy | static | Аналог MySQL функции Group By. |
| dbsearch2 | static | Поиск в базе данных. |
| dbgetlast | static | Получение последних измененных записей по полю gmtimeChange. |
| getByPkid | static | Получение записи по полю pkid. |
| dbDistinct | static | ... |
| dbMapReduce | static | ... |
dynamicметоды можно вызывать только через экземпляр класса.staticметоды можно вызывать только через методIOCore::call().