Проблема «толстых» контроллеров или как я ее решал

от автора

Мне нравится MVC, познакомился с ним в CodeIgniter’e года 2 назад и после битрикса это казалось настолько понятным и удобным. Так же давно услышал фразу “толстые контроллеры”, но столкнулся с этим только когда начал писать админку интернет-магазина.

После этого было принято решение написать свою реализацию, которая решала бы эту проблему и вот что получилось.

Приведу пример “толстого” контроллера. Допустим, если админка начинается с /admin, то контроллер /controllers/admin.php занимается обработкой всех запросов вида /admin/catalog, /admin/catalog/products, /admin/profile и т.д. Таких страниц может быть несколько десятков, а значит и admin.php становится большим и тяжело управляемым.

Частично это можно решить разделением контроллера на /admin и /admin_catalog, что тоже ни к чему хорошему не приведет, т.к. придется дублировать код проверки авторизации, например.

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

Данная структура контроллеров имеет один недостаток, пришлось дублировать проверку авторизации на каждой странице. Решением стал ввод хуков (из CI), которые выполняются до и после контроллера, что позволяет уменьшить каждый контроллер на строку:

if(!$shopmodel->isAuthorized()) redirect('/admin/login'); 

Такую структуру удалось получить с помощью следующего кода в файле framework.php:

<?php if(!defined('BASE_PATH')) die('No Access'); require APP_PATH . 'config.php'; require CORE_PATH . 'functions.php';  $uri = isset($_SERVER['REDIRECT_URL']) ? $_SERVER['REDIRECT_URL'] : '/'; $uri = strtolower($uri); if(mb_strlen($uri) > 1){     $uri = substr($uri, 1); }  $DEBUG = getLibrary('debug'); $DEBUG->start('controller');  executeHook('before_controller');  $controller = getController($uri, $config); require APP_PATH . 'controllers/' . $controller; //подключение контроллера $DEBUG->stop('controller', 'System', 'Время работы контроллера'); executeHook('after_controller'); $DEBUG->show(); //для отладки: время выполнения контроллера и запросов в базу 

Каждый контроллер представляет из себя файл, избавленный от лишнего class Admin… public function catalog().

Получение моделей и библиотек (как системных так и пользовательских):

$view = getLibrary('view'); $shopmodel = getModel('shop'); 

Получение данных из модели:

$shop = $shopmodel->getShop(); 

Вывод в шаблон:

$view->set('include', 'settings/catalog/categories'); $view->set('menu', 'settings'); $view->set('submenu', array(     'file' => 'settings',     'current' => 'catalog' )); $view->set('title', 'Настройки » Каталог » Категории'); $view->template('admin/_templates/twocol'); 

Роутинг простой, страница /admin/shop/ обрабатывается контроллером /controllers/admin/shop/index.php, а страница /admin/shop/orders — /controllers/admin/shop/orders.php.

Замена адресов регулярными выражениями:

$config['router'] = array(     'admin/shop/orders/([0-9]+)' => '/admin/shop/orders/detail.php' ); 

Так же были переписаны некоторые библиотеки, которые в составе CI не совсем мне подходили, например хранение сессий в куках, например.

Что мы имеем:
+ небольшой фреймворк, близкий к MVC;
+ строго структурированные контроллеры, что и требовалось;
+ прозрачность, фреймфорк не имеет и не выполняет какой либо тяжелый скрытый код, время выполнения любого контроллера или библиотеки фиксируется встроенным отладчиком.

ссылка на оригинал статьи http://habrahabr.ru/post/203510/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *