Контроллеры
Содержание
Контроллер — главный PHP-файл. Каждый тип страниц интернет-магазина имеет свой контроллер (например: товары → products.php, заказы → orders.php). Контроллеры панели администратора и витрины разделены и не пересекаются. Контроллер подключается автоматически в следующей последовательности:
Точка входа (index.php или admin.php) → init.php (функция fn_dispatch) -> название_контроллера.php
Контроллер является связующим звеном между пользователем, базой данных и шаблоном отображения. В контроллерах выполняются все основные функции платформы:
- Обработка POST- и GET-запросов;
- Получение и сохранение информации в базе данных;
- Выполнение функций и обработка данных перед отображением;
- Определение шаблонов и передача обработанных данных в шаблоны для вывода на экран;
Контроллер явлется самой важной частью работы платформы, так как без его участия не будет отображена ни одна страница.
Определить контроллер, работающий в настоящий момент, просто — он определяется в параметре dispatch
URL страницы:
Подсказка
Не рекомендуется вносить изменения в контроллеры.
Вы можете расширять контроллеры с помощью pre-контроллеров и post-контроллеров, в ваших модулях. Pre- и post-контроллеры подключаются автоматически и срабатывают до и после основного контроллера соответственно.
Инициализация контроллера
Порядок подключения файлов:
index.php или admin.php → init.php → [controller_name].php
Путь к контроллеру и его название определяются платформой автоматически на основе параметра dispatch
, передаваемого в главный исполняемый файл (index.php, admin.php, vendor.php).
Параметр dispatch
принимает значение в формате [controller_name].[mode_name]
, где:
controller_name
- название контроллераmode_name
- режим (mode) работы контроллера
При этом будет вызван:
- для панели администратора
app/controllers/backend/[controller_name].php
, - для витрины
app/controllers/frontend/[controller_name].php
. - Если контроллер
[controller_name].php
не будет найден в папке соответствующей зоны, то будет осуществлена попытка включенияapp/controllers/common/[controller_name].php
. Контроллер, расположенный вapp/controllers/common/[controller_name].php
, может работать в любой зоне (витрине и панели администратора).
Режим работы — mode_name
определяет секцию исполняемого кода внутри файла контроллера, а также имя шаблона отображения.
За подключение контроллеров отвечает функция fn_dispatch()
, которая:
- Проверяет параметры URL.
- Проверяет права доступа к контроллеру.
- Перенаправляет к защищенному протоколу (HTTPS), когда это необходимо.
- Готовит список pre-контроллеров и post-контроллеров (модулей и расширений) для последовательного соединения в правильном порядке.
- Автоматически определяет шаблон для отображения.
Расположение контроллеров
root/
└── app/
└── controllers/
├── backend/
├── common/
└── frontend/
Панель администратора admin.php |
app/controllers/backend/название_контроллера.php |
Витрина index.php |
app/controllers/frontend/название_контроллера.php |
Общие контроллеры admin.php и index.php |
app/controllers/common/название_контроллера.php |
Примеры
Пример “Страница витрины”
Рассмотрим работу контроллера на примере открытия(отображения) страницы в зоне клиента (витрине интернет-магазина).
Для примера будет использована детальная страница товара (карточка товара).
Параметр: dispatch=products.view
products
— название контроллера.Будет подключен и выполнен код из контроллера:
app/controllers/frontend/products.php
view
— режим (mode). Это означает, что:В контроллере
products.php
будет выполнен код из секции$mode == 'view'
:if (mode == 'view') { // код php }
Будет подключен шаблон отображения:
/design/themes/basic/templates/views/products/view.tpl
где
/products/
— название контроллера,view
— режим (mode).
По данному принципу отображаются все страницы платформы.
Пример “Страница в панели администратора”
Пример работы контроллера по отображению страницы в панели администратора.
Для примера будет использована страница редактирования товара, однако по данному принципу отображаются все страницы панели администратора.
Примечание
admin.php переименован для повышения безопасности в panel.php (см. Три шага к повышению безопасности)
Параметр: dispatch=products.update
Название контроллера: products
Будет подключен и выполнен контроллер: app/controllers/backend/products.php
Режим (mode): update
Это означает, что:
В контроллере
app/controllers/backend/products.php
будет выполнен код из секции:if (mode == 'update') { // код php }
Будет подключен шаблон:
/design/backend/templates/views/products/update.tpl
Пример “Отправка формы”
Рассмотрим работу контроллера при нажатии кнопки и отправке данных формы (POST
-запрос).
Для примера использована страница редактирования категории и нажатие кнопки “Сохранить”.
URL: demo.cs-cart.ru/panel.php?dispatch=categories.update&category_id=166
Когда мы нажимаем кнопку “Сохранить”, отправляется POST-запрос с данными формы редактирования категории на адрес demo.cs-cart.ru/panel.php
.
1. Проверяем форму
Название контроллера:
categories
.Будет подключен и выполнен контроллер:
app/controllers/backend/categories.php
Режим (mode):
update
В контроллере
app/controllers/backend/categories.php
будет выполнен код из секцииPOST
и$mode == update
:if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($mode == 'update') { // PHP код обработки формы, отправленной методом POST } }
Результатом работы контроллера по обработке
POST
-запроса будет перенаправление на страницу, заданную в контроллере. В данном примере контроллер сохранит изменения и выполнит перенаправление на ту же самую страницуdemo.cs-cart.ru/panel.php?dispatch=categories.update&category_id=166
. Процесс открытия данной страницы будет аналогичен примеру Страница в панели администратора .
Структура контроллера
Контроллер — php-файл, состоящий из трёх логических блок:
- Секция обработки
POST
-запросов. - Секция обработки
GET
-запросов. - Локальные функции контроллера.
Секции POST
и GET
разделены на блоки по режимам (mode) работы — mode_name
.
Секция обработки POST-запросов
Применяется для обработки данных с форм, AJAX-запросов и т.д. Когда Вы нажимаете кнопку в панели администратора или витрине, то обработка запроса будет происходить именно в этой секции контроллера. Обычно работа контроллера в данной секции завершается переходом на другой (или этот же) контроллер, где вступает в работу секция обработки GET
-запросов.
Секция всегда расположена перед секцией GET
в файле контроллера и заключена в условие:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// ...
}
Секция POST
разделена на блоки в зависимости от режима (mode) работы — mode_name
:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($mode == 'update') {
// [mode_name] — update
}
if ($mode == 'delete') {
// [mode_name] — delete
}
return array(CONTROLLER_STATUS_OK, "[redirect_url]");
}
В конце секции POST
обязательно необходимо вернуть массив с результатом работы, включающий статус и URL перенаправления:
return array(CONTROLLER_STATUS_OK, "[redirect_url]");
где:
CONTROLLER_STATUS_OK
— константа со статусом работы контроллера.
[redirect_url]
— URL для перенаправления после обработки запроса.
После обработки секции управление будет передано в функцию fn_dispatch()
, и будет осуществлён последующий переход на [redirect_url]
.
Пример 1. “Простой контроллер”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($mode == 'update') {
$data = array (
'amount' => 5,
'status' => 'A',
);
$product_id = 3;
db_query('UPDATE ?:products SET ?u WHERE product_id = ?i', $data, $order_id);
}
return array(CONTROLLER_STATUS_OK, "products.update");
}
// Начало секции GET
if ($mode == 'update') {
//.......
}
|
Секция обработки GET-запросов
Применяется при открытии страниц или для получения информации из базы данных и вывода на экран. Когда Вы открываете страницу в браузере, именно данный раздел контроллера работает над данными для открытия страницы.
Секция GET
-запросов всегда располагается после секции POST
в файле контроллера и разделена на блоки режимов (mode) работы:
if ($mode == '[mode_name_1]') {
} elseif ($mode == '[mode_name_2]') {
}
Блоки $mode
выполняются в зависимости от значения параметра URL параметра dispatch=[controller_name].[mode_name]
Работа контроллера в данной секции обычно заканчивается:
- Передачей обработанных данных в шаблон для отображения.
- Перенаправлением с помощью метода
GET
. - Прекращением работы скрипта:
exit;
.
В первом случае Вам необходимо передать информацию на отображение с помощью функции:
$view->assign('template_var_name', $php_var_name);
// где $view = Registry::get('view');
В данном случае в шаблоне будет доступна smarty-переменная template_var_name
, равная php_var_name
.
После завершения работы контроллера работу автоматически продолжит функция fn_dispatch
. Шаблон отображения будет определён автоматически, в нём будут доступны переменные, переданные контроллером.
Пример 1. “Определить контроллер и шаблон”
Рассмотрим страницу “Заказы” в панели администратора — отображает список заказов.
URL: /admin.php?dispatch=orders.manage
Из URL мы можем определить:
Название контроллера —
orders
Будет подключен и выполнен файл контроллера:
app/controllers/backend/orders.php
Режим (mode) работы контроллера —
manage
В контроллере будет исполнен код из блока:
if ($mode == 'manage') { }
Для отображения будет автоматически подключен шаблон:
/design/backend/templates/views/orders/manage.tpl
Примечание
Для панели администратора подключаются шаблоны:
/design/backend/templates/views/[controller_name]/[mode_name].tpl
Для витрины подключаются шаблоны:
/design/themes/[название_темы]/templates/views/[controller_name]/[mode_name].tpl
Пример 2. “Простой контроллер”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <?php
// Подключение класса Registry
use Tygh\Registry;
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
//......
}
// Секция GET
if ($mode == 'update') {
$id = $_REQUEST['product_id'];
$data = db_get_row("SELECT * FROM ?:products WHERE product_id = ?i", $id);
Registry::get('view')->assign('data', $data);
} elseif ($mode == 'manage') {
$products = fn_get_products($_REQUEST);
Registry::get('view')->assign('products', $products);
}
|
Локальные функции
В конце контроллера могут быть расположены функции, которые доступны и выполнятся в рамках файла контроллера.
Также контроллеры используют:
Функции из папки
app/functions/
Классы и методы классов из папки
app/Tygh/
Для использования классов в начале контроллера необходимо подключить класс, например:
// Подключение класса Registry use Tygh\Registry; // Использование методов класса $view = Registry::get('view');
Доступные данные
Для работы с данными Dы должны использовать следующие стандартные массивы:
$_REQUEST | Содержит все переменные, поступающие из GET- и POST-запросов. Данные в массиве проходят предварительную обработку:
Предварительную обработку можно отключить с помощью функции if ($mode == 'update_details') {
fn_trusted_vars('update_order');
|
---|---|
$_SESSION | Стандартный массив PHP, который хранит данные сессии пользователя. |
Registry | Специальный статический класс — хранилище данных, которые доступны из любого места программы платформы. Например, в данном классе хранится вся конфигурация платформы, которая помещается в него при запуске. Особенностью данного класса является то, что хранящиеся в нём данные кэшируются. Это позволяет сократить количество обращений к базе данных и ускорить работу платформы. Пример использования: $addons_info = Registry::get('addons');
Для использования в контроллерах или функциях класс должен быть подключён в начале php-файла: use Registry;
|
Передача данных на отображение
После выполнения кода контроллера работу продолжает функция fn_dispatch(), которая автоматически подключает шаблоны отображения. Шаблоны подключаются в зависимости от контроллера и будт содержат данные, переданные контроллером в шаблон.
Передача данных из контроллера в шаблон осуществляется с помощью:
$view->assign('tpl_data', $php_data);
// tpl_data - новая переменная, которая будет доступна в шаблоне
// $php_data - обработынные данные, которые передаются в шаблон
По умолчанию путь к шаблону определяется автоматически:
- Для панели администратора: /backend/templates/views/
[controller_name]
/[mode_name]
.tpl - Для витрины: /themes/
[theme name]
/templates/views/[controller_name]
/[mode_name]
.tpl
где:
[controller_name]
- контроллер
[mode_name]
- режим (mode) работы контроллера
[theme name]
- название темы (basic или responsive)
Однако шаблон может быть задан вручную прямо в контроллере, например:
$view->display('views/companies/components/share_object.tpl');
exit;