Контроллерами в ReadyScript называются объекты наследников класса RS::Controller::AbstractController. При запуске контроллер выполняет действие, что обычно подразумевает создание соответствующих моделей и отображение необходимых представлений. Действия - это методы класса контроллера, название которых начинается на action. Действие, выполняемое по-умолчанию у контроллера называется Index, оно выполняется если не указано иное действие в запросе.
В ReadyScript имеется 2 понятия контроллеров:
Существуют базовые классы фронт и блок контроллеров для клиентской части(frontend) и администраторской (backend).
Базовые классы контроллеров клиентской части располагаются в пространстве имен RS::Controller.
При запуске контроллера выполняется метод exec, который проверяет права на запуск данного контроллера, и если прав достаточно, то происходит запуск действия контроллера.
Контроллер проверяет права к модулю, которому принадлежит контроллер. Права должны быть больше либо равны значению, указанному в свойстве $access_right объекта контроллера. По умолчанию это значение равно 1, т.е. для запуска фронт-контроллера у группы пользователей, от которой происходит запуск, должны быть минимальные права доступа к соответствующему модулю.
Фронт-контроллеры с точки зрения кода - это потомки класса RS::Controller::Front. Клиентские фронт-контроллеры должны находиться в пространстве имен ModuleName\Controller\Front. Минимальный фронт-контроллер выглядит следующим образом:
Для контроллеров разделов, где требуется авторизация, существует базовый класс RS::Controller::AuthorizedFront. Действие такого контроллера будет выполнено, только если пользователь будет авторизован и будет принадлежать требуемой группе пользователей, в противном случае произойдет перенаправление на страницу авторизации.
Блок контроллеры - это потомки класса RS::Controller::Block. Блок контроллеры можно размещать на странице с помощью Конструктора сайта, расположенного в административной части или с помощью конструкции moduleinsert в Smarty. Система отображает блок контроллеры с описаниями в списках, поэтому у блок контроллеров есть свойства $controller_title и $controller_description, которые необходимо заполнять.
Пример простейшего блок-контроллера:
Блок контроллеры могут иметь собственные настройки. Настройки должны быть возвращены методом getParamObject() в виде объекта RS::Orm::ControllerParamObject. RS::Orm::ControllerParamObject - это ORM-объект с типом хранилища RS::Orm::Storage::Stub (заглушка). Подробно о порядке объявления свойств ORM объектов можно узнать в разделе ORM объекты. Данный объект будет использован для генерации визуальной формы запроса параметров.
Значения парметров будут доступны внутри контроллера с помощью метода getParam. Параметры по-умолчанию можно задать в свойстве $default_params.
Рекомендуется, чтобы у блок-контроллера можно было настраивать шаблон, в котором будет отображен результат. Это позволит на одной странице размещать один и тот же блок с разным отображением. Для удобства разработчиков в ReadyScript предумсотрен базовый класс RS::Controller:StandartBlock, в котором задан параметр indexTemplate. Большинство блок-контроллеров модулей, идущих в комплекте с системой, являются потомками RS::Controller:StandartBlock.
Базовые классы контроллеров административной части располагаются в пространстве имен RS::Controller::Admin. Для административной панели также существуют фронт и блок контроллеры. Для административной части есть несколько базовых классов разного назначения:
Блок-контроллеры в административной части также присутствуют. Например в системе есть блок модуля Фотографии, который присутствует в формах разных объектов: Товары, Статьи.
Виджет-контроллеры - используются для отображения виджетов на главной странице административной панели. Система автоматически распознает все виджет-контроллеры в пространствах имен: ИМЯ_МОДУЛЯ\Controller\Admin\Widget, и позволяет их вывести на страницу.
Фронт-контроллеры обрабатывают запросы при открытии разделов административной части из пунктов меню.
CRUD-контроллеры содержат реализацию стандартных CRUD(Create-Read-Update-Delete) действий. Большинство контроллеров административной части являются потомками RS::Controller::Admin::Crud.
Отдельно стоит сказать про CRUD контроллер. Он требует минимальных сведений для инициализации и способен полностью организовать администрирование ORM объектов. Такой контроллер имеет не стандартный ход выполнения действия(action) в отличие от других контроллеров. Как только такой контроллер запускается с действием, например Index, он ищет метод с название helper{ИМЯ_ДЕЙСТВИЯ} , т.е. helperIndex. В методе должен инициализироваться визуальный helper, который далее будет использован для построения элементов страницы. Результат выполнения метода helperIndex сохраняется в свойстве класса и доступен в дальнейшем с помощью метода getHelper. Далее выполняется метод actionIndex, в котором происходит действие(загрузка данных из модели или сохранение элементов) и к результату выдается шаблон, полученный от helper'а.
Данный подход необходим для предоставления возможности другим модулям изменять состав визуальных элементов на странице. После формирования helper'a в системе и перед вызовом метода с действием, вызывается событие controller.exec.СОКРАЩЕННОЕ_ИМЯ_КОНТРОЛЛЕРА.ИМЯ_ДЕЙСТВИЯ, которому в качестве параметра передается helper. Данное событие может быть обработано любым подписчиком. Любой обработчик, например, может добавить свою кнопку в панели инструментов или добавить дополнительную колонку в таблицу, и т.д.
Пример простого CRUD-контроллера:
Большинство страниц административной панели имеют схожую задачу - выполнение CRUD операций с объектами. Для решения этой задачи обычно требуется следующий набор страниц - страница со списком объектов(виде таблицы, в виде дерева и таблицы, в виде дерева) и страница с формой объекта. При этом на странице со списком объектов должна присутствовать форма поиска объектов, возможность выбора группы объектов, возможность произвести операцию с группой объектов, возможность выбора состава колонок в таблицах, возможность выбора сортировки элементов в таблице.
Для упрощения работы разработчиков, в ReadyScript есть класс RS::Controller::Admin::Helper::CrudCollection - помощник визуальной части, который является агрегатором настроек для всех визуальных элементов на странице. Помощник используется в CRUD контроллере.
Рассмотрим, как инициализируется helper в контроллере:
И как используется helper непосредственно в действии:
В момент инициализации, helper принимает параметры согласно правилу отсутствия магических массивов. Визуальные помощники позволяют строить стандартные интерфейсы административной части только при помощи PHP объектов, не углубляясь в HTML. Помощник RS::Controller::Admin::Helper::CrudCollection позволяет конструировать разные типы страниц. Установить тип отображаемой страницы позволяют методы:
viewAsAny - произвольная страница с заголовком и кнопками внизу viewAsForm - страница с формой объекта viewAsTable - страница с таблицей объектов viewAsTableTree - страница с деревом слева и с таблицей справа viewAsTree - страница с деревом
Объект шаблонизатора RS::View::Engine доступен в контроллере через свойство view.
В контроллере также доступны следущие свойства:
Ожидается, что действие контроллера вернет либо строку с HTML данными, которая будет отправлена в браузер, либо объект, имплементирующий интерфейс RS::Controller::Result::IResult или RS::Controller::Result::ITemplateResult.
В случае возвращения объекта, система будет располагать более структурированными данными о результате выполнения действия контроллера. Конечные данные, отправляемые в браузер извлекаются из объекта вызовом метода getOutput().
Интерфейс IResult предполагает, что из результата можно извлечь и установить HTML часть результат с помощью метода getHtml и setHtml. Интерфейс ITemplateResult расширяет IResult и добавляет возможность установить и получить шаблон для рендеринга с помощью методов setTemplate и getTemplate, а также получить переменные, которые должны быть переданы в шаблон с помощью метода getTemplateVars.
Для стандартизации частых ответов контроллера, в ReadyScript был разработан базовый класс RS::Controller::Result::Standard. Он имплементирует интерфейс ITemplateResult.
Идея стандартизации ответов в основном актуальна для Ajax запросов к серверу. Для масштабируемости важно, чтобы сервер в ответ на ajax запрос возвращал не HTML, а JSON данные, в которые можно было бы дописывать необходимые секции в случае потребности в расширении. Для одних и тех же по смыслу ответов контроллера, логично в JSON иметь одинаковые структуры данных и названия секций. Именно эту задачу решает класс стандартного ответа RS::Controller::Result::Standard.
Ответы сервера, которые формирует стандартизировано объект RS::Controller::Result::Standard:
Логика формирования ответов методом RS::Controller::Result::Standard::getOutput:
Если идет ajax запрос, то:
Если идет обычный запрос: