Контроллеры

Контроллер — главный PHP-файл. Каждый тип страниц интернет-магазина имеет свой контроллер (например: товары → products.php, заказы → orders.php). Контроллеры панели администратора и витрины разделены и не пересекаются. Контроллер подключается автоматически в следующей последовательности:

Точка входа (index.php или admin.php) → init.php (функция fn_dispatch) -> название_контроллера.php

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

  • Обработка POST- и GET-запросов;
  • Получение и сохранение информации в базе данных;
  • Выполнение функций и обработка данных перед отображением;
  • Определение шаблонов и передача обработанных данных в шаблоны для вывода на экран;

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

Определить контроллер, работающий в настоящий момент, просто — он определяется в параметре dispatch URL страницы:

Controllers Controllers

Подсказка

Не рекомендуется вносить изменения в контроллеры.

Вы можете расширять контроллеры с помощью 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

Примеры

Пример “Страница витрины”

Рассмотрим работу контроллера на примере открытия(отображения) страницы в зоне клиента (витрине интернет-магазина).

Для примера будет использована детальная страница товара (карточка товара).

URL: http://demo.cs-cart.ru/index.php?dispatch=products.view&product_id=17

Controllers

Параметр: dispatch=products.view

  1. products — название контроллера.

    Будет подключен и выполнен код из контроллера: app/controllers/frontend/products.php

  2. view — режим (mode). Это означает, что:

    1. В контроллере products.php будет выполнен код из секции $mode == 'view':

      if (mode == 'view') {
      
          // код php
      
      }
      
    2. Будет подключен шаблон отображения:

      /design/themes/basic/templates/views/products/view.tpl

      где /products/ — название контроллера, view — режим (mode).

По данному принципу отображаются все страницы платформы.

Пример “Страница в панели администратора”

Пример работы контроллера по отображению страницы в панели администратора.

Для примера будет использована страница редактирования товара, однако по данному принципу отображаются все страницы панели администратора.

URL: http://demo.cs-cart.ru/panel.php?dispatch=products.update&product_id=17

Примечание

admin.php переименован для повышения безопасности в panel.php (см. Три шага к повышению безопасности)

Controllers

Параметр: dispatch=products.update

Название контроллера: products

Будет подключен и выполнен контроллер: app/controllers/backend/products.php

Режим (mode): update

Это означает, что:

  1. В контроллере app/controllers/backend/products.php будет выполнен код из секции:

    if (mode == 'update') {
    
        // код php
    
    }
    
  2. Будет подключен шаблон:

    /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. Проверяем форму

Просмотрим исходный код формы:

Метод: POST

URL отправки формы: demo.cs-cart.ru/panel.php

Просмотрим исходный код кнопки “Сохранить”:

Controllers Controllers

Параметр: dispatch[categories.update]

Итак, контроллер и режим (mode) известны.

  1. Название контроллера: categories.

    Будет подключен и выполнен контроллер: app/controllers/backend/categories.php

  2. Режим (mode): update

    В контроллере app/controllers/backend/categories.php будет выполнен код из секции POST и $mode == update:

    if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    
        if ($mode == 'update') {
    
            // PHP код обработки формы, отправленной методом POST
    
        }
    
    }
    
  3. Результатом работы контроллера по обработке POST-запроса будет перенаправление на страницу, заданную в контроллере. В данном примере контроллер сохранит изменения и выполнит перенаправление на ту же самую страницу demo.cs-cart.ru/panel.php?dispatch=categories.update&category_id=166. Процесс открытия данной страницы будет аналогичен примеру Страница в панели администратора .

Структура контроллера

Контроллер — php-файл, состоящий из трёх логических блок:

  1. Секция обработки POST-запросов.
  2. Секция обработки GET-запросов.
  3. Локальные функции контроллера.

Секции 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 мы можем определить:

  1. Название контроллера — orders

    Будет подключен и выполнен файл контроллера: app/controllers/backend/orders.php

  2. Режим (mode) работы контроллера — manage

    В контроллере будет исполнен код из блока:

    if ($mode == 'manage') {
    
    }
    
  3. Для отображения будет автоматически подключен шаблон:

    /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');
    

Доступные данные

Для работы с данными вы должны использовать следующие стандартные массивы:

$_REQUEST

Содержит все переменные, поступающие из GET- и POST-запросов.

Данные в массиве проходят предварительную обработку:

  • Удаляются HTML-тэги;
  • Удаляются символы “/”, которые может добавлять PHP автоматически;

Предварительную обработку можно отключить с помощью функции fn_trusted_vars(). В функцию необходимо передать список переменных, которые не нужно обрабатывать. Например:

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;

Запуск контроллера в командной строке

  • Backend-контроллер:

    php /path/to/cart/admin.php --dispatch=controller.mode
    
  • Frontend-контроллер:

    php /path/to/cart/index.php --dispatch=controller.mode
    
  • Common-контроллер: любая из двух команд выше (common-контроллеры работают и с admin.php, и c index.php).

    Примечание

    Замените в командах /path/to/cart на путь к директории с установленным CS-Cart или Multi-Vendor на вашем сервере. Скорее всего, имя у admin.php тоже будет другим (этот файл переименовывают в целях безопасности).

Параметры контроллера передаются так:

php admin.php --dispatch=controller.mode --param1=value --param2=value --param3[]=value1 --param3[]=value2 --param4[param5]=value

Эти параметры передаются в контроллер как обычные request-параметры и доступны в массиве $_REQUEST. Если режим (mode) контроллера обрабатывает POST-запросы, то скрипту следует передать аргумент --p после указания параметров.

Запуск определённого режима у контроллера в командной строке приведёт к выполнению действий, реализованных в этом режиме. Если после запуска команды в командной строке ничего нет, то возможно, что:

  • Контроллер ничего не возвращает с помощью fn_set_progress, fn_echo, fn_set_notification.
  • Контроллер запущен с неправильным режимом.
  • Параметры режима были указаны неверно или вообще не были указаны.
  • Данный контроллер не может быть запущен с помощью этого скрипта. Например, backend-контроллер не запустится с помощью index.php.