Yii - перехват запросов
Все фреймворки, с которыми мне приходилось работать, при всей своей гибкости, все же слегка «деревянные». Например, ни один из них не позволяет динамически менять конфигурацию приложения, без редактирования конфигурационных файлов. Это создает определенные проблемы, если вы хотите, чтобы ваше приложение было по-настоящему модульным.
Представим, что вы хотите создать CMS, которая будет иметь кучу модулей, созданных сторонними разработчиками. И каждый пользователь вашей CMS должен иметь возможность сам решать, какие именно модули ему устанавливать. При этом установка/удаление модуля должны происходит по принципу «одного клика», т.е. пользователь должен лишь выбрать нужный модуль и нажать кнопку «Установить» (или «Удалить»), всю остальную работу, включая изменение настроек, система должна сделать сама.
Вот тут и начинаются проблемы. Скопировать (скачать) файлы модуля в определенную папку сервера не представляет труда, но как обновить «hard-coded» конфигурацию? Писать парсер php-файлов ради добавления пары строк в конфиг - далеко не самое умное решение. Гораздо лучше (и удобнее) работать с конфигурацией, находящейся в каком-нибудь хранилище (например в БД) и считывать ее при запуске приложения. Осталось только придумать как успеть загрузить настройки ДО начала работы приложения (обработки запроса)...
Описанная выше ситуация — это только один из случаев, когда приложение должно по каким-то причинам «перехватить управление» до начала обработки запроса самим фреймворком. Другая частая необходимость в таком поведении — проверка прав доступа. К примеру некоторые из установленных модулей сейчас отключены и хорошо бы чтобы фреймворк об этом узнал и соответственно отреагировал.
Предлагаемое ниже решение прекрасно работает в Yii и позволяет одним махом «закрыть» все подобные вопросы.
Yii имеет механизм временной блокировки сайта. Суть его сводится к следующему: в настройках можно указать маршрут (контроллер/действие), который будет вызываться при любом обращении к сайту. В самом действии обычно прописан код вывода сообщения типа «На сайте ведутся технические работы. Зайдите позже».
Как оказалось, этот механизм прекрасно подходит для решения вышеописанных задач, нужно лишь добавить пару строк, чтобы заставить фреймворк продолжить обработку запроса, когда все настройки и проверки уже выполнены. Таким образом мы получим систему, в которой перед обработкой любого запроса будет вызываться созданное нами действие (метод класса контроллера).
Перейдем к практической реализации.
Код до смешного прост. Создадим контроллер и обзовем его Privratnik:
class PrivratnikController extends Controller
{
public function actionIndex()
{
// здесь будем добавлять код
// возвращаем управление фреймворку
$_app = Yii::app();
$route = $_app->getUrlManager()->parseUrl($_app->getRequest());
$_app->runController($route);
}
}
Сохраним текст класса в файле PrivratnikController.php в папке protected/controllers. Затем активируем его, установив в конфигурации фреймворка значение параметра catchAllRequest равным маршруту к нашему контроллеру:
'catchAllRequest' => array('privratnik/index'),
Проверив работу сайта можно убедиться, что ничего не изменилось — все страницы открываются так же как и раньше. Но теперь все вызовы проходят через наш контроллер. Убедиться в этом проще простого: например, измените метод actionIndex() вот так:
public function actionIndex()
{
echo '<h1>Hello World</h1>';
$_app = Yii::app();
$route = $_app->getUrlManager()->parseUrl($_app->getRequest());
$_app->runController($route);
}
и вверху каждой страницы вашего сайты вы увидите надпись Hello World 
Как применять описанную возможность думайте сами. Например, можно динамически подменять параметры генерации URL'ов страниц и получить возможность указания элиасов страниц. Или можно проверить авторизацию пользователя и, в зависимости от нее, блокировать доступ к некоторым частям сайта. Так же здесь можно вставить анализ запросов для сбора статистики или защиты от DdoS-атак...
В общем применений масса.
