1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/inhere-php-srouter

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README.md 25 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 23.04.2025 07:57 22ca927

Простой маршрутизатор на PHP

Лицензия Версия PHP Последняя стабильная версия Статус сборки Статус покрытия

Очень быстрый и легковесный маршрутизатор для запросов.

  • Без зависимостей, простой, быстрый, функционально полный
  • Легковесный и быстрый, скорость поиска не зависит от количества маршрутов
  • Поддерживает группы маршрутов, определение параметров маршрутов и множество вариантов настройки маршрутов
  • Поддерживает именование маршрутов, позволяющее получить зарегистрированный объект маршрута по имени
  • Поддерживает методы запроса: GET POST PUT DELETE HEAD OPTIONS ...
  • Поддерживает автоматическое сопоставление маршрутов с контроллерами, как в Yii, см. параметр конфигурации autoRoute (не рекомендуется)
  • Сравнительные данные нагрузочного тестирования см. в разделе тестирование маршрутизатора

Многие версии:

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

  • SRouter статический класс. Простое упаковывание Router, использование через статические методы (удобно для быстрого использования в маленьких приложениях)
  • CachedRouter наследует Router, версия с поддержкой кэширования маршрутов, которая может кэшировать информацию о маршрутах в файл
    • Подходит для использования в окружении php-fpm (кэширование позволит избежать затрат на сбор и анализ маршрутов каждый раз)
  • PreMatchRouter наследует Router, предварительный маршрутизатор. Более быстрый поиск маршрутов при большом количестве статических маршрутов
    • Подходит для использования в окружении php-fpm, в случае php-fpm, фактически, мы знаем маршрут path и метод запроса METHOD до сбора маршрутов
  • ServerRouter наследует Router, серверный маршрутизатор. Внутренняя поддержка временного кэширования динамических маршрутов. Подходит для использования в приложениях, которые постоянно находятся в памяти, таких как swoole
    • Последние динамические маршруты, которые были запрошены, кэшируются как статические маршруты, следующий запрос к такому маршруту будет сразу найденВстроенные маршрутизаторы:- Поддерживаемые события: found notFound execStart execEnd execError. При срабатывании события вы можете выполнить определенные действия (например, запись логов и т.д.).
  • Поддержка динамического получения имени action. Поддержка настройки метода исполнителя (actionExecutor), через который можно настроить вызов реального метода запроса.
  • Поддержка ручного распределения маршрута методом $router->dispatch($path, $method)
  • Даже без настроек, он будет работать хорошо

Управление маршрутизацией

RouterManager позволяет удобно настроить несколько маршрутизаторов для обработки запросов с нескольких доменов в одном проекте

EN README

Проект

Установка

  • Команда composer
composer require inhere/sroute
  • composer.json
{
    "require": {
        "inhere/sroute": "dev-master"
    }
}
  • Прямое клонирование
git clone https://github.com/inhere/php-srouter.git // github

Пресс-тестирование

Автоматически сгенерировано 1000 маршрутов, каждый из которых имеет 9 параметров, и проведено тестирование для каждого маршрута 1000 раз

  • Соответствие первого маршрута
  • Соответствие последнего маршрута
  • Соответствие маршрута, которого нет

Для просмотра полного кода тестирования перейдите в репозиторий https://github.com/ulue/php-router-benchmark- Дата пресс-тестирования 2018.11.19

  • Пример маршрута: /9b37eef21e/{arg1}/{arg2}/{arg3}/{arg4}/{arg5}/{arg6}/{arg7}/{arg8}/{arg9}/bda37e9f9b

Наихудший случай соответствия

Этот тестовый сценарий проверяет соответствие последнего маршрута и маршрута, которого нет. Он генерирует случайно префиксированный и суффиксированный маршрут, чтобы помешать оптимизации. 1000 маршрутов, каждый из которых имеет 9 аргументов.Этот тестовый сценарий состоит из 14 тестов. Каждый тест выполняется 1000 раз, результаты обрабатываются, и затем усредняются. Значения, которые выходят за пределы 3 стандартных отклонений от среднего, отбрасываются.

Тестовое имя Результаты Время (мс) + Интервал Изменение
inhere/sroute(Router) - неизвестный маршрут (1000 маршрутов) 990 0.002031 +0.000871 75% медленнее
inhere/sroute(SRouter) - неизвестный маршрут (1000 маршрутов) 994 0.002895 +0.001736 150% медленнее
inhere/sroute(Router) - последний маршрут (1000 маршрутов) 997 0.005300 +0.004141 357% медленнее
inhere/sroute(SRouter) - последний маршрут (1000 маршрутов) 997 0.006467 +0.005308 458% медленнее
symfony/routing(кэшированный) - неизвестный маршрут (1000 маршрутов) 976 0.012777 +0.011618 1002% медленнее
symfony/routing(кэшированный) - последний маршрут (1000 маршрутов) 996 0.013608 +0.012449 1074% медленнее
mindplay/timber - последний маршрут (1000 маршрутов) 998 0.017211 +0.016052 1385% медленнее
FastRoute - неизвестный маршрут (1000 маршрутов) 991 0.039429 +0.038270 3302% медленнее
FastRoute(кэшированный) - неизвестный маршрут (1000 маршрутов) 990 0.040800 +0.039641 3420% медленнее
FastRoute(кэшированный) - последний маршрут (1000 маршрутов) 999 0.045065 +0.043906 3788% медленнее
FastRoute - последний маршрут (1000 маршрутов) 999 0.064694 +0.063535 5481% медленнее
Pux PHP - неизвестный маршрут (1000 маршрутов) 978 0.316016 +0.314857 27163% медленнее
symfony/routing - неизвестный маршрут (1000 маршрутов) 992 0.359482 +0.358323 30912% медленнее
Pux PHP - последний маршрут (1000 маршрутов) 999 0. 440489 +0. 439330 37901% медленнее
Macaw - неизвестный маршрут (1000 маршрутов) 991 1. 687441 +1. 686282 145475% медленнее
Macaw - последний маршрут (1000 маршрутов) 999 1. 786542 +1. 785383 154024% медленнее

Первое совпадение маршрутаЭтот бенчмарк проверяет, насколько быстро каждый маршрутизатор может найти первое совпадение маршрута. 1000 маршрутов, каждый с 9 аргументами.

Этот бенчмарк состоит из 7 тестов. Каждый тест выполняется 1000 раз, результаты обрабатываются, а затем усредняются. Значения, которые выходят за пределы 3 стандартных отклонений от среднего, отбрасываются.

Название теста Результаты Время Интервал Изменение
nikic/fast-route - первое совпадение маршрута(1000) 998 0.002929 +0.001571 116% медленнее
corneltek/pux(php) - первое совпадение маршрута(1000) 996 0.002971 +0.001613 119% медленнее
inhere/sroute(Router) - первое(1000) 979 0.006202 +0.004844 357% медленнее
inhere/sroute(SRouter) - первое(1000) 999 0.006627 +0.005269 388% медленнее
symfony/routing(cached) - первое совпадение маршрута(1000) 985 0.006858 +0.005501 405% медленнее
symfony/routing - первое совпадение маршрута(1000) 995 0.023105 +0.021747 1601% медленнее
nikic/fast-route(cached) - первое совпадение маршрута(1000) 999 0.041133 +0.039775 2929% медленнее
Macaw - первое совпадение маршрута (1000 маршрутов) 999 1.782017 +1.780659 131128% медленнее

Использование

Методы и параметры всех версий одинаковы

Сначала нужно импортировать класс

use Inhere\Route\Router;

$router = new Router();

Быстрый старт

Создайте простой файл public/index.php:

use Inhere\Route\Router;

// Сначала нужно загрузить файл autoload
require dirname(__DIR__) . '/vendor/autoload.php';
``````php
$router = new Router();

$router->get('/', function() {
    echo 'привет';
});

// Начать маршрутизацию
$router->dispatch();

Запустите тестовый сервер с помощью php: php -S 127.0.0.1:8080 -t ./public

Теперь вы можете посетить http://127.0.0.1:8080 и увидеть вывод "привет"

  • Без использования Composer

Если вы скачали пакет кода напрямую, вы можете загрузить файл test/boot.php, или загрузить его в пространство имен Inhere\Route.

Замените вышеупомянутую загрузку autoload.php следующим кодом:

require dirname(__DIR__) . '/test/boot.php';

Добавление маршрута

// Соответствует GET запросу. Обработчик - это замыкание Closure
$router->get('/', function() {
    echo 'привет';
});

// Соответствует параметру 'test/john'
$router->get('/test/{name}', function($params) {
    echo $params['name']; // 'john'
}, [
    'name' => '\w+', // Добавляет ограничение на соответствие параметра. Если ограничение не добавлено, будет автоматически установлено соответствие с любым символом, кроме '/'
]);

// Поддержка необязательных параметров. Соответствует 'hello' 'hello/john'
$router->get('/hello[/{name}]', function() {
    echo $params['name'] ?? 'Нет ввода'; // 'john'
}, [
    'name' => '\w+', // Добавление ограничений для параметров
]);

// Соответствует POST-запросам
$router->post('/user/login', function() {
    var_dump($_POST);
});

// Соответствует GET или POST
$router->map(['get', 'post'], '/user/login', function() {
    var_dump($_GET, $_POST);
});

// Разрешает любые методы запроса
$router->any('/home', function() {
    echo 'Привет, вы запросили страницу /home';
});
$router->any('/404', function() {
    echo "Извините, эта страница не найдена.";
});
```### Использование групп маршрутов

```php
// Группа маршрутов
$router->group('/user', function ($router) {
    $router->get('/', function () {
        echo 'Привет. Вы запросили: /user/';
    });
    $router->get('/index', function () {
        echo 'Привет. Вы запросили: /user/index';
    });
});

Использование контроллеров

// Использование контроллеров
$router->get('/', App\Controllers\HomeController::class);
$router->get('/index', 'App\Controllers\HomeController@index');

Запасной обработчик маршрутов

Можно зарегистрировать запасной обработчик маршрутов. Когда маршрут не соответствует, будет использован этот обработчик.

$router->any('*', 'fallback_handler');

Если настроено 'ignoreLastSlash' => true, '/index' эквивалентно '/index/'

Внимание

Необязательные параметры могут быть только в конце маршрута.

Правильные:

/hello[/{name}]      // соответствует: /hello/tom   /hello
/my[/{name}[/{age}]] // соответствует: /my/tom/78  /my/tom

Неправильные:

/my[/{name}]/{age}

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

Поддерживает соответствие маршрутов по URI запроса автоматически (как в yii), необходимо настроить autoRoute.

    'autoRoute' => 1, // Включено
    'controllerNamespace' => 'App\\Controllers', // Пространство имен контроллеров
    'controllerSuffix' => 'Controller', // Заключение класса контроллера

Пожалуйста, обратитесь к примеру example для использования

Теперь запросы к /demo /demo/test, которые не были настроены, будут автоматически пытаться найти App\\Controllers пространство имен и DemoControllerЛогика поиска:

  • Если есть только одна часть (например, /demo), то она будет использована как имя класса контроллера для поиска.
  • Если есть две или более части, то последняя часть будет использована как имя класса контроллера, а предпоследняя как действие.
  • Если поиск не удаётся, то предпоследняя часть будет использована как имя класса контроллера, а последняя как действие.

Установка конфигурации маршрутизации

// установка конфигурации
$router->config([
    'ignoreLastSlash' => true,    
    'autoRoute' => 1,
    'controllerNamespace' => 'app\\controllers',
    'controllerSuffix' => 'Controller',
]);

ВНИМАНИЕ: Необходимо вызвать $router->config() до добавления маршрутов

Соответствие маршрутов

array public function match($path, $method)
  • $path string Путь URI запроса
  • $method string Метод запроса
  • Возвращает array Информацию о соответствующем маршруте

Пример

На основе URI path запроса и метода запроса ищет соответствующий определённый нами маршрут.

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];

$routeInfo = $router->match($path, $method);

На основе возвращённой информации о маршруте, можно свободно определить, как вызывать соответствующее действие.

Структура возвращаемых данных можно посмотреть в документации по ключевым методам

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

Если вы не хотите реализовывать распределение маршрутов самостоятельно, вы можете использовать встроенный маршрутизатор `Inhere\Route\Dispatcher\Dispatcher````php use Inhere\Route\Dispatcher\Dispatcher;

$dispatcher = new Dispatcher([ // имя метода действия по умолчанию 'defaultAction' => 'index',

'actionPrefix' => '',

'actionSuffix' => 'Action',

'dynamicAction' => true,
// @см. Router::$globalParams['act']
'dynamicActionVar' => 'act',

]);


### Установка обработки событий

```php
// Успешное соответствие маршрута
$dispatcher->on(Dispatcher::ON_FOUND, function ($uri, $cb) use ($app) {
    $app->logger->debug("Соответствующий путь URI: $uri, устанавливаемый обратный вызов: " . is_string($cb) ? $cb : get_class($cb));
});

// При несоответствии маршрута, перенаправление на '/404'
$dispatcher->on('notFound', '/404');
// Или, при несоответствии маршрута, вывод сообщения...
$dispatcher->on('notFound', function ($uri) {
    echo "страница $uri не найдена!";
});

Использование методов контроллера

С помощью символа @ можно указать метод для выполнения, соединяя класс контроллера и имя метода.

$router->get('/', App\Controllers\HomeController::class);

$router->get('/index', 'App\Controllers\HomeController@index');
$router->get('/about', 'App\Controllers\HomeController@about');

ВНИМАНИЕ: Если второй параметр является только классом, будет попытка выполнить метод по умолчанию, определенный в конфигурации defaultAction

Динамическое соответствие методов контроллера

'dynamicAction' => true,  // Включить
// имя метода действия соответствует имени параметра, удовлетворяющему условию, будет использоваться в качестве имени действия
// @see Router::$globalParams['act'] соответствует '[a-zA-Z][\w-]+'
'dynamicActionVar' => 'act',
```> ВНИМАНИЕ: Использование динамического соответствия методов контроллера требует использования `any()` для добавления маршрутов. В этом случае нельзя ограничивать метод запроса `REQUEST_METHOD`.

```php
// доступ к '/home/test' выполнит 'App\Controllers\HomeController::test()'
$router->any('/home/{act}', App\Controllers\HomeController::class);

// может соответствовать '/home', '/home/test' и т.д.
$router->any('/home[/{act}]', App\Controllers\HomeController::class);

ВНИМАНИЕ: Разница между двумя примерами заключается в том, что первый не может соответствовать '/home'

Использование метода-исполнителя

Настройте actionExecutor на имя метода, которое вам нужно, например, настройте 'actionExecutor' => 'run', тогда все запросы к методам будут отправлены этому методу. Метод run($action) получит реальное действие в качестве параметра, вам нужно будет использовать этот метод для выполнения реального запроса к методу.

ВНИМАНИЕ: Полезно, когда вы хотите интегрировать маршрутизатор в свой собственный фреймворк

Пример:

// доступ к '/user' вызовет App\Controllers\UserController::run('')
$router->get('/user', 'App\Controllers\UserController');

// доступ к '/user/profile' вызовет App\Controllers\UserController::run('profile')
$router->get('/user/profile', 'App\Controllers\UserController');

// одновременно настройте 'actionExecutor' => 'run' и 'dynamicAction' => true,
// доступ к '/user' вызовет App\Controllers\UserController::run('')
// доступ к '/user/profile' вызовет App\Controllers\UserController::run('profile')
$router->any('/user[/{name}]', 'App\Controllers\UserController');
```## Начало маршрутизации и распределения

```php
$router->dispatch($dispatcher);

Пример выполнения

Пример кода находится в папке example.

  • версия объекта

Вы можете запустить тестовый сервер с помощью php -S 127.0.0.1:5670 example/object.php, теперь вы можете получить доступ к http://127.0.0.1:5670

Тестирование

phpunit
  • простой benchmark
php example/benchmark.php

Лицензия

MIT

Мои другие проекты

inhere/console github git@osc

Богатый функциональностью командный интерфейс приложения, библиотека командного интерфейса.

inhere/php-validate github git@osc

Простая и компактная библиотека для валидации PHP с полезными функциями. Состоит из нескольких файлов без каких-либо зависимостей.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/inhere-php-srouter.git
git@api.gitlife.ru:oschina-mirror/inhere-php-srouter.git
oschina-mirror
inhere-php-srouter
inhere-php-srouter
master