{"id":37279613,"url":"https://github.com/quimcalpe/router","last_synced_at":"2026-04-29T23:12:35.474Z","repository":{"id":32484162,"uuid":"36064476","full_name":"quimcalpe/router","owner":"quimcalpe","description":"Regexp based Router, easy to use with a rich feature set","archived":false,"fork":false,"pushed_at":"2026-04-29T14:48:44.000Z","size":70,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-04-29T16:31:38.006Z","etag":null,"topics":["php","psr-7","router","routing"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quimcalpe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2015-05-22T09:38:28.000Z","updated_at":"2026-04-29T14:48:28.000Z","dependencies_parsed_at":"2022-08-24T20:30:09.517Z","dependency_job_id":null,"html_url":"https://github.com/quimcalpe/router","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/quimcalpe/router","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quimcalpe%2Frouter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quimcalpe%2Frouter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quimcalpe%2Frouter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quimcalpe%2Frouter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quimcalpe","download_url":"https://codeload.github.com/quimcalpe/router/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quimcalpe%2Frouter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32447393,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T22:27:22.272Z","status":"ssl_error","status_checked_at":"2026-04-29T22:10:49.234Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["php","psr-7","router","routing"],"created_at":"2026-01-16T02:11:35.729Z","updated_at":"2026-04-29T23:12:35.469Z","avatar_url":"https://github.com/quimcalpe.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# quimcalpe/router\n\n[![Version](https://img.shields.io/packagist/v/quimcalpe/router.svg?style=flat-square)](https://packagist.org/packages/quimcalpe/router)\n[![License](https://img.shields.io/packagist/l/quimcalpe/router.svg?style=flat-square)](https://packagist.org/packages/quimcalpe/router)\n[![Tests](https://github.com/quimcalpe/router/actions/workflows/tests.yml/badge.svg)](https://github.com/quimcalpe/router/actions/workflows/tests.yml)\n\nRegexp based Router, easy to use and with a rich feature set. It includes various built-in dispatchers, and we also provide an interface to develop fully customized dispatchers for your project.\n\n## Install\n\nVia Composer\n\n``` bash\n$ composer require quimcalpe/router\n```\n\n## Requirements\n\nThe following versions of PHP are supported by this version.\n\n* PHP 8.5\n\n## Basic Usage\n\n```php\n// Require composer autoloader\nrequire __DIR__ . '/vendor/autoload.php';\n\nuse QuimCalpe\\Router\\Router;\nuse QuimCalpe\\Router\\Dispatcher\\SimpleDispatcher;\n\n// Create Router instance\n$router = new Router();\n\n// Define routes, last parameter defining route name is optional\n$router-\u003eaddRoute('GET', '/users', 'Quimi\\Controllers\\UserController', 'user_list');\n$router-\u003eaddRoute('GET', '/users/edit/{id:number}', 'Quimi\\Controllers\\UserController::edit', 'user_edit');\n$router-\u003eaddRoute(['POST', 'DELETE'], '/users/remove/{id:number}', 'Quimi\\Controllers\\UserController::remove', 'user_delete');\n\n// Sugar methods for common verbs are also available (GET, POST, PUT, DELETE...)\n$router-\u003eaddGet('/user/{id}', 'Quimi\\Controllers\\UserController::show', 'user_show');\n\n// You can also create a QuimCalpe\\Router\\Route\\Route value object and add directly to router's `-\u003eadd()`\n$route = new Route('GET', '/', 'Quimi\\Controllers\\HomeController', 'home');\n$router-\u003eadd($route);\n\ntry {\n    // Match routes\n    $route = $router-\u003eparse($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);\n    // Dispatch route\n    $dispatcher = new SimpleDispatcher();\n    $response = $dispatcher-\u003ehandle($route);\n} catch (QuimCalpe\\Router\\Exception\\MethodNotAllowedException $e) {\n\theader('HTTP/1.0 405 Method Not Allowed');\n\t// exception message contains allowed methods\n\theader('Allow: '.$e-\u003egetMessage());\n} catch (QuimCalpe\\Router\\Exception\\RouteNotFoundException $e) {\n\theader('HTTP/1.0 404 Not Found');\n    // not found....\n}\n```\n\n## Constructor optional Route[] parameter\n\nYou can alternatively pass an array of `Route` objects to Router's constructor, and routes will be created;\n\n```php\nuse QuimCalpe\\Router\\Router;\nuse QuimCalpe\\Router\\Route\\Route;\n\n$routes = [\n\tnew Route('GET', '/users', 'Quimi\\Controllers\\UserController', 'user_list'),\n\tnew Route('GET', '/users/edit/{id:number}', 'Quimi\\Controllers\\UserController::edit', 'user_edit'),\n\tnew Route(['POST', 'DELETE'], '/users/remove/{id:number}', 'Quimi\\Controllers\\UserController::remove', 'user_delete'),\n]\n\n$router = new Router($routes);\n```\n\nThis array can be included from another file, enabling config separation in a simple way.\n\n### Route Providers\n\nIf you want to import a bunch of Routes from a specific package/namespace/bundle and you want to keep routes organized, \nyou can use Route providers, define your provider like this:\n\n```php\nnamespace My\\Package;\n\nuse QuimCalpe\\Router\\Route\\Route;\nuse QuimCalpe\\Router\\Route\\RouteProvider;\n\nclass MyPackageRoutes implements RouteProvider\n{\n    public function routes(): array\n    {\n        return [\n            new Route('GET', '/users', 'Quimi\\Controllers\\UserController', 'user_list'),\n            new Route('GET', '/users/edit/{id:number}', 'Quimi\\Controllers\\UserController::edit', 'user_edit'),\n            new Route(['POST', 'DELETE'], '/users/remove/{id:number}', 'Quimi\\Controllers\\UserController::remove', 'user_delete'),\n        ];\n    }\n}\n```\nAnd then initialize the Router with:\n```php\n$router = new Router();\n$router-\u003eaddRouteProvider(new \\My\\Package\\MyPackageRoutes());\n```\n\n### Route Patterns\n\nBasic regexp patterns are supported, some are already included:\n\n- `[^/]+` as default\n- 'word' =\u003e `\\w+`\n- 'number' =\u003e `\\d+`\n- 'slug' =\u003e `[A-Za-z0-9_-]+`\n\nPatterns can be used this way:\n\n```php\n$router-\u003eaddRoute('GET', '/users/edit/{id:number}', 'Controller::action');\n$router-\u003eaddRoute('GET', '/users/{name:word}', 'Controller::action');\n```\n\nYou can define your own patterns:\n\n```php\n$router-\u003eaddPattern(\"phone\", \"[0-9]-[0-9]{3}-[[0-9]{3}-[0-9]{4}\"); // #-###-###-####\n$router-\u003eaddRoute(\"GET\", \"/customer/{phone:phone}\", \"Vendor\\Package\\Controller\");\n$parsedRoute = $router-\u003eparse(\"GET\", \"/customer/1-222-333-4444\");\n```\n\n### Wildcards\n\nWildcards in routes can be used with `WildcardDispatcher`:\n\n```php\n$router-\u003eaddRoute('GET', '/test/{controller}/{action}/{id}', 'Vendor\\Package\\{controller}::{action}');\n$parsedRoute = $router-\u003eparse(\"GET\", \"/test/user/edit\");\n$dispatcher = new WildcardDispatcher;\n$response = $dispatcher-\u003ehandle($parsedRoute); // =\u003e Vendor\\Package\\User::edit($id)\n```\n\n### Request Response\n\nStandard Request - Response workflow with Symfony HttpFoundation components is supported with `RequestResponseDispatcher`:\n\n```php\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse QuimCalpe\\Router\\Router;\nuse QuimCalpe\\Router\\Dispatcher\\RequestResponseDispatcher;\n\n$router = new Router();\n$router-\u003eaddRoute('GET', '/users', 'Quimi\\Controllers\\UserController::index');\n\n$request = Request::createFromGlobals();\n$route = $router-\u003eparse($request-\u003egetMethod(), $request-\u003egetPathInfo());\n\n// You can optionally modify the request object here before dispatching:\n$request-\u003eattributes-\u003eset('foo', 'bar');\n\n$dispatcher = new RequestResponseDispatcher($request);\n$response = $dispatcher-\u003ehandle($route);\n$response-\u003esend();\n```\n\n### PSR-7 HTTP Message\n\nA built-in `PSR7Dispatcher` is available to work with PHP-FIG's PSR-7 HTTP Message standard implementations, an example using [Zend Diactoros](https://github.com/zendframework/zend-diactoros) and a simple [PSR-7 Response Sender](https://github.com/quimcalpe/psr7-response-sender) would look like this:\n\n```php\nuse QuimCalpe\\Router\\Router;\nuse QuimCalpe\\Router\\Route\\Route;\nuse QuimCalpe\\Router\\Dispatcher\\PSR7Dispatcher;\nuse function QuimCalpe\\ResponseSender\\send AS send_response;\nuse Zend\\Diactoros\\ServerRequestFactory;\nuse Zend\\Diactoros\\Response;\n\n$router = new Router();\n$router-\u003eadd(new Route(\"GET\", \"/test\", \"ControllerFoo\"));\n\n$request = ServerRequestFactory::fromGlobals();\n$route = $router-\u003eparse($request-\u003egetMethod(), $request-\u003egetUri()-\u003egetPath());\n\n$dispatcher = new PSR7Dispatcher($request, new Response());\n$response = $dispatcher-\u003ehandle($route);\nsend_response($response);\n```\n\n### Custom Dispatcher\n\nYou can create your custom Dispatcher, implementing `DispatcherInterface`:\n\n```php\ninterface DispatcherInterface\n{\n    public function handle(ParsedRoute $route): mixed;\n}\n```\n\n`QuimCalpe\\Router\\Route\\ParsedRoute` is a small Value Object with `controller()` and `params()` methods already parsed by `Router::parse`.\n\n### Trailing slash\n\nDefault behaviour is to honour distinction between routes with and wothout trailing slashes:\n\n```php\n$router = new Router();\n$router-\u003eaddRoute('GET', '/users', 'Controller');\n$router-\u003eparse('GET', '/users'); // =\u003e OK!\n$router-\u003eparse('GET', '/users/'); // =\u003e NOT FOUND\n```\n\nYou can disable this behaviour with `disableTrailingSlashCheck` method:\n\n```php\n$router = new Router();\n$router-\u003eaddRoute('GET', '/users', 'Controller');\n$router-\u003edisableTrailingSlashCheck();\n$router-\u003eparse('GET', '/users'); // =\u003e OK!\n$router-\u003eparse('GET', '/users/'); // =\u003e OK!\n```\n\n## Testing\n\n``` bash\n$ vendor/bin/phpunit\n```\n\n## License\n\nThe MIT License (MIT). Please see [License File](https://github.com/quimcalpe/router/blob/master/LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquimcalpe%2Frouter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquimcalpe%2Frouter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquimcalpe%2Frouter/lists"}