Примеры
В данном разделе приведены некоторые типовые примеры работы API модуля simai.storage с пояснениями.
Примеры работы с классами второго уровня
Произведем несколько стандартных операций с хранилищем. Если что-то в описанных примерах непонятно, то нужно смотреть раздел документации «Классы 2 уровня».
Создаем новое хранилище:
$storage_id = \SIMAI\Storage\Storage::add( array( 'STORAGE_ID'=>'test_storage', // код хранилища (обязателен) 'ACTIVE'=>'Y', // активность хранилища 'SORT'=>'100', // показатель сортировки 'SITE_ID'=>array('s1'), // привязка к сайтам (обязательна) 'ACCESS'=>array('1'=>'X', '2'=>'R'), // уровень доступа групп 'ELEMENT_ACCESS'=>'N', // возможность раздельного доступа для элементов 'LOG'=>'N', // логирование действия хранилищ ) ); // Системные свойства заголовка и шаблонов URL создались автоматически, поскольку мы не указали обратного в параметрах
//Все ошибки можно увидеть в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
Задаем для нашего хранилища свойство «заголовок» – это свойство системное и создано автоматически:
$res = \SIMAI\Storage\Property::setPropValue( 'test_storage', // код хранилища 0, // параметр $element_id=0 означает, что значение свойства задается для самого хранилища, а не его элемента 'TITLE', // код свойства array('ru' => 'Новое тестовое хранилище', 'en' => 'New test storage') // заголовок на разных языках ); //Все ошибки можно увидеть в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
Для записей хранилища создадим еще одно свойство - файловое для присвоения записям картинки:
$file_property_id = \SIMAI\Storage\Property::add( array( 'STORAGE_ID'=>'test_storage', // код хранилища 'CODE'=>'PICTURE', // код свойства 'TYPE'=>'file', // тип свойства 'SETTINGS'=>array( 'file_type' => 'I', // тип файлов - изображения 'file_ext' => 'jpg,jpeg,png,gif,bmp', // допустимые расширения ), // набор доп. параметров, для каждого типа свойств этот набор свой 'MULTIPLE'=>'N', // не множественное свойство 'MULTILANGUAGE'=>'N', // не мультиязычное свойство 'SORT'=>'200', // показатель сортировки 'STORAGE_USE'=>'N', // не используется для самого хранилища 'SECTION_USE'=>'N', // не используется для разделов 'ITEM_USE'=>'Y', // используется для записей 'SYSTEM'=>'N', // свойство не системное 'LANGUAGE'=>array('ru'=>'Картинка', 'en'=>'Picture'), // языковые заголовки свойства ) ); //Все ошибки можно увидеть в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
Добавим в наше хранилище раздел, установим его заголовок и обновим для него поля сортировки и поиска:
$section_id = \SIMAI\Storage\Element::add( 'test_storage', // код хранилища array( 'ACTIVE'=>'Y', // активность элемента 'SORT'=>'500', // показатель сортировки 'TYPE'=>'S', // это раздел, а не запись ) ); // Поскольку это раздел, то \SIMAI\Storage\Element::tree_resort вызовется из этого добавления автоматически // Установим заголовок раздела $res = \SIMAI\Storage\Property::setPropValue( 'test_storage', // код хранилища $section_id, // ид раздела 'TITLE', // код свойства array('ru' => 'Новый тестовый раздел', 'en' => 'New test section') // заголовки на разных языках ); // Поля сортировки и поиска для таблицы элементов нужно обновлять принудительно \SIMAI\Storage\Property::UpdateStorageElementSorts('test_storage', $section_id); // заполняем поля сортировки \SIMAI\Storage\Search::UpdateStorageElementSearch('test_storage', $section_id); // заполняем поля поиска
//Все ошибки можно увидеть в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
Теперь добавим в этот раздел новую запись, установим для заголовок и картинку, после чего обновим для нее поля сортировки и поиска:
// Добавим новую запись $item_id = \SIMAI\Storage\Element::add( 'test_storage', // код хранилища array( 'ACTIVE'=>'Y', // активность элемента 'SORT'=>'100', // показатель сортировки 'TYPE'=>'I', // это запись, а не раздел 'PARENT_ID'=>array($section_id), // привязки к род. разделам ) ); // Установим заголовок записи $res = \SIMAI\Storage\Property::setPropValue( 'test_storage', // код хранилища $item_id, // ид записи 'TITLE', // код свойства array('ru' => 'Новая тестовая запись', 'en' => 'New test item') // заголовки на разных языках ); // Присвоим значение файловому свойству для новой записи (загрузим картинку, допустим, в виде файла /upload/abc.jpg) $res = \SIMAI\Storage\Property::setPropValue( 'test_storage', // код хранилища $item_id, // ид записи 'PICTURE', // код свойства array_merge( CFile::MakeFileArray($_SERVER["DOCUMENT_ROOT"]."/upload/abc.jpg"), array("module_id" => "simai.storage") ) // значение - файловый массив ); \SIMAI\Storage\Property::UpdateStorageElementSorts('test_storage', $item_id); // заполняем поля сортировки \SIMAI\Storage\Search::UpdateStorageElementSearch('test_storage', $item_id); // заполняем поля поиска
//Все ошибки можно увидеть в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
Предположим, что у нас в хранилище уже много элементов. Сделаем выборки:
$res_elements = \SIMAI\Storage\Element::getList( 'test_storage', // код хранилища array( 'filter' => array( 'TYPE' => 'I', // выбрать только записи '%PARENT_IDS' => array('-1-', '-2-'), // выбрать только принадлежащие к разделам с идами 4 и 5 ), 'order' => array( 'SORT' => 'asc', // сортировать по показателю сортировки ), 'select' => array( 'ELEMENT_ID', 'ACTIVE', // в выборке только поля ида и активности ), ) // остальные параметры по умолчанию ); while ($el_data = $res_elements ->fetch()) { echo '<pre>'; print_r($el_data); echo '</pre>'; } //Все ошибки можно увидеть в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
$res_elements = \SIMAI\Storage\Element::getList( 'test_storage', // код хранилища array( 'filter' => array( 'ACTIVE' => 'Y', // выбрать только активные '%PROP_TITLE.PROP_TITLE' => 'тест', // выбрать только элементы, в заголовке которых есть подстрока «тест» '=PROP_TITLE.LANGUAGE_ID' => array('ru', ''), // фильтрация по свойству заголовка только среди русских и неязыковых значений ), 'order' => array( 'PROP_TITLE' => 'asc', // сортировать по значениям свойства TITLE ), 'group' => array( 'ELEMENT_ID', // группировать по ELEMENT_ID чтобы избежать дублирования строк выборки из-за подключения таблицы свойств ), ), array('TITLE'), // в фильтрах используется свойство TITLE false, // не проверять принадлежность к текущему сайту true, // проверять права доступа к элементам 'ru' // сортировка по русскоязычным значениям ); while ($el_data = $res_elements ->fetch()) { echo '<pre>'; print_r($el_data); echo '</pre>'; } //Все ошибки можно увидеть в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
Обратите внимание, что выборки по элементам не возвращают значений свойств. Их мы должны получить дополнительными запросами. Допустим, мы хотим увидеть картинку некой записи.
// Выберем значение файлового свойства из элемента (вернется массив, рассортированный по кодам свойств) $values = \SIMAI\Storage\Property::GetPropValues( 'test_storage', // код хранилища $item_id, // ид записи array('PICTURE'), // код свойства LANGUAGE_ID // Свойство не языковое, но установленный язык упростит возвращаемое значение ); // Выведем полученную картинку через методы Универсальных свойств CModule::IncludeModule("simai.property"); \SIMAI\Property::view( 'file', // тип универсального свойства '', // шаблон универсального свойства, в нашем случае .default $values['PICTURE'], // файловый ид картинки array() // параметры универсального свойства, в данном случае - пустой массив ); //Все ошибки можно увидеть в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
Работа с классами первого уровня
Классы первого уровня, такие как StorageTable, PropertyTable, PropertyLanTable и т.д. в основном наследуются от Bitrix\Main\Entity\DataManager с некоторыми дополнениями, поэтому к ним применимы стандартные приемы работы с ORM в ядре D7.
Учебный курс по ORM можно найти по ссылке
https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43&CHAPTER_ID=05748
Сущности, определяемые этими классами, лежат в пространстве имен SIMAI\Storage, соответственно обращение к базовым классам и их методам должно включать указание пространства имен. Например, \SIMAI\Storage\StorageTable::add()
Несколько особняком стоят сущности, создаваемые для таблицы свойств и таблицы элементов каждого хранилища. Они создаются непосредственно в процессе работы, поэтому не принадлежат к пространству имен SIMAI.
Рассмотрим пример работы с сущностью таблицы элементов методами ORM.
Допустим, у нас стоит задача посчитать количество элементов хранилища test_storage с ELEMENT_ID<100 и мы по какой-то причине не хотим использовать класс Element.
В этом случае мы можем работать непосредственно с сущностью элемента, предварительно создав ее:
// посчитаем, сколько в хранилище элементов с ELEMENT_ID<100
// сначала создадим сущность, опирающуюся на таблицу элементов $el_entity = \SIMAI\Storage\StorageTable::compileElementsEntity('test_storage'); // создадим сущность, опирающуюся на таблицу элементов хранилища test_storage if ($el_entity) { $el_entity_data_class = $el_entity->getDataClass(); // имя базового класса сущности $res = $el_entity_data_class::getList(array( 'select' => array('CNT'), // в выборке только виртуальное поле, содержащее COUNT(ELEMENT_ID), заданное в runtime 'filter' => array('<ELEMENT_ID' => 10), // условие 'runtime' => array( new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(ELEMENT_ID)') // создание для выборки виртуального поля, содержащего COUNT(ELEMENT_ID) ) )); if ($arr = $res->fetch()) { $count_els = intval($arr['CNT']); // получаем результат подсчета echo $count_els; } } //Все ошибки можно увидеть в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
Работа с событиями (с примерами)
События, определяемые методами классов второго уровня, работают через \Bitrix\Main\EventManager
Список событий:
Событие |
Параметры |
Описание |
События класса Storage |
||
OnBeforeStorageAdd |
array $fields |
Вызывается перед добавлением хранилища, может быть использовано для отмены или модификации данных. |
OnAfterStorageAdd |
string $primary array $fields |
Вызывается после добавления хранилища. |
OnBeforeStorageUpdate |
string $primary array $fields |
Вызывается перед обновлением хранилища, может быть использовано для отмены или модификации данных. |
OnAfterStorageUpdate |
string $primary array $fields |
Вызывается после обновления хранилища. |
OnBeforeStorageDelete |
string $primary |
Вызывается перед удалением хранилища. |
OnAfterStorageDelete |
string $primary |
Вызывается после удаления хранилища. |
События класса Element |
||
OnBeforeElementAdd |
string $storage_id array $fields |
Вызывается перед добавлением элемента хранилища, может быть использовано для отмены или модификации данных. |
OnAfterElementAdd |
string $storage_id string $primary array $fields |
Вызывается после добавления элемента хранилища. |
OnBeforeElementUpdate |
string $storage_id string $primary array $fields |
Вызывается перед обновлением элемента хранилища, может быть использовано для отмены или модификации данных. |
OnAfterElementUpdate |
string $storage_id string $primary array $fields |
Вызывается после обновления элемента хранилища. |
OnBeforeElementDelete |
string $storage_id string $primary |
Вызывается перед удалением элемента хранилища. |
OnAfterElementDelete |
string $storage_id string $primary |
Вызывается после удаления элемента хранилища. |
События класса Property |
||
OnBeforePropertyAdd |
array $fields |
Вызывается перед добавлением свойства, может быть использовано для отмены или модификации данных. |
OnAfterPropertyAdd |
string $primary array $fields |
Вызывается после добавления свойства. |
OnBeforePropertyUpdate |
string $primary array $fields |
Вызывается перед обновлением свойства, может быть использовано для отмены или модификации данных. |
OnAfterPropertyUpdate |
string $primary array $fields |
Вызывается после обновления свойства. |
OnBeforePropertyDelete |
string $primary |
Вызывается перед удалением свойства. |
OnAfterPropertyDelete |
string $primary |
Вызывается после удаления свойства. |
События класса Set |
||
OnBeforeSetAdd |
array $fields |
Вызывается перед добавлением набора, может быть использовано для отмены или модификации данных. |
OnAfterSetAdd |
string $primary array $fields |
Вызывается после добавления набора. |
OnBeforeSetUpdate |
string $primary array $fields |
Вызывается перед обновлением набора, может быть использовано для отмены или модификации данных. |
OnAfterSetUpdate |
string $primary array $fields |
Вызывается после обновления набора. |
OnBeforeSetDelete |
string $primary |
Вызывается перед удалением набора. |
OnAfterSetDelete |
string $primary |
Вызывается после удаления набора. |
Для примера рассмотрим работу с событиями при добавлении элемента.
Пример 1: запретим добавлять в хранилище test_storage элементы с показателем сортировки меньше 100 через событие OnBeforeElementAdd
//можно добавить обработчик, например, в init.php
// запретим добавлять в хранилище test_storage элементы с показателем сортировки меньше 100 через событие OnBeforeElementAdd $eventManager = \Bitrix\Main\EventManager::getInstance(); $eventManager->addEventHandler( 'simai.storage', 'OnBeforeElementAdd', function (\Bitrix\Main\Event $event) { $storage_id = $event->getParameter('storage_id'); $data = $event->getParameter('fields'); //SUCCESS по умолчанию $result = new \Bitrix\Main\EventResult($event->getEventType(), array('fields' => $data)); if ($storage_id == 'test_storage' && isset($data['SORT'])) { if ($data['SORT'] < 100) { //ERROR $result = new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::ERROR, new \Bitrix\Main\Error('No sorts less than 100!', 'SF_STORAGE_WRONG_ADD1'), 'simai.storage'); } } return $result; } ); |
Теперь если попробовать добавить в хранилище элемент с SORT<100, добавления не произойдет:
\SIMAI\Storage\Element::add( 'test_storage', // код хранилища array( 'ACTIVE'=>'Y', // активность элемента 'SORT'=>'50', // показатель сортировки меньше 100 'TYPE'=>'I', // это запись, а не раздел ) ); //Результат с ошибкой будет присутсвовать в массиве $GLOBALS['SF_STORAGE_ERRORS'] |
Пример 2: после добавления элемента запишем код хранилища и ид элемента в файл /upload/el.log
// после добавления элемента запишем код хранилища и ид элемента в файл /upload/el.log $eventManager = \Bitrix\Main\EventManager::getInstance(); $eventManager->addEventHandler( 'simai.storage', 'OnAfterElementAdd', function (\Bitrix\Main\Event $event) { $storage_id = $event->getParameter('storage_id'); $primary = $event->getParameter('primary'); $data = $event->getParameter('fields'); if (@file_put_contents($_SERVER["DOCUMENT_ROOT"]."/upload/el.log", $storage_id.','.$primary)) { //SUCCESS $result = new \Bitrix\Main\EventResult($event->getEventType(), array('fields' => $data)); } else { //ERROR $result = new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::ERROR, new \Bitrix\Main\Error('testerr', 'SF_STORAGE_WRONG_ADD2'), 'simai.storage'); } return $result; } ); |
Что касается классов первого уровня, то к ним можно применять стандартные события Bitrix\Main\Entity\DataManager для соответсвующих сущностей.