{"id":14966398,"url":"https://github.com/yiisoft/router","last_synced_at":"2025-05-16T12:01:50.153Z","repository":{"id":37793148,"uuid":"187923555","full_name":"yiisoft/router","owner":"yiisoft","description":"Router is a request matcher and URL generator","archived":false,"fork":false,"pushed_at":"2025-02-25T12:38:03.000Z","size":549,"stargazers_count":59,"open_issues_count":18,"forks_count":25,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-04-27T18:01:45.251Z","etag":null,"topics":["hacktoberfest","router","yii3"],"latest_commit_sha":null,"homepage":"https://www.yiiframework.com/","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/yiisoft.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"open_collective":"yiisoft","github":["yiisoft"]}},"created_at":"2019-05-21T22:38:58.000Z","updated_at":"2025-02-25T12:38:05.000Z","dependencies_parsed_at":"2024-02-22T19:29:58.930Z","dependency_job_id":"50fdc5ab-35bd-4fc1-ade6-39d5d89d8152","html_url":"https://github.com/yiisoft/router","commit_stats":{"total_commits":240,"total_committers":27,"mean_commits":8.88888888888889,"dds":0.5916666666666667,"last_synced_commit":"ff74591e1097026ab3ff4317b4842d24aee47bd4"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yiisoft%2Frouter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yiisoft%2Frouter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yiisoft%2Frouter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yiisoft%2Frouter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yiisoft","download_url":"https://codeload.github.com/yiisoft/router/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252833089,"owners_count":21811110,"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":["hacktoberfest","router","yii3"],"created_at":"2024-09-24T13:36:19.596Z","updated_at":"2025-05-16T12:01:50.134Z","avatar_url":"https://github.com/yiisoft.png","language":"PHP","funding_links":["https://opencollective.com/yiisoft","https://github.com/sponsors/yiisoft"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/yiisoft\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://yiisoft.github.io/docs/images/yii_logo.svg\" height=\"100px\" alt=\"Yii\"\u003e\n    \u003c/a\u003e\n    \u003ch1 align=\"center\"\u003eYii Router\u003c/h1\u003e\n    \u003cbr\u003e\n\u003c/p\u003e\n\n[![Latest Stable Version](https://poser.pugx.org/yiisoft/router/v)](https://packagist.org/packages/yiisoft/router)\n[![Total Downloads](https://poser.pugx.org/yiisoft/router/downloads)](https://packagist.org/packages/yiisoft/router)\n[![Build status](https://github.com/yiisoft/router/actions/workflows/build.yml/badge.svg)](https://github.com/yiisoft/router/actions/workflows/build.yml)\n[![Code coverage](https://codecov.io/gh/yiisoft/router/graph/badge.svg?token=FxndVgUmF0)](https://codecov.io/gh/yiisoft/router)\n[![Mutation testing badge](https://img.shields.io/endpoint?style=flat\u0026url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fyiisoft%2Frouter%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/router/master)\n[![Static analysis](https://github.com/yiisoft/router/actions/workflows/static.yml/badge.svg?branch=master)](https://github.com/yiisoft/router/actions/workflows/static.yml?query=branch%3Amaster)\n[![type-coverage](https://shepherd.dev/github/yiisoft/router/coverage.svg)](https://shepherd.dev/github/yiisoft/router)\n\nThe package provides [PSR-7](https://www.php-fig.org/psr/psr-7/) compatible request routing and\na [PSR-15 middleware](https://www.php-fig.org/psr/psr-15/) ready to be used in an application.\nInstead of implementing routing from ground up, the package provides an interface for configuring routes and could be used\nwith an adapter package. Currently, the only adapter available is [FastRoute](https://github.com/yiisoft/router-fastroute).\n\n## Features\n\n- URL matching and URL generation supporting HTTP methods, hosts, and defaults.\n- Good IDE support for defining routes.\n- Route groups with infinite nesting.\n- Middleware support for both individual routes and groups.\n- Ready to use middleware for route matching.\n- Convenient `CurrentRoute` service that holds information about last matched route.\n- Out of the box CORS middleware support.\n\n## Requirements\n\n- PHP 8.1 or higher.\n\n## Installation\n\nThe package could be installed with [Composer](https://getcomposer.org):\n\n```shell\ncomposer require yiisoft/router\n```\n\nAdditionally, you will need an adapter such as [FastRoute](https://github.com/yiisoft/router-fastroute).\n\n## Defining routes and URL matching\n\nCommon usage of the router looks like the following:\n\n```php\nuse Yiisoft\\Router\\CurrentRoute;\nuse Yiisoft\\Router\\Group;\nuse Yiisoft\\Router\\Route;\nuse Yiisoft\\Router\\RouteCollection;\nuse Yiisoft\\Router\\RouteCollectorInterface;\nuse Yiisoft\\Router\\UrlMatcherInterface;\nuse Yiisoft\\Router\\Fastroute\\UrlMatcher;\nuse Psr\\Http\\Message\\ServerRequestInterface;\nuse Psr\\Http\\Server\\RequestHandlerInterface;\n\n// Define routes\n$routes = [\n    Route::get('/')\n        -\u003eaction(static function (ServerRequestInterface $request, RequestHandlerInterface $next) use ($responseFactory) {\n            $response = $responseFactory-\u003ecreateResponse();\n            $response\n                -\u003egetBody()\n                -\u003ewrite('You are at homepage.');\n            return $response;\n        }),\n    Route::get('/test/{id:\\w+}')\n        -\u003eaction(static function (CurrentRoute $currentRoute, RequestHandlerInterface $next) use ($responseFactory) {\n            $id = $currentRoute-\u003egetArgument('id');\n    \n            $response = $responseFactory-\u003ecreateResponse();\n            $response\n                -\u003egetBody()\n                -\u003ewrite('You are at test with argument ' . $id);\n            return $response;\n        })\n];\n\n// Add routes defined to route collector\n$collector = $container-\u003eget(RouteCollectorInterface::class);\n$collector-\u003eaddRoute(Group::create(null)-\u003eroutes($routes));\n\n// Initialize URL matcher\n/** @var UrlMatcherInterface $urlMatcher */\n$urlMatcher = new UrlMatcher(new RouteCollection($collector));\n\n// Do the match against $request which is PSR-7 ServerRequestInterface. \n$result = $urlMatcher-\u003ematch($request);\n\nif (!$result-\u003eisSuccess()) {\n     // 404\n}\n\n// $result-\u003earguments() contains arguments from the match.\n\n// Run middleware assigned to a route found.\n$response = $result-\u003eprocess($request, $notFoundHandler);\n```\n\n\u003e Note: Despite `UrlGeneratorInterface` and `UrlMatcherInterface` being common for all adapters available, certain\n\u003e features and, especially, pattern syntax may differ. To check usage and configuration details, please refer\n\u003e to specific adapter documentation. All examples in this document are for\n\u003e [FastRoute adapter](https://github.com/yiisoft/router-fastroute).\n\n### Middleware usage\n\nIn order to simplify usage in PSR-middleware based application, there is a ready to use middleware provided:\n\n```php\n$router = $container-\u003eget(Yiisoft\\Router\\UrlMatcherInterface::class);\n$responseFactory = $container-\u003eget(\\Psr\\Http\\Message\\ResponseFactoryInterface::class);\n\n$routerMiddleware = new Yiisoft\\Router\\Middleware\\Router($router, $responseFactory, $container);\n\n// Add middleware to your middleware handler of choice.\n```\n\nIn case of a route match router middleware executes handler middleware attached to the route. If there is no match, next\napplication middleware processes the request.\n\n### Routes\n\nRoute could match for one or more HTTP methods: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`. There are\ncorresponding static methods for creating a route for a certain method. If a route is to handle multiple methods at once,\nit could be created using `methods()`.\n\n```php\nuse Yiisoft\\Router\\Route;\n\nRoute::delete('/post/{id}')\n    -\u003ename('post-delete')\n    -\u003eaction([PostController::class, 'actionDelete']);\n    \nRoute::methods([Method::GET, Method::POST], '/page/add')\n    -\u003ename('page-add')\n    -\u003eaction([PageController::class, 'actionAdd']);\n```\n\nIf you want to generate a URL based on route and its parameters, give it a name with `name()`. Check \"Creating URLs\"\nfor details.\n\n`action()` in the above is a primary middleware definition that is invoked last when matching result `process()`\nmethod is called. How middleware are executed and what middleware formats are accepted is defined by middleware\ndispatcher used. See [readme of yiisoft/middleware-dispatcher](https://github.com/yiisoft/middleware-dispatcher)\nfor middleware examples.  \n\nIf a route should be applied only to a certain host, it could be defined like the following:\n\n```php\nuse Yiisoft\\Router\\Route;\n\nRoute::get('/special')\n    -\u003ename('special')\n    -\u003eaction(SpecialAction::class)\n    -\u003ehost('https://www.yiiframework.com');\n```\n\nDefaults for parameters could be provided via `defaults()` method:\n\n```php\nuse Yiisoft\\Router\\Route;\n\nRoute::get('/api[/v{version}]')\n    -\u003ename('api-index')\n    -\u003eaction(ApiAction::class)\n    -\u003edefaults(['version' =\u003e 1]);\n```\n\nIn the above we specify that if \"version\" is not obtained from URL during matching then it will be `1`.\n\nBesides action, additional middleware to execute before the action itself could be defined:\n\n```php\nuse Yiisoft\\Router\\Route;\n\nRoute::methods([Method::GET, Method::POST], '/page/add')\n    -\u003emiddleware(Authentication::class)\n    -\u003emiddleware(ExtraHeaders::class)\n    -\u003eaction([PostController::class, 'add'])\n    -\u003ename('blog/add');\n```\n\nIt is typically used for a certain actions that could be reused for multiple routes such as authentication.\n\nIf there is a need to either add middleware to be executed first or remove existing middleware from a route,\n`prependMiddleware()` and `disableMiddleware()` could be used.\n\nIf you combine routes from multiple sources and want last route to have priority over existing ones, mark it as \"override\":\n\n```php\nuse Yiisoft\\Router\\Route;\n\nRoute::get('/special')\n    -\u003ename('special')\n    -\u003eaction(SpecialAction::class)\n    -\u003eoverride();\n```\n\n### Route groups\n\nRoutes could be grouped. That is useful for API endpoints and similar cases:\n\n```php\nuse \\Yiisoft\\Router\\Route;\nuse \\Yiisoft\\Router\\Group;\nuse \\Yiisoft\\Router\\RouteCollectorInterface;\n\n// for obtaining router see adapter package of choice readme\n$collector = $container-\u003eget(RouteCollectorInterface::class);\n    \n$collector-\u003eaddRoute(\n    Group::create('/api')\n        -\u003emiddleware(ApiAuthentication::class)\n        -\u003ehost('https://example.com')\n        -\u003eroutes([\n            Route::get('/comments'),\n            Group::create('/posts')-\u003eroutes([\n                Route::get('/list'),\n            ]),\n        ])\n);\n```\n\nA group could have a prefix, such as `/api` in the above. The prefix is applied for each group's route both when\nmatching and when generating URLs.\n\nSimilar to individual routes, a group could have a set of middleware managed using `middleware()`, `prependMiddleware()`,\nand `disableMiddleware()`. These middleware are executed prior to matched route's own middleware and action.\n\nIf host is specified, all routes in the group would match only if the host match.\n\n### Automatic OPTIONS response and CORS\n\nBy default, router responds automatically to OPTIONS requests based on the routes defined:\n\n```\nHTTP/1.1 204 No Content\nAllow: GET, HEAD\n```\n\nGenerally that is fine unless you need [CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). In this\ncase, you can add a middleware for handling it such as [tuupola/cors-middleware](https://github.com/tuupola/cors-middleware):\n\n```php\nuse Yiisoft\\Router\\Group;\nuse \\Tuupola\\Middleware\\CorsMiddleware;\n\nreturn [\n    Group::create('/api')\n        -\u003ewithCors(CorsMiddleware::class)\n        -\u003eroutes([\n          // ...\n        ]\n    );\n];\n```\n\n## Creating URLs\n\nURLs could be created using `UrlGeneratorInterface::generate()`. Let's assume a route is defined like the following:\n\n```php\nuse Psr\\Http\\Message\\ServerRequestInterface;\nuse Psr\\Http\\Server\\RequestHandlerInterface;\nuse Psr\\Http\\Message\\ResponseFactoryInterface;\nuse Yiisoft\\Yii\\Http\\Handler\\NotFoundHandler;\nuse Yiisoft\\Yii\\Runner\\Http\\SapiEmitter;\nuse Yiisoft\\Yii\\Runner\\Http\\ServerRequestFactory;\nuse Yiisoft\\Router\\CurrentRoute;\nuse Yiisoft\\Router\\Route;\nuse Yiisoft\\Router\\RouteCollection;\nuse Yiisoft\\Router\\RouteCollectorInterface;\nuse Yiisoft\\Router\\Fastroute\\UrlMatcher;\n\n\n$request = $container\n    -\u003eget(ServerRequestFactory::class)\n    -\u003ecreateFromGlobals();\n$responseFactory = $container-\u003eget(ResponseFactoryInterface::class);\n$notFoundHandler = new NotFoundHandler($responseFactory);\n$collector = $container-\u003eget(RouteCollectorInterface::class);\n$collector-\u003eaddRoute(\n    Route::get('/test/{id:\\w+}')\n        -\u003eaction(static function (CurrentRoute $currentRoute, RequestHandlerInterface $next) use ($responseFactory) {\n            $id = $currentRoute-\u003egetArgument('id');\n            $response = $responseFactory-\u003ecreateResponse();\n            $response\n                -\u003egetBody()\n                -\u003ewrite('You are at test with argument ' . $id);\n\n           return $response;\n        })\n        -\u003ename('test')\n);\n$router = new UrlMatcher(new RouteCollection($collector));\n$route = $router-\u003ematch($request);\n$response = $route-\u003eprocess($request, $notFoundHandler);\n$emitter = new SapiEmitter();\n$emitter-\u003eemit($response, $request-\u003egetMethod() === Method::HEAD);\n```\n\nThen that is how URL could be obtained for it:\n\n```php\nuse Yiisoft\\Router\\UrlGeneratorInterface;\n\nfunction getUrl(UrlGeneratorInterface $urlGenerator, $parameters = [])\n{\n    return $urlGenerator-\u003egenerate('test', $parameters);\n}\n```\n\nAbsolute URL cold be generated using `UrlGeneratorInterface::generateAbsolute()`:\n\n```php\nuse Yiisoft\\Router\\UrlGeneratorInterface;\n\nfunction getUrl(UrlGeneratorInterface $urlGenerator, $parameters = [])\n{\n    return $urlGenerator-\u003egenerateAbsolute('test', $parameters);\n}\n```\n\nAlso, there is a handy `UrlGeneratorInterface::generateFromCurrent()` method. It allows generating a URL that is\na modified version of the current URL:\n\n```php\nuse Yiisoft\\Router\\UrlGeneratorInterface;\n\nfunction getUrl(UrlGeneratorInterface $urlGenerator, $id)\n{\n    return $urlGenerator-\u003egenerateFromCurrent(['id' =\u003e 42]);\n}\n```\n\nIn the above, ID will be replaced with 42 and the rest of the parameters will stay the same. That is useful for\nmodifying URLs for filtering and/or sorting.\n\n## Obtaining current route information\n\nFor such a route:\n\n```php\nuse \\Yiisoft\\Router\\Route;\n\n$routes = [\n    Route::post('/post/{id:\\d+}')\n        -\u003eaction([PostController::class, 'actionEdit']),\n];\n```\n\nThe information could be obtained as follows:\n\n```php\nuse Psr\\Http\\Message\\ResponseInterface\nuse Psr\\Http\\Message\\UriInterface;\nuse Yiisoft\\Router\\CurrentRoute;\nuse Yiisoft\\Router\\Route;\n\nfinal class PostController\n{   \n    public function actionEdit(CurrentRoute $currentRoute): ResponseInterface\n    {\n        $postId = $currentRoute-\u003egetArgument('id');\n        if ($postId === null) {\n            throw new \\InvalidArgumentException('Post ID is not specified.');\n        }\n        \n        // ...\n    \n    }\n}\n```\n\nIn addition to commonly used `getArgument()` method, the following methods are available:\n\n- `getArguments()` - To obtain all arguments at once.\n- `getName()` - To get route name.\n- `getHost()` - To get route host.\n- `getPattern()` - To get route pattern.\n- `getMethods()` - To get route methods.\n- `getUri()` - To get current URI.\n\n## Documentation\n\n- [Internals](docs/internals.md)\n\nIf you need help or have a question, the [Yii Forum](https://forum.yiiframework.com/c/yii-3-0/63) is a good place for that.\nYou may also check out other [Yii Community Resources](https://www.yiiframework.com/community).\n\n## License\n\nThe Yii Router is free software. It is released under the terms of the BSD License.\nPlease see [`LICENSE`](./LICENSE.md) for more information.\n\nMaintained by [Yii Software](https://www.yiiframework.com/).\n\n## Support the project\n\n[![Open Collective](https://img.shields.io/badge/Open%20Collective-sponsor-7eadf1?logo=open%20collective\u0026logoColor=7eadf1\u0026labelColor=555555)](https://opencollective.com/yiisoft)\n\n## Follow updates\n\n[![Official website](https://img.shields.io/badge/Powered_by-Yii_Framework-green.svg?style=flat)](https://www.yiiframework.com/)\n[![Twitter](https://img.shields.io/badge/twitter-follow-1DA1F2?logo=twitter\u0026logoColor=1DA1F2\u0026labelColor=555555?style=flat)](https://twitter.com/yiiframework)\n[![Telegram](https://img.shields.io/badge/telegram-join-1DA1F2?style=flat\u0026logo=telegram)](https://t.me/yii3en)\n[![Facebook](https://img.shields.io/badge/facebook-join-1DA1F2?style=flat\u0026logo=facebook\u0026logoColor=ffffff)](https://www.facebook.com/groups/yiitalk)\n[![Slack](https://img.shields.io/badge/slack-join-1DA1F2?style=flat\u0026logo=slack)](https://yiiframework.com/go/slack)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyiisoft%2Frouter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyiisoft%2Frouter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyiisoft%2Frouter/lists"}