SRoute

August 19, 2022 · View on GitHub

License PHP Version Latest Stable Version Unit-tests Coverage Status

A very lightweight and fasted request router. lightweight web framework.

  • Lightweight and fast speed, the search speed is not affected by the routing number
  • supported request methods: GET POST PUT DELETE HEAD OPTIONS
  • support event: found notFound. Some things you can do when the triggering event (such as logging, etc.)
  • support manual dispatch a URI route by $router->dispatch($path, $method), you can dispatch a URI in your logic.
  • Support automatic matching routing like yii framework, by config autoRoute.
  • more interesting config, please see $router->config
  • You can also do not have to configure anything, it can also work very well

中文README更详细

Project

Install

required PHP 8.0+

  • by composer.json
{
    "require": {
        "inhere/sroute": "dev-master"
    }
}
  • by composer require
composer require inhere/sroute

Benchmark

Test time: 2018.11.19

Worst-case matching

This benchmark matches the last route and unknown route. It generates a randomly prefixed and suffixed route in an attempt to thwart any optimization. 1,000 routes each with 9 arguments.

This benchmark consists of 14 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded.

Test NameResultsTime(ms)+ IntervalChange
inhere/sroute(Router) - unknown route(1000 routes)9900.002031+0.00087175% slower
inhere/sroute(SRouter) - unknown route(1000 routes)9940.002895+0.001736150% slower
inhere/sroute(Router) - last route(1000 routes)9970.005300+0.004141357% slower
inhere/sroute(SRouter) - last route(1000 routes)9970.006467+0.005308458% slower
symfony/routing(cached) - unknown route(1000 routes)9760.012777+0.0116181002% slower
symfony/routing(cached) - last route(1000 routes)9960.013608+0.0124491074% slower
mindplay/timber - last route(1000 routes)9980.017211+0.0160521385% slower
FastRoute - unknown route(1000 routes)9910.039429+0.0382703302% slower
FastRoute(cached) - unknown route(1000 routes)9900.040800+0.0396413420% slower
FastRoute(cached) - last route(1000 routes)9990.045065+0.0439063788% slower
FastRoute - last route(1000 routes)9990.064694+0.0635355481% slower
Pux PHP - unknown route(1000 routes)9780.316016+0.31485727163% slower
symfony/routing - unknown route(1000 routes)9920.359482+0.35832330912% slower
symfony/routing - last route(1000 routes)9990.418813+0.41765436031% slower
Pux PHP - last route(1000 routes)9990.440489+0.43933037901% slower
Macaw - unknown route(1000 routes)9911.687441+1.686282145475% slower
Macaw - last route(1000 routes)9991.786542+1.785383154024% slower

First route matching

This benchmark tests how quickly each router can match the first route. 1,000 routes each with 9 arguments.

This benchmark consists of 7 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded.

Test NameResultsTime+ IntervalChange
nikic/fast-route - first route(1000)9980.002929+0.001571116% slower
corneltek/pux(php) - first route(1000)9960.002971+0.001613119% slower
inhere/sroute(Router) - first(1000)9790.006202+0.004844357% slower
inhere/sroute(SRouter) - first(1000)9990.006627+0.005269388% slower
symfony/routing(cached) - first route(1000)9850.006858+0.005501405% slower
symfony/routing - first route(1000)9950.023105+0.0217471601% slower
nikic/fast-route(cached) - first route(1000)9990.041133+0.0397752929% slower
Macaw - first route (1000 routes)9991.782017+1.780659131128% slower

Usage

first, import the class

use Inhere\Route\Router;

$router = new Router();

add some routes

// match GET. handler use Closure
$router->get('/', function() {
    echo 'hello';
});

// access 'test/john'
$router->get('/test/{name}', function($params) {
    echo $params['name']; // 'john'
}, ['name' => '\w+']); 

// match POST
$router->post('/user/login', function() {
    var_dump($_POST);
});

// match GET or POST
$router->map(['get', 'post'], '/user/login', function() {
    var_dump($_GET, $_POST);
});

// match any method
$router->any('/home', function() {
    echo 'hello, you request page is /home';
});

// route group
$router->group('/user', function () {
    $router->get('/', function () {
        echo 'hello. you access: /user/';
    });
    $router->get('/index', function () {
        echo 'hello. you access: /user/index';
    });
});

Use controller action

// if you config 'ignoreLastSlash' => true, '/index' is equals to '/index/'
$router->get('/index', 'app\controllers\Home@index');

Dynamic action

match dynamic action, config 'dynamicAction' => true

NOTICE: use dynamic action, should be use any().

// access '/home/test' will call 'app\controllers\Home::test()'
$router->any('/home/{name}', app\controllers\Home::class);

// can match '/home', '/home/test'
$router->any('/home[/{name}]', app\controllers\Home::class);

Use action executor

if you config 'actionExecutor' => 'run'

// access '/user', will call app\controllers\User::run('')
// access '/user/profile', will call app\controllers\User::run('profile')
$router->get('/user', 'app\controllers\User');
$router->get('/user/profile', 'app\controllers\User');

// if config 'actionExecutor' => 'run' and 'dynamicAction' => true,
// access '/user', will call app\controllers\User::run('')
// access '/user/profile', will call app\controllers\User::run('profile')
$router->get('/user[/{name}]', 'app\controllers\User');

Automatic matching is routed to the controller

Support automatic matching like yii routed to the controller, need config autoRoute.

    'autoRoute' => 1, // enanbled
    'controllerNamespace' => 'Example\\controllers', // The controller class in the namespace
    'controllerSuffix' => 'Controller', // The controller class suffix

setting config

// set config
$router->config([
    'ignoreLastSlash' => true,
    
    // enable autoRoute, work like yii framework
    // you can access '/demo' '/admin/user/info', Don't need to configure any route
    'autoRoute' => 1,
    'controllerNamespace' => 'Example\\controllers',
    'controllerSuffix' => 'Controller',
]);
  • default config
// there are default config.
[
    // ignore last '/' char. If is True, will clear last '/', so '/home' equals to '/home/'
    'ignoreLastSlash' => false,

    // auto route match @like yii framework
    // If is True, will auto find the handler controller file.
    'autoRoute' => false,
    // The default controllers namespace, is valid when `'enable' = true`
    'controllerNamespace' => '', // eg: 'app\\controllers'
    // controller suffix, is valid when `'enable' = true`
    'controllerSuffix' => '',    // eg: 'Controller'
]

NOTICE: you must call $router->config() on before the add route.

Route dispatcher

use Inhere\Route\Dispatcher;

$dispatcher = new Dispatcher([
    'dynamicAction' => true,
]);

Events

$dispatcher->on(Dispatcher::ON_FOUND, function ($uri, $route) use ($app) {
    $app->logger->debug("Matched uri path: $uri");
});

// on notFound, redirect to '/404'
$dispatcher->on('notFound', '/404');
// can also, on notFound, output a message.
$dispatcher->on('notFound', function ($uri) {
    echo "the page $uri not found!";
});

begin dispatch

$router->dispatch($dispatcher);

example

please the example folder's codes.

you can run a test server by php -S 127.0.0.1:5670 -t example/static, now please access http://127.0.0.1:5670

License

MIT