@smart_pro
php начинающий

В чем суть роутера на php?

Знаю и и начитан о таких подобных вопросах как мой, но все же хочется более детальных объяснений. Единственное что я понял то что роутер в движках для сайтов работают с url адресами, парсит их и задает там какой то модуль для вывода страницы и т.д.
1. В чем суть роутера в целом?
2. Нужен ли он вообще?
3. Приведите маленький пример (желательно на функциях) роутера.
4. Можно ли обойтись без него?
Хочу разработать свой роутер ссылаясь на опыт уже существующих разработок.
P.s. разрабатываю свой мини движок для своего личного сайта(как блог).
  • Вопрос задан
  • 19766 просмотров
Решения вопроса 4
onqu
@onqu
weasy
1. Здесь пугают всякими контроллерами, ларавелями. Давайте жить проще. Для начала дадим определение модному слову роутер. Это маршрутизатор. Что делает маршрутизатор? Правильно. Обрабатывает маршруты, являясь связующим звеном. Маршрутом для web сайта принято считать метод запроса [GET, POST, PUT и другие] и компоненты URI.

например: https://ru.wikipedia.org/wiki/URI?foo=bar#title
[схема: https] :// [источник: ru.wikipedia.org] [путь: /wiki/URI] [запрос: ?foo=bar] [фрагмент: #title]


Но для определения маршрута может браться любая другая информация передаваемая серверу, определение выше это лишь наиболее употребляемые параметры.

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

2. Он необходим, если в приложении одна точка входа, когда любой запрос приходит на один файл.

3. Простой пример
// файл index.php

// Маршруты
// [маршрут => функция которая будет вызвана]
$routes = [
    // срабатывает при вызове корня или /index.php
    '/' => 'hello',
    // срабатывает при вызове /about или /index.php/about
    '/about' => 'about',
    // динамические страницы
    '/page' => 'page'
];

// возвращает путь запроса
// вырезает index.php из пути
function getRequestPath() {
    $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

    return '/' . ltrim(str_replace('index.php', '', $path), '/');
}

// наш роутер, в который передаются маршруты и запрашиваемый путь
// возвращает функцию если маршшрут совпал с путем
// иначе возвращает функцию notFound
function getMethod(array $routes, $path) {
    // перебор всех маршрутов
    foreach ($routes as $route => $method) {
        // если маршрут сопадает с путем, возвращаем функцию
        if ($path === $route) {
            return $method;
        }
    }

    return 'notFound';
}

// функция для корня
function hello() {
    return 'Hello, world!';
}

// функция для страницы "/about"
function about() {
    return 'About us.';
}

// чуть более сложный пример
// функция отобразит страницу только если
// в запросе приходит id и этот id равен
// 33 или 54
// [/page?id=33]
function page() {

    $pages = [
        33 => 'Сага о хомячках',
        54 => 'Мыши в тумане'
    ];

    if (isset($_GET['id']) && isset($pages[$_GET['id']])) {
        return $pages[$_GET['id']];
    }

    return notFound();
}

// метод, который отдает заголовок и содержание для маршрутов,
// которые не существуют
function notFound() {
    header("HTTP/1.0 404 Not Found");

    return 'Нет такой страницы';
}


// Роутер
// получаем путь запроса
$path = getRequestPath();
// получаем функцию обработчик
$method = getMethod($routes, $path);
// отдаем данные клиенту
echo $method();


На практике используют более сложные маршрутизаторы, у которых гораздо большие возможности.

4. Обойтись без него можно. Если каждая страница в вашем приложении будет являться отдельным файлом, который отвечает за отдачу информации.
index.php
about.php
contact.php
...


Это олдскульная структура, в новых проектах почти не применяется.
Ответ написан
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Роутер отвечает за доставку данных к контроллеру/сервису.
Если нет пути - роутер обычно выдаёт 404 ошибку.
URI роутером делится на: протокол, домен, сервис и переменные сервиса
например:
domain.com/catalog/145 - сервис catalog отображает ветку с ID 145
роутер - перенаправляет лишь запрос по части URI: /catalog
сервис catalog - сам берёт нужные ему переменные из запроса.

Еще примеры:
domain.com/catalog/145/add - сервис catalog отображает диалог добавления новой категории в существующую категорию с ID 145.
domain.com/catalog/145/sort/price/09/col/1/2/title - сервис catalog отображает категорию с ID 145 с сортировкой по цене от наименьшей к большей и выводом колонок с ID:1, ID:2, и по названию столбца: title.

Также, router может быть древовидным и рекурсивным.
Пример: domain.com/catalog/145/add/prod/24/56/37
Описание: Добавить в каталог с ID:145 товары с ID:24,56,37
Вначале, определяется, что категория с ID:145 существует и необходимо добавление, затем снова вызывается роутер с линком: /prod/24/56/37 и уже сервис prod проверяет существование продуктов и добавляет к каждому ID категорию 145 и так же возвращает результат в сервис catalog.
Шаблон страницы вывода - будет выбран согласно операции: add.

Таким образом, URI превращается в понятные предложения для общения пользователя/JS (front-end) с сервером через URI-запросы. Router - это как-бы механизм, "понимающий" то, что вы просите от веб-сайта через URI.
Суммарно: это примитивный язык общения в виде структурированных лексических "предложений" между сайтом и пользователем/JS посредством URI-запросов.
Ответ написан
Комментировать
iCoderXXI
@iCoderXXI
React.JS/FrontEnd engineer
Встречал "сайты", где весь код упакован в километровую простыню с кучей if/case, внутри которых и обрабатывались те или иные запросы. В целом это плохо по многим причинам, одна из которых - в интерпретатор при каждом запросе вгружается очень много кода, который надо распарсить и пр., и 99% которого не используется принципиально.

Чтобы подобные безобразия пресечь на корню, принято функциональные блоки выносить в отдельные "модули", и подгружать на конкретный запрос только их, в купе с ядром и стандартными библиотеками (что по сути можно назвать "фреймворк").

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

Для своего движка я сделал предельно простой роутер, который на входе ждет название модуля и его экшена, которому необходимо передать обработку запроса, причем модуль, по сути - это просто папка внутри папки modules, а экшен - это некая папка внутри папки модуля, т.е. modules/[module]/[action]/[action].php, соответственно модуль/экшен добавляется в проект через создание пары папок и файла. Все остальные параметры ЧПУ передаются в экшен в переменной GET.

Таким образом все что делает роутер - генерирует путь, и проверяет, есть ли там соответствующий файл PHP, и если есть - подгружает его и передает ему управление.

Если роутер не получил название экшена и.или модуля, то подставляется default, если по указанному пути файл не обнаружен, то выдается 404. Предельно просто и прозрачно, и всегда наверняка знаешь где и что лежит и как называется и почему.

Подобный подход практикуется в JavaScript фреймворке Ember.JS, под подходом я подразумеваю весьма жесткие соглашения относительно структуры и именования папок, и файлов проектов.

Шаблоны в моих проектах точно так же находятся в строго определенных местах и подключаются экшенами автоматически, если тип их выдачи HTML, иначе генерится JSON, или что-то еще, имеется несколько конвертеров на выходе, подключается тот, который запросил экшен.
Ответ написан
Комментировать
trevoga_su
@trevoga_su
Комментировать
Пригласить эксперта
Ответы на вопрос 3
akubintsev
@akubintsev
Опытный backend разработчик
По поводу пункта №2. Без роутера конфиг nginx/apache очень быстро разрастётся в километровую простыню и с каждой новой строчкой будет расти шанс что-то сломать.
Ответ написан
Комментировать
Вот детально описано, чем отличаются подходы фреймворков (с том числе роутеров) от обычного PHP
https://symfony.com.ua/doc/current/introduction/fr...

Документация по роутеру в Symfony
https://symfony.com.ua/doc/current/routing.html
Ответ написан
Комментировать
А почему, применяя маршрутизацию используют именно такой подход
www.my.site/docs/writes/news?id=7
а не набор GET параметров
www.my.site/index.php?docs=writes&news=7
Ведь короче проверить существование get параметра (isset($_GET['X'])) чем распарсить url и потом проверять наличие определенного пути в нем.

В чем преимущество первого варианта?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы