devlibs / routing
a fast and flexible HTTP Router
Installs: 47
Dependents: 0
Suggesters: 0
Security: 0
Stars: 7
Watchers: 3
Forks: 0
Open Issues: 0
pkg:composer/devlibs/routing
Requires
- php: ^7.0
Requires (Dev)
- phpunit/phpunit: ^6.3
This package is not auto-updated.
Last update: 2025-10-20 12:23:04 UTC
README
A fast, flexible and scalable HTTP router for PHP.
Features
- Grouping and nested group
- Easy to design RESTful API
- Full Tests
- Flexible and scalable
- No third-party library dependencies
- Named Param Placeholder
- Detect all request methods of the specify path
- Straightforward documentation
Requirements
- PHP - 7.0,7.1,7.2andmasterare tested.
Install
composer require devlibs/routing:1.0.0
Documentation
include '/path-to-vendor/autoload.php'; use DevLibs\Routing\Router; // create an router instance $settings = [ 'middlewares' => [ 'DebugMiddleware', ], ]; $router = new Router($settings);
Register handler
Router::handle($method, $path, $handler, $settings = null);
- method-- stringor- array, case-sensitive, such as- GET,- GET|POST(split by- |, without space),- ['GET', 'POST']
- path- the path MUST start with slash- /, such as- /,- /users,- /users/<username>.
- handler-- mixed, whatever you want.
- settings- user-defined settings.
Examples
| Method | Path | Handler | Matched | Unmatched | 
|---|---|---|---|---|
| GET | / | handler | GET / | POST /get / | 
| GET|POST | /users | handler | GET /usersPOST /users | |
| ['GET', 'POST'] | /merchants | handler | GET /merchantsPOST /merchants | |
| GET | /users/<username> | handler | GET /users/fooGET /users/bar | |
| GET | /orders/<order_id:\d+> | handler | GET /orders/123456 | GET /orders/letters | 
It also provides a few shortcuts for registering handler:
- Router::delete
- Router::get
- Router::post
- Router::put
$router->get('/', 'handler'); $router->handle('GET|POST', '/users', 'handler'); $router->handle(['GET', 'POST'], '/merchants', 'handler'); $router->get('/users/<username>', 'handler'); $router->get('/orders/<order_id:\d+>', 'handler');
Dispatch request
Router::dispatch($method, $path);
- method- request method, case-sensitive.
- path- URI path
If matched, an Route instance which implements RouteInterface will be returns, null otherwise.
$path = '/users/baz'; $route = $router->dispatch(Router::METHOD_GET, $path); if (is_null($route)) { throw new \Exception('404 Not Found'); } // handle requset $handler = $route->handler(); // 'handler' $params = $route->params(); // ['username' => 'baz'] $settings = $route->settings(); // $settings
Route
Class Route implements RouteInterface, provides some basic methods.
You can also define your own Route class via the following code snippet:
Router::$routeClassName = 'namespace\MyRoute';
RouteInterface
Route class MUST implements this interface, see RouteInterface for more detail.
Named Params Placeholder
As the examples shown above, Router has ability to detect the param's value of the path.
In general, an placeholder pattern MUST be one of <name> and <name:regex>, it will be
converted to ([^/]+) and (regex) respectively.
You can also change it via replace the Router::$replacePatterns and Router::$replacements.
| Pattern | Path | Matched | Params | 
|---|---|---|---|
| /guests/<name> | /guests/小明 | YES | ['name' => '小明'] | 
| /guests/<name:\w+> | /guests/foo | YES | ['name' => 'foo'] | 
| /guests/<name:\w+> | /guests/小明 | NO | |
| /orders/<order_id:\d+> | /orders/123 | YES | ['order_id' => '123'] | 
| /orders/<order_id:\d+> | /orders/letters | NO | |
| /posts/<year:\d{4}>/<month:\d{2}>/<title> | /posts/2017/10/hello-world | YES | ['year' => '2017', 'month' => '10', title' => 'hello-world'] | 
| /posts/<year:\d{4}>/<month:\d{2}>/<title> | /posts/201/10/hello-world | NO | |
| /posts/<year:\d{4}>/<month:\d{2}>/<title> | /posts/2017/9/hello-world | NO | |
| /posts/<year:\d{4}><month:\d{2}>/<title> | /posts/201710/hello-world | YES | ['year' => '2017', 'month' => '10', title' => 'hello-world'] | 
Settings
You can extend Router via settings, such as param's default value and middleware etc, but this topic are out of
scope of this document.
Grouping
Grouping is an powerful feature of Router for separating modules or API's versions. And this library also implements this feature, it allows nested grouping.
Router::group($prefix, array $settings = []);
- prefix- group prefix, it MUST NOT contains slash- /.
- settings- settings for extending, it will inherits parent's settings.
// grouping $v1Settings = [ 'version' => '1', 'middlewares' => [ 'AuthMiddleware', ], ]; $v1 = $router->group('v1', $v1Settings); $v1->get('/hello', 'hello'); $route = $router->dispatch(Router::METHOD_GET, '/v1/hello'); // matched /** * [ * 'version' => '1', * 'middlewares' => [ * 'DebugMiddleware', * 'AuthMiddleware', * ], * ]; */ var_dump($route->settings());
// nested group $v1Users = $v1->group('users'); $v1Users->get('/', 'users'); $v1Users->get('/<name>', 'user profile'); $route = $router->dispatch(Router::METHOD_GET, '/v1/users'); // matched $route = $router->dispatch(Router::METHOD_GET, '/v1/users/bar'); // matched
RESTful API
As the examples shown above, it is obviously easy to design a RESTful API application.
$router->get('/products', 'products'); $router->post('/products', 'create product'); $router->get('/products/<product_id:\d+>', 'product detail'); $router->put('/products/<product_id:\d+>', 'update product'); $router->delete('/products/<product_id:\d+>', 'delete product');
Detect methods
In consideration of OPTIONS request, it provides an API for detecting all valid methods of the specify URI path.
Route::getAllowMethods($path, $methods = null);
- path- request URL path
- methods-- Router::$methodsdefined some common request methods, but it does not include all request methods, you can specify the methods if the key method is not one of the- Router::$methods.
$allowMethods = $router->getAllowMethods('/merchants'); // ['GET', 'POST']
FAQ
Package Not Found
Please add the following repository into repositories when composer complains about
that Could not find package devlibs/routing ....
{
    "type": "git",
    "url": "https://github.com/devlibs/routing.git"
}