Контроллеры
Содержание
Контроллер — главный 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.phpview— режим (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, $product_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;