{"id":15694192,"url":"https://github.com/razonyang/routing","last_synced_at":"2025-10-08T10:57:37.220Z","repository":{"id":56966813,"uuid":"105111515","full_name":"razonyang/routing","owner":"razonyang","description":"A fast, flexible and scalable HTTP router for PHP.","archived":false,"fork":false,"pushed_at":"2017-10-24T03:07:52.000Z","size":36,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-27T01:33:29.248Z","etag":null,"topics":["fast","flexible","grouping","http","php","restful-api","router"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/razonyang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-28T06:40:00.000Z","updated_at":"2019-08-22T06:32:06.000Z","dependencies_parsed_at":"2022-08-21T09:50:39.454Z","dependency_job_id":null,"html_url":"https://github.com/razonyang/routing","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razonyang%2Frouting","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razonyang%2Frouting/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razonyang%2Frouting/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razonyang%2Frouting/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/razonyang","download_url":"https://codeload.github.com/razonyang/routing/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252866988,"owners_count":21816586,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fast","flexible","grouping","http","php","restful-api","router"],"created_at":"2024-10-03T18:54:07.159Z","updated_at":"2025-10-08T10:57:32.190Z","avatar_url":"https://github.com/razonyang.png","language":"PHP","readme":"# PHP Router\r\n\r\n[![Build Status](https://travis-ci.org/devlibs/routing.svg?branch=master)](https://travis-ci.org/devlibs/routing) \r\n[![Coverage Status](https://coveralls.io/repos/github/devlibs/routing/badge.svg?branch=master)](https://coveralls.io/github/devlibs/routing?branch=master)\r\n[![Latest Stable Version](https://poser.pugx.org/devlibs/routing/v/stable.svg)](https://packagist.org/packages/devlibs/routing)\r\n[![Total Downloads](https://poser.pugx.org/devlibs/routing/downloads.svg)](https://packagist.org/packages/devlibs/routing)\r\n[![License](https://poser.pugx.org/devlibs/routing/license.svg)](LICENSE)\r\n\r\nA fast, flexible and scalable HTTP router for PHP.\r\n\r\n## Features\r\n\r\n- **Grouping and nested group**\r\n- **Easy to design RESTful API**\r\n- **Full Tests**\r\n- **Flexible and scalable**\r\n- **No third-party library dependencies**\r\n- **Named Param Placeholder**\r\n- **Detect all request methods of the specify path**\r\n- **Straightforward documentation**\r\n\r\n## Requirements\r\n\r\n- PHP - `7.0`, `7.1`, `7.2` and `master` are tested.\r\n\r\n## Install\r\n\r\n```\r\ncomposer require devlibs/routing:1.0.0\r\n```\r\n\r\n## Documentation\r\n\r\n```php\r\ninclude '/path-to-vendor/autoload.php';\r\n\r\nuse DevLibs\\Routing\\Router;\r\n\r\n// create an router instance\r\n$settings = [\r\n    'middlewares' =\u003e [\r\n        'DebugMiddleware',\r\n    ],\r\n];\r\n$router = new Router($settings);\r\n```\r\n\r\n### Register handler\r\n\r\n```php\r\nRouter::handle($method, $path, $handler, $settings = null);\r\n```\r\n\r\n- `method` - `string` or `array`, **case-sensitive**, such as `GET`, `GET|POST`(split by `|`, without space), `['GET', 'POST']`\r\n- `path` - the path **MUST** start with slash `/`, such as `/`, `/users`, `/users/\u003cusername\u003e`.\r\n- `handler` - `mixed`, whatever you want.\r\n- `settings` - user-defined settings.\r\n\r\n\r\nExamples\r\n\r\n| Method                     | Path                           | Handler | Matched                            | Unmatched                              |\r\n|:---------------------------|:-------------------------------|:--------|:-----------------------------------|----------------------------------------|\r\n| `GET`                      | `/`                            | handler | `GET /`                            | `POST /` `get /`                       |\r\n| \u003ccode\u003eGET\u0026#124;POST\u003c/code\u003e | `/users`                       | handler | `GET /users` `POST /users`         |                                        |\r\n| `['GET', 'POST']`          | `/merchants`                   | handler | `GET /merchants` `POST /merchants` |                                        |\r\n| `GET`                      | `/users/\u003cusername\u003e`            | handler | `GET /users/foo` `GET /users/bar`  |                                        |\r\n| `GET`                      | `/orders/\u003corder_id:\\d+\u003e`       | handler | `GET /orders/123456`               | `GET /orders/letters`                  |\r\n\r\nIt also provides a few shortcuts for registering handler:\r\n\r\n- `Router::delete`\r\n- `Router::get`\r\n- `Router::post`\r\n- `Router::put`\r\n\r\n```php\r\n$router-\u003eget('/', 'handler');\r\n\r\n$router-\u003ehandle('GET|POST', '/users', 'handler');\r\n\r\n$router-\u003ehandle(['GET', 'POST'], '/merchants', 'handler');\r\n\r\n$router-\u003eget('/users/\u003cusername\u003e', 'handler');\r\n\r\n$router-\u003eget('/orders/\u003corder_id:\\d+\u003e', 'handler');\r\n```\r\n\r\n### Dispatch request\r\n\r\n```php\r\nRouter::dispatch($method, $path);\r\n```\r\n\r\n- `method` - request method, **case-sensitive**.\r\n- `path` - URI path\r\n\r\nIf matched, an [`Route`](#route) instance which implements [`RouteInterface`](#routeinterface) will be returns, `null` otherwise.\r\n\r\n```php\r\n$path = '/users/baz';\r\n$route = $router-\u003edispatch(Router::METHOD_GET, $path);\r\nif (is_null($route)) {\r\n    throw new \\Exception('404 Not Found');\r\n}\r\n\r\n// handle requset\r\n$handler = $route-\u003ehandler(); // 'handler'\r\n$params = $route-\u003eparams(); // ['username' =\u003e 'baz']\r\n$settings = $route-\u003esettings(); // $settings\r\n```\r\n\r\n### Route\r\n\r\nClass `Route` implements [`RouteInterface`](#routeinterface), provides some basic methods.\r\n\r\nYou can also define your own `Route` class via the following code snippet:\r\n\r\n```php\r\nRouter::$routeClassName = 'namespace\\MyRoute';\r\n```\r\n\r\n### RouteInterface\r\n\r\n`Route` class **MUST** implements this interface, see [`RouteInterface`](src/RouteInterface.php) for more detail.\r\n\r\n### Named Params Placeholder\r\n\r\nAs the examples shown above, Router has ability to detect the param's value of the path.\r\n\r\nIn general, an placeholder pattern MUST be one of `\u003cname\u003e` and `\u003cname:regex\u003e`, it will be \r\nconverted to `([^/]+)` and `(regex)` respectively.\r\nYou can also change it via replace the `Router::$replacePatterns` and `Router::$replacements`.\r\n\r\n| Pattern                                     | Path                                       | Matched | Params |\r\n|:--------------------------------------------|:-------------------------------------------|:--------|:-----------------------------------------------------------------|\r\n| `/guests/\u003cname\u003e`                            | `/guests/小明`                              | YES     | `['name' =\u003e '小明']`                                              |\r\n| `/guests/\u003cname:\\w+\u003e`                        | `/guests/foo`                              | YES     | `['name' =\u003e 'foo']`                                              |\r\n| `/guests/\u003cname:\\w+\u003e`                        | `/guests/小明`                              | NO      |                                                                  |\r\n| `/orders/\u003corder_id:\\d+\u003e`                    | `/orders/123`                              | YES     | `['order_id' =\u003e '123']`                                          |\r\n| `/orders/\u003corder_id:\\d+\u003e`                    | `/orders/letters`                          | NO      |                                                                  |\r\n| `/posts/\u003cyear:\\d{4}\u003e/\u003cmonth:\\d{2}\u003e/\u003ctitle\u003e` | `/posts/2017/10/hello-world`               | YES     | `['year' =\u003e '2017', 'month' =\u003e '10', title' =\u003e 'hello-world']`   |\r\n| `/posts/\u003cyear:\\d{4}\u003e/\u003cmonth:\\d{2}\u003e/\u003ctitle\u003e` | `/posts/201/10/hello-world`                | NO      |                                                                  |\r\n| `/posts/\u003cyear:\\d{4}\u003e/\u003cmonth:\\d{2}\u003e/\u003ctitle\u003e` | `/posts/2017/9/hello-world`                | NO      |                                                                  |\r\n| `/posts/\u003cyear:\\d{4}\u003e\u003cmonth:\\d{2}\u003e/\u003ctitle\u003e`  | `/posts/201710/hello-world`                | YES     | `['year' =\u003e '2017', 'month' =\u003e '10', title' =\u003e 'hello-world']`   |\r\n\r\n### Settings\r\n\r\nYou can extend Router via `settings`, such as `param's default value` and `middleware` etc, but this topic are out of\r\nscope of this document.\r\n\r\n### Grouping\r\n\r\nGrouping is an powerful feature of Router for separating modules or API's versions.\r\nAnd this library also implements this feature, it allows nested grouping.\r\n\r\n```php\r\nRouter::group($prefix, array $settings = []);\r\n```\r\n\r\n- `prefix` - group prefix, it **MUST NOT** contains slash `/`. \r\n- `settings` - settings for extending, it will inherits parent's settings.\r\n\r\n```php\r\n// grouping\r\n$v1Settings = [\r\n    'version' =\u003e '1',\r\n    'middlewares' =\u003e [\r\n        'AuthMiddleware',\r\n    ],\r\n];\r\n$v1 = $router-\u003egroup('v1', $v1Settings);\r\n$v1-\u003eget('/hello', 'hello');\r\n$route = $router-\u003edispatch(Router::METHOD_GET, '/v1/hello'); // matched\r\n/**\r\n * [\r\n *     'version' =\u003e '1',\r\n *     'middlewares' =\u003e [\r\n *         'DebugMiddleware',\r\n *         'AuthMiddleware',\r\n *     ],\r\n * ];\r\n */\r\n var_dump($route-\u003esettings());\r\n```\r\n\r\n```php\r\n// nested group\r\n$v1Users = $v1-\u003egroup('users');\r\n$v1Users-\u003eget('/', 'users');\r\n$v1Users-\u003eget('/\u003cname\u003e', 'user profile');\r\n$route = $router-\u003edispatch(Router::METHOD_GET, '/v1/users'); // matched\r\n$route = $router-\u003edispatch(Router::METHOD_GET, '/v1/users/bar'); // matched\r\n```\r\n\r\n### RESTful API\r\n\r\nAs the examples shown above, it is obviously easy to design a RESTful API application.\r\n\r\n```php\r\n$router-\u003eget('/products', 'products');\r\n$router-\u003epost('/products', 'create product');\r\n$router-\u003eget('/products/\u003cproduct_id:\\d+\u003e', 'product detail');\r\n$router-\u003eput('/products/\u003cproduct_id:\\d+\u003e', 'update product');\r\n$router-\u003edelete('/products/\u003cproduct_id:\\d+\u003e', 'delete product');\r\n```\r\n\r\n### Detect methods\r\n\r\nIn consideration of `OPTIONS` request, it provides an API for detecting all valid methods of the specify URI path.\r\n\r\n```php\r\nRoute::getAllowMethods($path, $methods = null);\r\n```\r\n\r\n- `path` - request URL path\r\n- `methods` - `Router::$methods` defined some common request methods, but it does not include all request methods,\r\n you can specify the methods if the key method is not one of the `Router::$methods`. \r\n\r\n```\r\n$allowMethods = $router-\u003egetAllowMethods('/merchants'); // ['GET', 'POST']\r\n```\r\n\r\n## FAQ\r\n\r\n### Package Not Found\r\n\r\nPlease add the following repository into `repositories` when `composer` complains about\r\nthat `Could not find package devlibs/routing ...`.\r\n\r\n```json\r\n{\r\n    \"type\": \"git\",\r\n    \"url\": \"https://github.com/devlibs/routing.git\"\r\n}\r\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frazonyang%2Frouting","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frazonyang%2Frouting","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frazonyang%2Frouting/lists"}