Создание маршрутизатора в собственном фреймворке на PHP. Часть 1
Погружаясь в мир маршрутизаторов: шаг за шагом к созданию эффективной системы роутинга
Дорогие друзья, продолжаем наше увлекательное путешествие в мир программирования и разбираемся с важнейшим компонентом любого веб-приложения — маршрутизатором (router). Чтобы вы понимали, зачем нам этот элемент, давайте начнем с основ.
В процессе разработки любого веб-приложения на PHP важным аспектом является правильная обработка URL запросов. В этом посте мы создадим маршрутизатор для нашего фреймворка, который будет отвечать за направление запросов на соответствующие контроллеры и действия. Это важный компонент, который помогает организовать структуру приложения и управлять его поведением.
Что такое маршрутизатор и роутинг?
Проще говоря, маршрутизатор — это как менеджер на ресепшене, который принимает запросы от пользователей и направляет их к соответствующим специалистам. Он разбирается в потребностях клиента и определяет, какая служба или функция сможет помочь. В нашем случае, маршрутизатор принимает запросы от браузера и решает, что делать с каждым конкретным запросом:
- Проверяет, существует ли адрес на сайте.
- Если адрес не найден, возвращает ошибку 404.
- Если адрес существует, перенаправляет запрос к соответствующему контроллеру.
Сегодня мы рассмотрим, как реализовать все эти функции в коде.
Как работает маршрутизатор?
Когда поступает запрос, маршрутизатор разбирает его на сегменты. Например, данный сегмент может выглядеть как page/view. Здесь Page указывает на контроллер, а View — на метод (action) этого контроллера. Также маршрутизатор может принимать параметры запроса, например, Contact.
Мы можем представить строку запроса как: Page, покажи страницу Contact. Здесь Page — это контроллер, а View — это action, который необходимо вызвать. Однако, в случае, если мы не укажем метод, маршрутизатор должен правильно интерпретировать запрос и отработать с ним по умолчанию.
Правила маршрутов: зачем они нужны?
Без таблицы маршрутов никуда. Это массив адресов, которые мы будем описывать с помощью регулярных выражений. Например, маршрут PageContact может быть представлен как регулярное выражение, где Page — это неизменная часть, а Contact — динамическая. Это позволяет управлять огромным количеством страниц без необходимости создавать по отдельному правилу для каждой.
Если у нас есть интернет-магазин, мы можем рассмотреть продукт ProductApple, где контроллер Product обеспечивает отображение нужного продукта, а Apple — это параметр, указывающий, какой конкретно продукт показать. Таким образом, мы можем использовать один маршрут, который обрабатывает множество запросов.
Подготовка к реализации
Прежде чем приступить к написанию кода, необходимо создать вспомогательные функции для отладки и хранения маршрутов. Создадим папку helpers, в которой будет файл functions.php, с функцией для красивой распечатки данных на экране.
Также, следует создать новую таблицу маршрутов в файле routes.php, где будут храниться регэкспы для обработки адресов. Все эти компоненты мы подключим в файл конфигурации.
Создание класса маршрутизатора
Теперь мы переходим к созданию самого класса маршрутизатора. Он будет содержать два основных свойства:
- Roots — массив, который будет хранить все маршруты.
- Root — конкретный маршрут, который будет найден в процессе обработки запроса.
Дополнительно мы создадим методы для добавления маршрутов и получения информации о текущих маршрутах. Это позволит нам динамически управлять маршрутами и контроллерами.
use blog\Router;
// Добавляем маршрут для главной страницы админ-панели
Router::add('^admin/?$', [
'controller' => 'Main', // Контроллер, отвечающий за обработку запроса
'action' => 'index', // Метод в контроллере, который будет вызван
'admin_prefix' => 'admin' // Префикс для админ-зоны
]);
// Добавляем маршрут для админ-панели с динамическими контроллерами и действиями
Router::add('^admin/(?P[a-z-]+)/?(?P[a-z-]+)?$', [
'admin_prefix' => 'admin' // Префикс для админ-зоны
]);
// Добавляем маршрут для главной пользовательской страницы
Router::add('^$', [
'controller' => 'Main', // Контроллер для главной страницы
'action' => 'index' // Метод, который будет обработан
]);
// Добавляем маршрут для пользовательской части с динамическими контроллерами и действиями
Router::add('^(?P[a-z-]+)/(?P[a-z-]+)/?$', [
// Параметры будут извлечены из URL и переданы в соответствующий контроллер и метод
]);
Объяснение маршрутов:
-
Маршрут для админ-панели (
^admin/?$):- Этот маршрут отвечает за доступ к главной странице админкой. Если пользователь переходит по адресу
/admin, будет вызван контроллерMainи методindex. - Параметр
admin_prefixуказывает, что это часть админской зоны.
- Этот маршрут отвечает за доступ к главной странице админкой. Если пользователь переходит по адресу
-
Динамические маршруты админ-панели (
^admin/(?P[a-z-]+)/?(?P[a-z-]+)?$):- Этот маршрут обрабатывает запросы, которые содержат контроллер и действие.
- Использует именованные параметры, чтобы захватить контроллер и действие из URL, например:
/admin/users/editбудет соответствоватьcontroller = usersиaction = edit.
-
Маршрут для главной (пользовательской) страницы (
^$):- Отвечает за запрос на корневой адрес сайта, ведет к контроллеру
Mainи методуindex.
- Отвечает за запрос на корневой адрес сайта, ведет к контроллеру
-
Динамический маршрут для пользовательской части (
'^(?P[a-z-]+)/(?P[a-z-]+)/?$'):- Этот маршрут позволяет пользователям обращаться к другим страницам сайта, передавая названия контроллеров и методов через URL. Например,
/posts/viewбудет соответствовать контроллеруpostsи методуview.
- Этот маршрут позволяет пользователям обращаться к другим страницам сайта, передавая названия контроллеров и методов через URL. Например,
Рекомендации
- Убедитесь, что ваши контроллеры и методы соответствуют правилам именования, заданным в маршрутах.
- Если вы используете специальные символы или цифры в именах контроллеров и действий, обновите регулярные выражения соответственно, чтобы они их принимали.
namespace blog;
class Router
{
protected static array $routes = [];
protected static array $route = [];
public static function add($regexp, $route = [])
{
self::$routes[$regexp] = $route;
}
public static function getRoutes(): array
{
return self::$routes;
}
public static function getRoute(): array
{
return self::$route;
}
public static function dispatch($url)
{
var_dump($url);
}
}
Итог
В заключение, как только мы создадим все необходимые маршруты и подключим к ним контроллеры, мы сможем обрабатывать запросы от пользователей эффективно и без лишнего кода. Надеюсь, что вся информация будет полезной, и в следующих статьях мы погрузимся в конкретный код и его структуру!
Таким образом, создание маршрутизатора - это не просто набор правил, это продуманная система, которая делает ваше приложение универсальным и стабильным. Давайте продолжим развивать наш проект, и вскоре мы увидим, как все эти элементы работают вместе!
А тепер подробно расмотрим!
Основные технологии
- PHP: Серверный язык программирования для создания фреймворка.
- Namespaces: Для организации кода и предотвращения конфликтов имен.
- Функции: Для упрощения и улучшения работы с данными.
Структура проекта
/vendor
└── /blog
├── /helpers
│ └── function.php
├── App.php
├── ErrorHandler.php
├── Router.php
/config
└── routes.php
/public
└── index.php
- vendor/blog/: Папка с классами для приложения.
- public/errors/: Папка для хранения шаблонов ошибок.
- tmp/logs/: Папка для хранения логов ошибок.
Разбор кода
1. Создание папки и файла с функциями
Создайте папку helpers в каталоге vendor/blog/ и добавьте файл function.php с функцией debug.
// vendor/blog/helpers/function.php
' . print_r($data, true) . '
'; if ($die) die(); }
Объяснение:
- Функция позволяет удобно выводить данные для отладки.
2. Подключение файла с функциями
Подключите этот файл в index.php:
// public/index.php
require_once HELPERS . '/function.php';
3. Создание файла маршрутов
Создайте файл routes.php в каталоге config:
// public/index.php
require_once CONFIG . '/routes.php';
4. Создание класса Router
Создайте класс Router в vendor/blog/Router.php.
// vendor/blog/Router.php
namespace blog;
class Router
{
protected static array $routes = [];
protected static array $route = ['admin_prefix' => '', 'controller' => '', 'action' => ''];
public static function add($regexp, $route = [])
{
self::$routes[$regexp] = $route;
}
public static function getRoutes(): array
{
return self::$routes;
}
public static function getRoute(): array
{
return self::$route;
}
public static function dispatch($url)
{
var_dump($url);
}
}
Объяснение:
- Класс
Routerсодержит массив маршрутов и методы для обработки запросов.
5. Вызов маршрутизатора в классе App
Вызовите маршрутизатор в классе App.
// vendor/blog/App.php
public function __construct()
{
session_start(); // Начало сеанса
$query = trim(urldecode($_SERVER['QUERY_STRING']), '/');
new ErrorHandler();
self::$app = Registry::getInstance();
$this->getParams();
Router::dispatch($query); // Вызов маршрутизатора
}
Объяснение:
- Получаем URL и передаем его в метод
dispatchмаршрутизатора.
6. Добавление маршрутов в routes.php
Добавьте маршруты в routes.php.
// config/routes.php
use blog\Router;
// Маршруты для администраторов
Router::add('^admin/?$', ['controller' => 'Main', 'action' => 'index', 'admin_prefix' => 'admin']);
Router::add('^admin/(?P[a-z-]+)/(?P[a-z-]+)/?$', ['admin_prefix' => 'admin']);
// Маршруты для главной страницы
Router::add('^(?P[a-z])?/?$', ['controller' => 'Main', 'action' => 'index']);
Router::add('^(?P[a-z-]+)/?(?P[a-z-]+)?$');
Объяснение:
- Здесь мы определяем маршруты для административной панели и главной страницы.
7. Обработка маршрутов в методе dispatch
Теперь реализуйте логику в методе dispatch.
public static function dispatch($url)
{
var_dump($url);
}
Заключение
Созданный нами маршрутизатор эффективно управляет запросами и помогает организовать структуру вашего приложения на PHP. Используйте предложенные инструменты и методы, чтобы развивать и расширять функциональность вашего фреймворка.
Если у вас есть вопросы или хотите узнать больше, не стесняйтесь обращаться в комментариях!
Добавить комментарий или задать вопрос ツ
Комментариев нет