{"id":16292249,"url":"https://github.com/divineniiquaye/flight-routing","last_synced_at":"2025-03-20T03:30:45.943Z","repository":{"id":43222311,"uuid":"241773968","full_name":"divineniiquaye/flight-routing","owner":"divineniiquaye","description":"Flight routing is a simple, fast PHP router that is easy to get integrated with other routers.","archived":false,"fork":false,"pushed_at":"2023-03-10T18:56:45.000Z","size":1530,"stargazers_count":15,"open_issues_count":3,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-02-28T22:49:48.933Z","etag":null,"topics":["biurad","http-router","middleware","php","psr-15","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":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/divineniiquaye.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"patreon":"biurad","custom":["https://biurad.com/sponsor"]}},"created_at":"2020-02-20T02:22:43.000Z","updated_at":"2023-03-19T17:45:00.000Z","dependencies_parsed_at":"2024-10-27T21:44:24.518Z","dependency_job_id":"b78722f0-c609-453e-a643-ee6166d4442e","html_url":"https://github.com/divineniiquaye/flight-routing","commit_stats":{"total_commits":770,"total_committers":6,"mean_commits":"128.33333333333334","dds":0.0714285714285714,"last_synced_commit":"430fb0274940f0b34fa772063de8a177819bd3ef"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/divineniiquaye%2Fflight-routing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/divineniiquaye%2Fflight-routing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/divineniiquaye%2Fflight-routing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/divineniiquaye%2Fflight-routing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/divineniiquaye","download_url":"https://codeload.github.com/divineniiquaye/flight-routing/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244543726,"owners_count":20469551,"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":["biurad","http-router","middleware","php","psr-15","psr-7","router","routing"],"created_at":"2024-10-10T20:05:10.332Z","updated_at":"2025-03-20T03:30:45.593Z","avatar_url":"https://github.com/divineniiquaye.png","language":"PHP","funding_links":["https://patreon.com/biurad","https://biurad.com/sponsor"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# The PHP HTTP Flight Routing\n\n[![PHP Version](https://img.shields.io/packagist/php-v/divineniiquaye/flight-routing.svg?style=flat-square\u0026colorB=%238892BF)](http://php.net)\n[![Latest Version](https://img.shields.io/packagist/v/divineniiquaye/flight-routing.svg?style=flat-square)](https://packagist.org/packages/divineniiquaye/flight-routing)\n[![Workflow Status](https://img.shields.io/github/workflow/status/divineniiquaye/flight-routing/build?style=flat-square)](https://github.com/divineniiquaye/flight-routing/actions?query=workflow%3Abuild)\n[![Code Maintainability](https://img.shields.io/codeclimate/maintainability/divineniiquaye/flight-routing?style=flat-square)](https://codeclimate.com/github/divineniiquaye/flight-routing)\n[![Coverage Status](https://img.shields.io/codecov/c/github/divineniiquaye/flight-routing?style=flat-square)](https://codecov.io/gh/divineniiquaye/flight-routing)\n[![Psalm Type Coverage](https://img.shields.io/endpoint?style=flat-square\u0026url=https%3A%2F%2Fshepherd.dev%2Fgithub%2Fdivineniiquaye%2Frade-di%2Fcoverage)](https://shepherd.dev/github/divineniiquaye/flight-routing)\n[![Quality Score](https://img.shields.io/scrutinizer/g/divineniiquaye/flight-routing.svg?style=flat-square)](https://scrutinizer-ci.com/g/divineniiquaye/flight-routing)\n\n\u003c/div\u003e\n\n---\n\nFlight routing is yet another high performance HTTP router for [PHP][1]. It is simple, easy to use, scalable and fast. This library depends on [PSR-7][2] for route match and support using [PSR-15][3] for intercepting route before being rendered.\n\nThis library previous versions was inspired by [Sunrise Http Router][4], [Symfony Routing][5], [FastRoute][6] and now completely rewritten for better performance.\n\n## 🏆 Features\n\n- Supports all HTTP request methods (eg. `GET`, `POST` `DELETE`, etc).\n- Regex Expression constraints for parameters.\n- Reversing named routes paths to full URL with strict parameter checking.\n- Route grouping and merging.\n- Supports routes caching for performance.\n- [PSR-15][3] Middleware (classes that intercepts before the route is rendered).\n- Domain and sub-domain routing.\n- Restful Routing.\n- Supports PHP 8 attribute `#[Route]` and doctrine annotation `@Route` routing.\n- Support custom matching strategy using custom route matcher class or compiler class.\n\n## 📦 Installation\n\nThis project requires [PHP][1] 8.0 or higher. The recommended way to install, is via [Composer][7]. Simply run:\n\n```bash\n$ composer require divineniiquaye/flight-routing\n```\n\nI recommend reading [my blog post][8] on setting up Apache, Nginx, IIS server configuration for your [PHP][1] project.\n\n## 📍 Quick Start\n\nThe default compiler accepts the following constraints in route pattern:\n\n- `{name}` - required placeholder.\n- `{name=foo}` - placeholder with default value.\n- `{name:regex}` - placeholder with regex definition.\n- `{name:regex=foo}` - placeholder with regex definition and default value.\n- `[{name}]` - optional placeholder.\n\nA name of a placeholder variable is simply an acceptable PHP function/method parameter name expected to be unique, while the regex definition and default value can be any string (i.e [^/]+).\n\n- `/foo/` - Matches **/foo/** or **/foo**. ending trailing slashes are striped before matching.\n- `/user/{id}` - Matches **/user/bob**, **/user/1234** or **/user/23/**.\n- `/user/{id:[^/]+}` - Same as the previous example.\n- `/user[/{id}]` - Same as the previous example, but also match **/user** or **/user/**.\n- `/user[/{id}]/` - Same as the previous example, ending trailing slashes are striped before matching.\n- `/user/{id:[0-9a-fA-F]{1,8}}` - Only matches if the id parameter consists of 1 to 8 hex digits.\n- `/files/{path:.*}` - Matches any URL starting with **/files/** and captures the rest of the path into the parameter **path**.\n- `/[{lang:[a-z]{2}}[-{sublang}]/]{name}[/page-{page=0}]` - Matches **/cs/hello**, **/en-us/hello**, **/hello**, **/hello/page-12**, or **/ru/hello/page-23**\n\nRoute pattern accepts beginning with a `//domain.com` or `https://domain.com`. Route path also support adding controller (i.e `*\u003ccontroller@handler\u003e`) directly at the end of the route path:\n\n- `*\u003cApp\\Controller\\BlogController@indexAction\u003e` - translates as a callable of BlogController class with method named indexAction.\n- `*\u003cphpinfo\u003e` - translates as a function, if a handler class is defined in route, then it turns to a callable.\n\nHere is an example of how to use the library:\n\n```php\nuse Flight\\Routing\\{Router, RouteCollection};\n\n$router = new Router();\n$router-\u003esetCollection(static function (RouteCollection $routes) {\n    $routes-\u003eadd('/blog/[{slug}]', handler: [BlogController::class, 'indexAction'])-\u003ebind('blog_show');\n    //... You can add more routes here.\n});\n```\n\nIncase you'll prefer declaring your routes outside a closure scope, try this example:\n\n```php\nuse Flight\\Routing\\{Router, RouteCollection};\n\n$routes = new RouteCollection();\n$routes-\u003eget('/blog/{slug}*\u003cindexAction\u003e', handler: BlogController::class)-\u003ebind('blog_show');\n\n$router = Router::withCollection($routes);\n```\n\n\u003e NB: If caching is enabled, using the router's `setCollection()` method has much higher performance than using the `withCollection()` method.\n\nBy default Flight routing does not ship a [PSR-7][2] http library nor a library to send response headers and body to the browser. If you'll like to install this libraries, I recommend installing either [biurad/http-galaxy][9] or [nyholm/psr7][10] and [laminas/laminas-httphandlerrunner][11].\n\n```php\n$request = ... // A PSR-7 server request initialized from global request\n\n// Routing can match routes with incoming request\n$route = $router-\u003ematchRequest($request);\n// Should return an array, if request is made on a a configured route path (i.e /blog/lorem-ipsum)\n\n// Routing can also generate URLs for a given route\n$url = $router-\u003egenerateUri('blog_show', ['slug' =\u003e 'my-blog-post']);\n// $url = '/blog/my-blog-post' if stringified else return a GeneratedUri class object\n```\n\nIn this example below, I'll assume you've installed [nyholm/psr-7][10] and [laminas/laminas-httphandlerrunner][11], So we can use [PSR-15][3] to intercept route before matching and [PSR-17][12] to render route response onto the browser:\n\n```php\nuse Flight\\Routing\\Handlers\\RouteHandler;\nuse Laminas\\HttpHandlerRunner\\Emitter\\SapiStreamEmitter;\n\n$router-\u003epipe(...); # Add PSR-15 middlewares ...\n\n$handlerResolver = ... // You can add your own route handler resolver else default is null\n$responseFactory = ... // Add PSR-17 response factory\n$request = ... // A PSR-7 server request initialized from global request\n\n// Default route handler, a custom request route handler can be used also.\n$handler = new RouteHandler($responseFactory, $handlerResolver);\n\n// Match routes with incoming request and return a response\n$response = $router-\u003eprocess($request, $handler);\n\n// Send response to the browser ...\n(new SapiStreamEmitter())-\u003eemit($response);\n```\n\nTo use [PHP][1] 8 attribute support, I highly recommend installing [biurad/annotations][13] and if for some reason you decide to use [doctrine/annotations][14] I recommend you install [spiral/attributes][15] to use either one or both.\n\nAn example using annotations/attribute is:\n\n```php\nuse Biurad\\Annotations\\AnnotationLoader;\nuse Doctrine\\Common\\Annotations\\AnnotationRegistry;\nuse Flight\\Routing\\Annotation\\Listener;\nuse Spiral\\Attributes\\{AnnotationReader, AttributeReader};\nuse Spiral\\Attributes\\Composite\\MergeReader;\n\n$reader = new AttributeReader();\n\n// If you only want to use PHP 8 attribute support, you can skip this step and set reader to null.\nif (\\class_exists(AnnotationRegistry::class)) $reader = new MergeReader([new AnnotationReader(), $reader]);\n\n$loader = new AnnotationLoader($reader);\n$loader-\u003elistener(new Listener(), 'my_routes');\n$loader-\u003eresource('src/Controller', 'src/Bundle/BundleName/Controller');\n\n$annotation = $loader-\u003eload('my_routes'); // Returns a Flight\\Routing\\RouteCollection class instance\n```\n\nYou can add more listeners to the annotation loader class to have all your annotations/attributes loaded from one place.\nAlso use either the `populate()` route collection method or `group()` to merge annotation's route collection into default route collection, or just simple use the annotation's route collection as your default router route collection.\n\nFinally, use a restful route, refer to this example below, using `Flight\\Routing\\RouteCollection::resource`, method means, route becomes available for all standard request methods `Flight\\Routing\\Router::HTTP_METHODS_STANDARD`:\n\n```php\nnamespace Demo\\Controller;\n\nclass UserController {\n    public function getUser(int $id): string {\n        return \"get {$id}\";\n    }\n\n    public function postUser(int $id): string {\n        return \"post {$id}\";\n    }\n\n    public function deleteUser(int $id): string {\n        return \"delete {$id}\";\n    }\n}\n```\n\nAdd route using `Flight\\Routing\\Handlers\\ResourceHandler`:\n\n```php\nuse Flight\\Routing\\Handlers\\ResourceHandler;\n\n$routes-\u003eadd('/user/{id:\\d+}', ['GET', 'POST'], new ResourceHandler(Demo\\UserController::class, 'user'));\n```\n\nAs of Version 2.0, flight routing is very much stable and can be used in production, Feel free to contribute to the project, report bugs, request features and so on.\n\n\u003e Kindly take note of these before using:\n\u003e * Avoid declaring the same pattern of dynamic route multiple times (eg. `/hello/{name}`), instead use static paths if you choose use same route path with multiple configurations.\n\u003e * Route handlers prefixed with a `\\` (eg. `\\HelloClass` or `['\\HelloClass', 'handle']`) should be avoided if you choose to use a different resolver other the default handler's RouteInvoker class.\n\u003e * If you decide again to use a custom route's handler resolver, I recommend you include the static `resolveRoute` method from the default's route's RouteInvoker class.\n\n## 📓 Documentation\n\nIn-depth documentation on how to use this library, kindly check out the [documentation][16] for this library. It is also recommended to browse through unit tests in the [tests](./tests/) directory.\n\n## 🙌 Sponsors\n\nIf this library made it into your project, or you interested in supporting us, please consider [donating][17] to support future development.\n\n## 👥 Credits \u0026 Acknowledgements\n\n- [Divine Niiquaye Ibok][18] is the author this library.\n- [All Contributors][19] who contributed to this project.\n\n## 📄 License\n\nFlight Routing is completely free and released under the [BSD 3 License](LICENSE).\n\n[1]: https://php.net\n[2]: http://www.php-fig.org/psr/psr-7/\n[3]: http://www.php-fig.org/psr/psr-15/\n[4]: https://github.com/sunrise-php/http-router\n[5]: https://github.com/symfony/routing\n[6]: https://github.com/nikic/FastRoute\n[7]: https://getcomposer.org\n[8]: https://divinenii.com/blog/php-web_server_configuration\n[9]: https://github.com/biurad/php-http-galaxy\n[10]: https://github.com/nyholm/psr7\n[11]: https://github.com/laminas/laminas-httphandlerrunner\n[12]: https://www.php-fig.org/psr/psr-17/\n[13]: https://github.com/biurad/php-annotations\n[14]: https://github.com/doctrine/annotations\n[15]: https://github.com/spiral/attributes\n[16]: https://divinenii.com/courses/php-flight-routing/\n[17]: https://divinenii.com/sponser\n[18]: https://github.com/divineniiquaye\n[19]: https://github.com/divineniiquaye/flight-routing/contributors\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdivineniiquaye%2Fflight-routing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdivineniiquaye%2Fflight-routing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdivineniiquaye%2Fflight-routing/lists"}