Router Component

Компонент triangle/router предоставляет мощную систему маршрутизации с поддержкой различных алгоритмов диспетчеризации.

Установка

composer require triangle/router

Как это работает

Router автоматически загружается при старте приложения через Triangle\Router\Bootstrap. При инициализации:

  1. Загружаются маршруты из config/route.php
  2. Загружаются маршруты из плагинов (если установлены)
  3. Создается диспетчер для обработки запросов

Определение маршрутов

Важно: Файл config/route.php — это не конфигурационный файл с return, а обычный PHP-файл, который выполняется напрямую. В нем вызываются методы класса Router.

Базовое определение

<?php
// config/route.php

use Triangle\Request;
use Triangle\Response;
use Triangle\Router;

// Простой маршрут
Router::get('/', function (Request $request): Response {
    return response('Hello, World!');
});

// Маршрут с параметрами
Router::get('/user/{id}', function (Request $request, string $id): Response {
    return response("User ID: $id");
});

// Маршрут на контроллер
Router::get('/home', [\App\Controller\IndexController::class, 'index']);

HTTP-методы

Router::get('/users', [UserController::class, 'index']);
Router::post('/users', [UserController::class, 'store']);
Router::put('/users/{id}', [UserController::class, 'update']);
Router::patch('/users/{id}', [UserController::class, 'update']);
Router::delete('/users/{id}', [UserController::class, 'destroy']);
Router::head('/users/{id}', [UserController::class, 'show']);
Router::options('/users', [UserController::class, 'options']);

// Любой метод
Router::any('/path', [Controller::class, 'method']);

Параметры маршрутов

// Обязательный параметр
Router::get('/user/{id}', function (Request $request, string $id) {
    // ...
});

// Необязательный параметр
Router::get('/user/{id?}', function (Request $request, string $id = null) {
    // ...
});

// Несколько параметров
Router::get('/posts/{post}/comments/{comment}', function (
    Request $request,
    string $post,
    string $comment
) {
    // ...
});

Именованные маршруты

Router::get('/user/{id}', [UserController::class, 'show'])
    ->name('user.show');

// Генерация URL по имени маршрута
$url = route('user.show', ['id' => 123]);
// Результат: /user/123

Группировка маршрутов

// Группа с префиксом
Router::group('/api', function () {
    Router::get('/users', [UserController::class, 'index']);
    Router::get('/posts', [PostController::class, 'index']);
});

// Группа с префиксом и middleware
Router::group('/admin', function () {
    Router::get('/dashboard', [AdminController::class, 'dashboard']);
})->middleware(\App\Middleware\AuthMiddleware::class);

Middleware на маршруте

Router::get('/profile', [ProfileController::class, 'show'])
    ->middleware(\App\Middleware\AuthMiddleware::class);

// Несколько middleware
Router::get('/admin', [AdminController::class, 'index'])
    ->middleware([
        \App\Middleware\AuthMiddleware::class,
        \App\Middleware\AdminMiddleware::class,
    ]);

Автоматическая маршрутизация

Triangle поддерживает автоматическую маршрутизацию на основе контроллеров:

/app/controller/UserController::index  -> GET /user/index
/app/controller/UserController::show   -> GET /user/show

Автоматические маршруты работают для контроллеров в папке app/controller/.

Для отключения автоматической маршрутизации используйте аннотацию #[DisableDefaultRoute]:

<?php

namespace App\Controller;

use Triangle\Annotation\DisableDefaultRoute;
use Triangle\Request;
use Triangle\Response;

#[DisableDefaultRoute]
class UserController
{
    // Методы этого контроллера не будут автоматически маршрутизированы
}

Fallback маршруты

Маршрут по умолчанию для несуществующих URL:

Router::fallback(function (Request $request): Response {
    return response('404 Not Found', 404);
});

Работа с маршрутами в коде

use Triangle\Router;

// Получить маршрут по имени
$route = Router::getByName('user.show');

// Получить URL маршрута
$url = route('user.show', ['id' => 123]);

Алгоритмы диспетчеризации

Router поддерживает несколько алгоритмов для оптимизации производительности:

  • GroupCountBased — оптимален для большого количества маршрутов (по умолчанию)
  • MarkBased — самый быстрый для маршрутов с параметрами
  • CharCountBased — эффективен для маршрутов с различной длиной
  • GroupPosBased — комбинированный подход

Алгоритм выбирается автоматически при создании диспетчера в Router::collect().

Примеры использования

Полный пример route.php

<?php
// config/route.php

use Triangle\Request;
use Triangle\Response;
use Triangle\Router;

// Главная страница
Router::get('/', [\App\Controller\IndexController::class, 'index']);

// API маршруты
Router::group('/api', function () {
    Router::get('/users', [\App\Controller\Api\UserController::class, 'index']);
    Router::post('/users', [\App\Controller\Api\UserController::class, 'store']);
    Router::get('/users/{id}', [\App\Controller\Api\UserController::class, 'show']);
})->middleware(\App\Middleware\ApiAuthMiddleware::class);

// Админка
Router::group('/admin', function () {
    Router::get('/dashboard', [\App\Controller\Admin\DashboardController::class, 'index']);
    Router::get('/users', [\App\Controller\Admin\UserController::class, 'index']);
})->middleware([
    \App\Middleware\AuthMiddleware::class,
    \App\Middleware\AdminMiddleware::class,
]);

// Именованные маршруты
Router::get('/profile', [\App\Controller\ProfileController::class, 'show'])
    ->name('profile.show');

Router::get('/login', [\App\Controller\AuthController::class, 'showLogin'])
    ->name('login');

// Fallback
Router::fallback(function (Request $request): Response {
    return response('404 Not Found', 404);
});