Маршрутизация заказа аккаунта через единую точку входа

Раздел: Маршрутизация в веб-приложениях -> Маршруты PHP

Реализация маршрута заказа аккаунта

Наиболее эффективное решение для маршрута /account/order основано на единой точке входа index.php и классе-маршрутизаторе с поддержкой параметров. Этот подход обеспечивает гибкость, легкость поддержки и возможность расширения.

Пример базовой структуры файлов:


/project
  /src
    Router.php
  /public
    index.php
  .htaccess
  

Index php route information (маршрут информационной страницы php)

Код маршрутизатора Router.php:


<?php

class Router
{
    private array $routes = [];

    public function add(string $pattern, callable $handler): void
    {
        $this->routes[$pattern] = $handler;
    }

    public function dispatch(string $uri): void
    {
        $uri = parse_url($uri, PHP_URL_PATH);
        $uri = rtrim($uri, '/') ?: '/';

        foreach ($this->routes as $pattern => $handler) {
            $regex = $this->patternToRegex($pattern);
            if (preg_match($regex, $uri, $matches)) {
                array_shift($matches); // убираем полное совпадение
                call_user_func_array($handler, $matches);
                return;
            }
        }
        http_response_code(404);
        echo 'Страница не найдена';
    }

    private function patternToRegex(string $pattern): string
    {
        // Замена {param} на именованные группы
        $regex = preg_replace('/\{([a-zA-Z_]+)\}/', '(?P<$1>[^/]+)', $pattern);
        return '#^' . $regex . '$#';
    }
}
  

Index php route account order (маршрут заказа аккаунта php)

Файл index.php (точка входа):


<?php

require_once __DIR__ . '/../src/Router.php';

$router = new Router();

// Маршрут для заказа аккаунта: /account/order (без параметров)
$router->add('/account/order', function () {
    echo 'Оформление заказа аккаунта';
});

// Маршрут с параметром id: /account/order/123
$router->add('/account/order/{id}', function ($id) {
    echo "Заказ аккаунта с ID: " . htmlspecialchars($id);
});

$router->dispatch($_SERVER['REQUEST_URI']);
  

Ru index php route checkout (маршрут оформления заказа php (русский))

Проблемы и типичные ошибки:

Ошибка: все запросы возвращают 404. Причина: отсутствует файл .htaccess или не включён модуль mod_rewrite. Решение: создать .htaccess в корне public/:


RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
    

Index php route common home (маршрут общей домашней страницы php)

Также убедиться, что веб-сервер настроен на чтение .htaccess.

Как реализовать простой маршрут заказа аккаунта без дополнительных классов?

Можно использовать простой switch/case в index.php. Такой вариант подходит только для очень маленьких проектов с фиксированным набором маршрутов.


<?php

$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = rtrim($uri, '/') ?: '/';

switch ($uri) {
    case '/account/order':
        echo 'Заказ аккаунта';
        break;
    default:
        http_response_code(404);
        echo 'Не найдено';
        break;
}
  

Shop index php route (маршрут магазина php)

Проблема: при добавлении параметров (например, /account/order/42) нужно обрабатывать их вручную. Это приводит к разрастанию кода и усложнению поддержки.

Решение: для каждого варианта с параметрами придётся использовать explode() или регулярное выражение внутри case, что делает код громоздким.

Как обработать маршрут заказа аккаунта с помощью регулярных выражений вручную?

Можно написать собственную небольшую функцию для разбора URI по регулярному выражению. Это будет компактнее, чем полноценный класс.


<?php

function route($uri, $routes) {
    $uri = parse_url($uri, PHP_URL_PATH);
    $uri = rtrim($uri, '/') ?: '/';
    foreach ($routes as $pattern => $handler) {
        $regex = preg_replace('/\{([a-zA-Z_]+)\}/', '(?P<$1>[^/]+)', $pattern);
        $regex = '#^' . $regex . '$#';
        if (preg_match($regex, $uri, $matches)) {
            $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
            call_user_func($handler, $params);
            return;
        }
    }
    http_response_code(404);
    echo 'Страница не найдена';
}

$routes = [
    '/account/order' => function() {
        echo 'Базовый заказ аккаунта';
    },
    '/account/order/{id}' => function($params) {
        echo 'Заказ аккаунта #' . htmlspecialchars($params['id']);
    },
];

route($_SERVER['REQUEST_URI'], $routes);
  

Route info php id (информация о маршруте по id php)

Ошибка: если в пути есть лишний слеш в конце, результат может не совпадать. Необходимо всегда нормализовать URI (как в примере выше).

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

Как использовать готовые библиотеки маршрутизации для заказа аккаунта?

Популярные библиотеки, например nikic/FastRoute, предоставляют гибкую и производительную маршрутизацию. Пример подключения через Composer.


composer require nikic/fast-route
  

Index php route extension (маршрут расширения php)

Код в index.php:


<?php

require __DIR__ . '/../vendor/autoload.php';

$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
    $r->addRoute('GET', '/account/order', function() {
        echo 'Заказ аккаунта (FastRoute)';
    });
    $r->addRoute('GET', '/account/order/{id:\d+}', function($vars) {
        echo 'Заказ аккаунта #' . $vars['id'];
    });
});

$httpMethod = $_SERVER['REQUEST_METHOD'];
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = rtrim($uri, '/') ?: '/';

$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
switch ($routeInfo[0]) {
    case FastRoute\Dispatcher::NOT_FOUND:
        http_response_code(404);
        echo 'Не найдено';
        break;
    case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
        http_response_code(405);
        echo 'Метод не поддерживается';
        break;
    case FastRoute\Dispatcher::FOUND:
        $handler = $routeInfo[1];
        $vars = $routeInfo[2];
        call_user_func($handler, $vars);
        break;
}
  

Проблема: при неправильном порядке объявления маршрутов с параметрами возможны ложные срабатывания. FastRoute решает это автоматически, так как хранит маршруты в дереве – порядок не важен, но нужно правильно задавать регулярные выражения для параметров (например {id:\d+}).

Типичная ошибка: не обрабатывать разные HTTP методы. В примере выше добавлена проверка метода.

- Index php route common (маршрут общей страницы php)
- Index php route account (маршрут аккаунта php)
- Route index php page (маршрут страницы php)

Расширенные примеры маршрута заказа аккаунта

Пример 1. Обработка нескольких параметров в URL заказа аккаунта (например, /account/order/123/product/456).

Пример

// В классе Router (расширение)
$router->add('/account/order/{orderId}/product/{productId}', function ($orderId, $productId) {
    // Логика заказа аккаунта с товаром
    echo "Заказ аккаунта #$orderId, товар #$productId";
});
При запросе /account/order/7/product/99 вывод:
Заказ аккаунта #7, товар #99

Пример 2. Использование именованных параметров в функции обратного вызова. В классе Router можно передавать ассоциативный массив.

Пример

// Модифицируем dispatch для передачи именованных параметров
public function dispatch(string $uri): void
{
    ...
    if (preg_match($regex, $uri, $matches)) {
        $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
        call_user_func($handler, $params);
        return;
    }
    ...
}

// При добавлении маршрута
$router->add('/account/order/{id}', function ($params) {
    echo "Заказ аккаунта с ID: " . $params['id'];
});
Запрос /account/order/15 выведет:
Заказ аккаунта с ID: 15

Пример 3. Маршрут с обязательным указанием HTTP метода (GET, POST, PUT). Реализация через простой массив с методами.

Пример

$router->add('GET', '/account/order', function() { /* ... */ });
$router->add('POST', '/account/order', function() { /* обработка формы */ });

// В dispatch нужно проверять метод
public function dispatch(string $method, string $uri): void
{
    // ... поиск по маршрутам, затем проверка метода
}

Пример 4. Встроенная поддержка опциональных параметров (например, /account/order/{id?}). В классе Router можно модифицировать преобразование шаблона, а затем в обработчике проверять наличие параметра.

Пример

private function patternToRegex(string $pattern): string
{
    // Замена опциональных параметров {param?} на группу, которая может отсутствовать
    $regex = preg_replace('/\{([a-zA-Z_]+)\?\}/', '(?P<$1>[^/]*)?', $pattern);
    return '#^' . $regex . '$#';
}

// Пример маршрута
$router->add('/account/order/{id?}', function ($params) {
    $id = $params['id'] ?? 'не указан';
    echo "Заказ аккаунта с ID: $id";
});
При запросе /account/order вывод:
Заказ аккаунта с ID: не указан

При запросе /account/order/42 вывод:
Заказ аккаунта с ID: 42

Пример 5. Группировка маршрутов (префикс) – для упрощения можно определить общий префикс, например /account, и затем добавлять подмаршруты.

Пример

class RouterGroup
{
    private string $prefix;
    private array $routes = [];

    public function __construct(string $prefix)
    {
        $this->prefix = rtrim($prefix, '/');
    }

    public function add(string $path, callable $handler): void
    {
        $fullPath = $this->prefix . '/' . ltrim($path, '/');
        $this->routes[$fullPath] = $handler;
    }

    public function getRoutes(): array
    {
        return $this->routes;
    }
}

$accountGroup = new RouterGroup('/account');
$accountGroup->add('/order', function() { echo 'Заказ аккаунта'; });
$accountGroup->add('/order/{id}', function($id) { echo "Заказ #$id"; });

Пример 6. Обработка ошибок маршрутизации в отдельном классе. Если маршрут не найден, можно перенаправить на специальный контроллер.

Пример

$router->setNotFoundHandler(function() {
    http_response_code(404);
    echo 'Страница заказа не найдена';
});

// В dispatch
if (!found) {
    call_user_func($this->notFoundHandler);
}

Результат: вместо стандартного сообщения 404 выводится кастомизированный ответ.

Маршрут заказа аккаунта PHP - comments

En
Index php route account order (php)