Создание маршрутизатора в собственном фреймворке на PHP. Часть 3
В этом посте мы продолжим разработку нашего маршрутизатора, сосредоточившись на его оптимизации, интеграции с контроллерами и обработке ошибок. После предыдущих шагов мы сформировали основу для маршрутизатора. Теперь давайте завершим его реализацию, чтобы он мог полноценно работать в нашем фреймворке.
1. Переход к контроллерам
Когда пользователь делает запрос, наша задача — определить, какой контроллер должен обработать этот запрос. Все контроллеры находятся в пространстве имен app\controllers, и мы должны корректно сформировать имя контроллера в зависимости от маршрута.
2. Обработка маршрутов: метод dispatch
Вернемся к методу dispatch, который принимает строку URL:
protected static function dispatch($url) {
// Проверяем наличие соответствия маршруту
if (!self::matchRoute($url)) {
// Если соответствие не найдено, выбрасываем исключение
throw new \Exception('404 Not Found: Страница не найдена');
}
// Определяем контроллер
$controllerNamespace = 'app\\controllers\\';
$adminPrefix = self::$root['admin_prefix'] ? self::$root['admin_prefix'] . '/' : '';
$controllerClass = $controllerNamespace . $adminPrefix . ucfirst(self::$root['controller']) . 'Controller';
// Проверяем, существует ли контроллер и создаем его экземпляр
if (!class_exists($controllerClass)) {
throw new \Exception("Контроллер не найден: $controllerClass");
}
$controllerObject = new $controllerClass();
// Далее будет вызов метода контроллера
}
3. Формирование названия контроллера
Как видно из кода, мы добавляем логику для формирования имени контроллера, основываясь на маршруте пользователя. Важно учесть, что админ-префикс может добавляться к маршруту, и в зависимости от этого мы формируем имя контроллера:
$controllerNamespace = 'app\\controllers\\'; // Пространство имен для контроллеров
$adminPrefix = self::$root['admin_prefix'] ? self::$root['admin_prefix'] . '/' : ''; // Проверяем наличие админ-префикса
$controllerClass = $controllerNamespace . $adminPrefix . ucfirst(self::$root['controller']) . 'Controller'; // Формируем имя контроллера
4. Проверка существования контроллера
Перед созданием объекта контроллера, мы должны убедиться, что класс существует:
if (!class_exists($controllerClass)) {
throw new \Exception("Контроллер не найден: $controllerClass");
}
$controllerObject = new $controllerClass(); // Создаем объект контроллера
Таким образом, если контроллер не найден, будет выброшено исключение, что упростит отладку и понимание происходящего.
5. Вызов метода контроллера
Теперь, когда у нас есть экземпляр контроллера, нам необходимо вызвать метод, который будет обрабатывать запрос. Метод формируется на основании имени действия, указанного в маршруте:
$actionMethod = self::lowerCamelCase(self::$root['action']) . 'Action'; // Формируем метод, добавляя 'Action'
if (!method_exists($controllerObject, $actionMethod)) {
throw new \Exception("Метод не найден: $actionMethod в контроллере $controllerClass");
}
$controllerObject->$actionMethod(); // Вызываем метод контроллера
Таким образом, мы обеспечиваем, чтобы метод контроллера был найден, и только затем вызываем его.
6. Пример реализации контроллера
Для тестирования нашей логики создадим простой контроллер:
namespace app\controllers;
class MainController {
public function indexAction() {
echo "Добро пожаловать на главную страницу!";
}
}
Теперь добавим маршрут для главной страницы:
Router::add('^$', ['controller' => 'Main', 'action' => 'index']);
Теперь, если мы откроем корневой URL (/), мы должны увидеть следующее сообщение:
Добро пожаловать на главную страницу!
7. Обработка ошибок
Чтобы избежать сбоев в работе приложения, важно обработать возможные ошибки. Для этого обернем вызовы маршрутизатора в блок try-catch:
try {
Router::dispatch($url); // Вызываем метод dispatch
} catch (\Exception $e) {
echo $e->getMessage(); // Выводим сообщение об ошибке
}
8. Поддержка дополнительных параметров и улучшения
В будущем мы будем добавлять функционал, который позволит принимать дополнительные параметры, обеспечивать поддержку мультиязычности и автоматически вызывать модели и виды. Это значительно расширит функциональные возможности нашего фреймворка.
Заключение
Сегодня мы завершили разработку основного функционала маршрутизатора. Мы научились обрабатывать запросы, управлять контроллерами и их методами, а также будем учитывать возможные ошибки и исключения. В следующем уроке мы сосредоточимся на расширении возможностей маршрутизатора, интеграции мультиязычности и работе с дополнительными параметрами запроса.
Добавить комментарий или задать вопрос ツ
Комментариев нет