Версия: 6.x
burger close
Модели

Общие сведения

Модели - это классы, с помощью которых можно получать полезные данные или полезный результат. В классах моделей реализован основной функционал системы. Классы моделей могут быть достаточно объемными по количеству кода, в отличие от контроллеров. В контроллерах производится вызов методов модели для формирования данных, которые передаются в шаблон отображения.

В ReadyScript существует 3 уровня абстракции по работе с данными:

  1. Низкий уровень. Выборка данных через SQL-запросы к БД с помощью класса RS::Db::Adapter. Не рекомендуем для использования.
  2. Средний уровень. Выборка данных с помощью класса RS::Orm::Request. Рекомендуем для использования в классах моделей(API).
  3. Высокий уровень. Выборка данных с помощью классов моделей (API). Приоритетно рекомендуем для использования во всех классах системы(контроллерах, других моделях).

Модели предоставляют высокий уровень абстракции для работы с данными. В ReadyScript существует ряд классов, которые рекомендуется использовать в качестве базовых для моделей.

BaseModel

Класс может быть использован в качестве базового для построения любого API, в котором возможны ошибки во время выполнения какой-либо операции. Реализует методы:

  • addError - Добавляет ошибку в список
  • hasError - Возвращает true, если имеются ошибки, иначе false.
  • getErrors - Возвращает полный список ошибок
  • cleanErrors - Очищает ошибки
  • getDisplayErrors - Возвращает информацию об ошибках для отправки браузеру в формате json.
  • getErrorsStr - Возвращает ошибки в виде строки
  • getFormErrors - Возвращает ошибки формы
  • getNonFormErrors - Возвращает ошибки, не связанные с формами
namespace ModuleName\Model;
{
public function uploadFile($post_file_array)
{
if ($post_file_array['error'] == UPLOAD_ERR_OK) {
//...
return true;
} else {
return $this->addError('Ошибка загрузки файла №'.$post_file_array['error']);
}
}
}

EntityList

Расширяет класс RS::Module::AbstractModel::BaseModel. Класс может быть использован для создания класса модели(API) для работы со списком ORM объектов.

Некоторые(частоиспользуемые) методы:

  • setFilter - Устанавливает фильтр для последующей выборки элементов
  • clearFilter - Очищает условия выборки
  • getList - Возвращает список объектов, согласно заданным раннее условиям
  • getListAsArray - Возвращает список массивов, согласно заданным раннее условиям
  • getListAsResource - Возвращает результат выборки, согласно заданным раннее условиям, в виде объекта RS::Db::Result
  • getListCount - Возвращает общее количество элементов, согласно условию.
  • getFirst - Возвращает первый элемент, согласно условию
  • getOneItem - Загружает из базы 1 элемент
  • getById - Возвращает элемент по id или псевдониму
  • getElement - Возвращает ORM объект, с которым работает данное API
  • save - Сохраняет элемент, с которым работает данное API, принимая значения из POST
  • del - Удаляет элементы, используя механизм orm-object'ов
  • multiUpdate - Обновляет свойства у группы объектов
  • addFilterControl - Устанавливает фильтры, от компонента RS::Html::Filter::Control
  • addTableControl - Устанавливает сортировку от компонента RS::Html::Table::Control

Полный список методов можно узнать в описании класса.

Пример модели, построенной на основе класса EntityList:

class ArticleApi extends \RS\Module\AbstractModel\EntityList
{
function __construct()
{
parent::__construct(new \Article\Model\Orm\Article,
array( //Параметры задаются согласно ПОММ
'aliasField' => 'alias', //Сообщаем модели, в каком свойстве находится символьный ID
'nameField' => 'title', //Сообщаем модели, в каком свойстве находится название объекта
'multisite' => true, //Сообщаем, что объект мультисайтовый, соответственно и API тоже должно быть мультисайтовым
'defaultOrder' => 'dateof DESC' //Указываем сортировку по-умолчанию для выборок
));
}
function setCrazyFilter()
{
//Здесь можно реализовать установку сложного фильтра
//Модель(API) существует, чтобы предоставить внешнему окружению простые и понятные методы,
//внутри которых происходят сложные операции
}
//... здесь можно дописывать любое количество произвольных методов, которые могут выполнять самые разные операции.
}
//Создаем экземпляр API для объектов \Article\Model\Orm\Article
$api = new ArticleApi();
//Начинаем пользоваться готовым API
//Вернет все статьи в виде ассоциативного массива.
//В качестве ключа будет idField, в качестве значения будет nameField
$assoc_array = $api->getSelectList();
//Устанавливаем значение фильтра, для последующей выборки
$api->setFilter(array(
array(
'title:%like%' => 'С Новым годом',
'|title' => 'С Рождеством'
),
'dateof:>' => '2013-01-01',
'user_id:in' => '1,2,3,4,5,6,7'
));
//Посмотрим на запрос, который сгенерирован после установки фильтра
echo $api->queryObj(); //Вернет: SELECT * FROM `readyscript`.`xuve_article` as A WHERE (`A`.`site_id` = '1') AND ( `A`.`title` LIKE '%С Новым годом%' OR `A`.`title` = 'С Рождеством') AND `A`.`dateof` > '2013-01-01' AND `A`.`user_id` IN (1,2,3,4,5,6,7) ORDER BY dateof DESC
$total_count = $api->getListCount(); //Вернет количество найденных элементов, для заданного выше условия
$list = $api->getList(); //Вернет массив найденных ORM объектов \Article\Model\Orm\Article
//Если идет POST с данными объекта \Article\Model\Orm\Article, то можно вызвать метод для его сохранения.
if ($api->save()) {
//Сохранение прошло успешно
} else {
//Произошли ошибки, выводим их
print_r($api->getErrors());
}

С моделью, расширяющей класс EntityList успешно взаимодействует CRUD-контроллер. Это означает, что для создания раздела по администрированию каких-либо объектов в рамках модуля достаточно:

  • описать класс ORM-объектов
  • создать API для выборки этих объектов на базе класса RS::Module::AbstractModel::EntityList
  • создать CRUD-контроллер и передать в конструкторе экземпляр класса API

В административной панели появится полноценный раздел, поддерживающий сортировку, фильтрацию, отображение списка, диалоги создания и редактирования объектов.

TreeList

Расширяет класс RS::Module::AbstractModel::EntityList. Класс может быть использован для создания модели(API) для работы с древовидными списками ORM-объектов. У ORM-объектов должно быть поле parent_id, указывающее на ID родительского элемента.

Некоторые методы, которые реализованы в абстрактном классе RS::Module::AbstractModel::TreeList:

Полный список методов можно узнать в описании класса.

Пример модели, построенной на основе класса TreeList:

class CategoryApi extends \RS\Module\AbstractModel\TreeList
{
function __construct()
{
parent::__construct(new \Article\Model\Orm\Category,
array(
'parentField' => 'parent', //Сообщаем модели, в каком свойстве находится ссылка на ID родителя
'multisite' => true, //Сообщаем, что объект мультисайтовый, соответственно и API тоже должно быть мультисайтовым
'idField' => 'id', //Сообщаем модели, в каком свойстве находится ID
'aliasField' => 'alias', //Сообщаем модели, в каком свойстве находится символьный ID
'nameField' => 'title', //Сообщаем модели, в каком свойстве находится название объекта
'sortField' => 'sortn', //Сообщаем модели, в каком свойстве находится сортировочный индекс
'defaultOrder' => 'sortn' //Указываем сортировку по-умолчанию для выборок
));
}
//... здесь можно дописывать любое количество произвольных методов, которые могут выполнять самые разные операции.
}
//Создаем экземпляр API
$api = new CategoryApi();
$tree = $api->getTreeList(0); // Возвращает объект класса RS::Module::AbstractModel::TreeList::TreeListOrmIterator

TreeCookieList

Расширяет класс RS::Module::AbstractModel::TreeList. Отличается от TreeList тем, что во время загрузки элементов из базы, элементы дополняются сведениями из cookie, а именно сведениями о закрытых узлах. Данный класс обычно используют в качестве базового, когда требуется отображение объектов в административной панели в виде дерева с открывающимися/закрывающимися узлами.

Итератор древовидного списка

Для выборки элементов древовидного списка используются итераторы наследники RS::Module::AbstractModel::TreeList::AbstractTreeListIterator. итераторы позволяют сэкономить ресурсы сервера при работе с древовиднымми списками, а также автоматически удаляет из памяти не используемые ветви дерева.

Итератор имплементирует интерфейсы Iterator, ArrayAccess и Countable.

Метод RS::Module::AbstractModel::TreeList::AbstractTreeListIterator::getItems - возвращает массив узлов древовидного списка (наследников RS::Module::AbstractModel::TreeList::AbstractTreeListNode)

Некоторые методы, доступные у объекта узла:

Пример кода с использованием итератора (обработка дерева категорий):

class SomeClass
{
public function dirProcessing()
{
$dir_api = new \Catalog\Model\DirApi();
$this->recursiveDoSomething($dir_api->getTreeList());
}
public function recursiveDoSomething($tree)
{
foreach ($tree as $node) {
$orm_object = $node->getObject();
// здесь код обработки orm объекта
if ($node->getChildsCount()) {
$this->recursiveDoSomething($node->getChilds());
}
}
}
}