• Шаблоны для вашего сайта
  • Сделать сайт
  • Реклама
  • Berry CSS
  • Albireo Framework
  • Бесплатный HTML-курс
  • Telegram-канал
  • Обратная связь
MaxSite.org
О создании сайтов и не только
Создание сайтов под ключ (Украина) →
Вход
×
или зарегистрироваться

Как работает PHP-роутинг

PHPПросмотров: 5091Комментарии: 02 мая 2020 г.

Уж коли я затронул тему роутинга, то есть смысл немного окунуться в технические детали, поскольку большинство php-библиотек для роутинга представляются загадочными и сложными не только для новичков, но и опытных специалистов. Проблема здесь в том, что каждый разработчик пытается реализовать свои идеи, которые, как он думает, должны подходить для всех и каждого.

Данный подход делает php-разработки сложными и запутанными. PHP — такой язык программирования, который позволяет решать задачи просто и понятно. Во многих случаях не нужна лишняя обвеска и дополнительный уровень абстракции, которая только запутывает код. Работа с HTTP по какой-то мистической причине, часто обвешивается тонной абстракций, хотя всё крутится вокруг простых вещей.

Каркас приложения

Современное php-приложение строится достаточно просто. Все http-запросы отправляются в одну точку входа — это фронт-контролер. Обычный index.php в корне сайта. ЧПУ организуется в .htaccess. Приведу пример файла из одной своей разработки:

Options +FollowSymLinks
Options -Indexes
DirectoryIndex index.php
AddDefaultCharset UTF-8
 
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . / [L,QSA]
</IfModule>

В прошлой статье я уже рассказывал как это работает: всё передаётся в индексный файл (index.php).

Во фронт-контролере подключаются необходимые php-библиотеки, настраивается автозагрузка классов PSR-4 и определяются базовые константы (об этом я рассказывал в своём telegram-канале, поэтому не буду повторяться), например BASE_DIR, SITE_URL, SITE_PROTOCOL, SITE_HOST и т.д.

И после этого управление передаётся в точку входа application, то есть там, где непосредственно размещается ваше приложение. Например это будет файл app/bootstrap.php. Уже в этом файле запускается роутинг.

Следует отметить, что во многих php-фреймворках роутер подключается скрыто где-то в дебрях своих библиотек и модулей. Пользователю остаётся только возможность конфигурации через отдельные файлы. Полноценное управление роутером здесь невозможно. И уж тем более сменить его на какой-то свой вариант.

Запуск роутера

Поскольку app/bootstrap.php является точкой входа для приложения, то в нём и размещается роутер.

Роутер — это самый обычный php-класс, который может размещаться как угодно. Главное, чтобы он соответствовал PSR-4.

Первым делом создаём объект роутера. После этого считываем конфигурацию, где хранится массив правил для роутинга, скажем файл app/Config/routes.php.

Как хранить опции и конфигурации я также рассказывал недавно в своём telegram-канале.

Этот массив мы добавляем как правила роутинга. При этом мы можем прочитать и множество других файлов с правилами, для того, чтобы разделить их по модулям своего приложения, а не кидать всё в одну кучу. Правила роутинга суммируются и накапливаются в его объекте.

После этого можно задать специальное правило для случаев, если никакие другие не сработали. Это будет 404-страница, а точнее его класс и метод.

Дальше запускаем роутинг, который сам уже разруливает правила и подключает нужные классы. В некоторых php-фреймворках объект роутера даже именуется как $app, что показывает его основное назначение — запуск приложения.

В коде это выглядит так:

// создание объекта
$route = new \Lib\Router\Router;
 
// подключаем правила из конфига
if ($rules = \Lib\Core\Core::readConfig('routes.php'))
    $route->addRules($rules);
 
// данные для 404-страницы
$route->setNotFound('\Modules\Page404\Page404@index');
 
// run application
$route->run();

Правила роутинга

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

return [
    [
        'method' => 'GET',
        'pattern' => '', // home
        'action' => '\Modules\Home\Controller@index',
    ],
     
    [
        'method' => 'POST',
        'pattern' => '', // home
        'action' => '\Modules\Home\Controller@post',
    ],
  
    // contact использует класс Pages
    [
        'method' => 'GET',
        'pattern' => 'contact', 
        'action' => '\Modules\Pages\Pages@contact',
    ],
    
    [
        'method' => 'POST',
        'pattern' => 'contact', 
        'action' => '\Modules\Pages\Pages@contactPost',
    ],
];

Три основных ключа любого правила:

  • method — указывает на http-метод (GET, POST, OPTION, MYMETHOD). Любой вариант, можно и свой придумать. Для любого варианта используется ANY.
  • pattern — паттерн адреса. Представляет собой обычную регулярку. В роутере можно предусмотреть спецзамены для более простого использования ([:any], [:num], [:segment] и т.д.).
  • action — действие. Класс и метод, которые сработают на этот паттерн. Это может быть класс@метод, просто функция (function), либо название функции.

Кроме этого иногда нужно передать в action какие-то данные прямо из правила. В этом случае используется ключ param, где указывается, то что будет востребовано в выполняемом классе. Но, опять же это особые ситуации.

Лично я предпочитаю для конфигурации использовать именно php-массив, но многие роутинги позволяют добавлять эти же самые правила через строчку. Она парсится и добавляется во внутреннее поле объекта уже как положено в массиве.

В общем не важно как именно добавляются правила в итоге они всё равно должны описывать http-метод, URL-паттерн и действие для выполнения.

Метод setNotFound() описывает только action в том же формате.

Логика работы роутера

Запуск роутера происходит через метод run(). Первое, что там происходит — это сравнение текущего URL с паттернами правил. Например это может быть приватный метод match(), который возвращает результат сравнения.

В match() проверяется не только паттерн (это обычная регулярка), но и http-метод. Чтобы это сделать для текущего URL формируется массив его данных, который удобен для дальнейшего использования. Вот что-то такое:

[method] => GET
[method_data] => Array ()
[url] => 
[url_full] => http://сайт/
[query] => 
[url_segment] => Array
   (
      [0] => 
   )
[query_data] => Array ()

Разбор URL в большинстве случаев это не что иное, как данные из $_SERVER. В некоторых случаях ещё используют parse_url() и parse_str() для корректного декодирования адресов. Но в большинстве случаем роутинг любого php-проекта работает именно на этих трёх компонентах. Всё, что сверх этого — бессмысленная абстракция и утяжеление кода.

Когда match() находит совпадение по http-методу и паттерну, он парсит строчку action. На выходе получаем (в run() ) массив результата проверки, где уже подключаем файл, выполняем функцию или инициализируем объект указанного класса и выполняем указанный метод.

Если же возникла ситуация, что ни один action не сработал, то выполняем указанный для 404-страницы метод. Хотя, если и он не найден, то просто ничего не делаем. Роутер может вернуть false, который уже анализируется в app/bootstrap.php.

if (!$route->getResult()) echo '404-page';

Такой вариант позволяет не задавать 404-страницу для роутера.

Задача любого роутера — найти соответствие URL какому-то паттерну и запустить в случае успеха «что-то». Больше в его задачу ничего не входит, поскольку это уже лишнее.

Точно также, как и лишними будут многочисленные функции вроде getPost(), getGet() — возвращающие стандартные $_POST и $_GET. Разработчики PHP очень упростили задачу по работе с этими http-методами (включая и $_FILES) — подменять их своими функциями — больше смахивает на глупость.

HTTP-методы

В заключении пару слов от http-методах. На практике есть только два варианта: POST и GET. Именно их браузеры и поддерживают, хотя есть некие стандарты, которые предполагают существование других вариантов. Кроме того эти методы завязаны на HTML — в основном это обычные формы, либо Ajax-запросы. Во всех таких случаях, как ни крути, в реальности используется только POST.

Чтобы ничего не ломать, придумали хитрость: в post-запросе отправлять поле _method, который и содержит название http-метода. Для формы это выглядит так:

<form method="POST">
	<input type="hidden" name="_method" value="PUT">
	... прочие данные формы ...
</form>

То есть реальная отправка — POST, но роутер проверят наличие поля _method. Именно поэтому http-метод в php-роутере может быть абсолютно любым.

На этом базируется концепция RESTful и CRUD, где используется один адрес, но разные http-методы. Это указывается в правилах роутера:

[
    'method' => 'POST',
    'pattern' => 'task', // create new task (Create)
    'action' => '\Controller\Task\Task@create',
],
[
    'method' => 'GET',
    'pattern' => 'task', // task show (Read)
    'action' => '\Controller\Task\Task@read',
],
[
    'method' => 'PUT',
    'pattern' => 'task', // update/edit task (Update)
    'action' => '\Controller\Task\Task@update',
],
[
    'method' => 'DELETE',
    'pattern' => 'task', // delete task (Delete)
    'action' => '\Controller\Task\Task@delete',
],

А в форме что-то вроде такого:

...
<button type="submit" name="_method" value="PUT">Update selected</button>
<button type="submit" name="_method" value="DELETE">Delete selected</button>

В зависимости от сложности проекта, создаётся и роутинг. С моей точки зрения лучшим вариантом будет именно свой «велосипед», поскольку он на 100% покроет реальные задачи. Сторонние библиотеки всегда стараются сделать универсальными, а это приводит к тому, что 80% их возможностей просто не используются.


Создание сайтов (Украина) →
WAMP сервер своими руками
Виды PHP-роутинга
twitter.com facebook.com
Другие записи сайта
Шаблоны текста с помощью Punto Switcher
Шаблоны текста с помощью Punto Switcher
MVC (Model View Controller) в JavaFX
MVC (Model View Controller) в JavaFX
Как использовать функцию mail() в PHP
Как использовать функцию mail() в PHP
О главном :)
О главном :)
Организация CSS-кода
Организация CSS-кода
CodeIgniter 4. PSR-4. Произвольная MVC
CodeIgniter 4. PSR-4. Произвольная MVC
Оставьте комментарий!

Комментарий будет опубликован после проверки. Вы соглашаетесь с правилами сайта.

(обязательно)

Навигация
  • Шаблоны для MaxSite CMS 22
  • jQuery и JavaScript 6
  • Java и Android 5
  • PHP/ООП 25
  • SQL 17
  • Albireo Framework 11
  • Berry CSS 7
  • CSS, HTML, LESS, SASS 23
  • PHP 37
  • Тайм-менеджмент 9
  • Софт 37
  • SEO 13
  • Git. GitHub 3
  • CodeIgniter 5
  • Landing Page 3
  • Alpine.js 14
  • Фильмы 2
  • Дневник 55

Здесь можно заказать создание сайта (только Украина), шаблона или лендинга. Также вы можете выбрать готовые шаблоны для MaxSite CMS по небольшой цене. Также можно купить отдельные модули, компоненты для вашего сайта.

MaxSite.org
Как создать свой сайт

Услуги по созданию сайтов, блогов, лендингов
Обратная связь • Реклама на сайте
Карта сайта
Мои проекты
  • Шаблоны для вашего сайта
  • Заказать создание сайта
  • MaxSite CMS
  • Berry CSS (CSS Utilities)
  • Albireo Framework
  • UniCSS (Universal Atomic CSS)
  • Landing Page Framework
  • Бесплатные НТML-курсы
Ссылки
  • Telegram-канал
  • Github
  • Twitter
  • Telegram-бот
  • RSS
© MaxSite.org, 2006-2022. Работает на MaxSite CMS | Время: 0.2548 | SQL: 20 | Память: 4.63MB | Вход