{"id":13520118,"url":"https://github.com/codeburnerframework/router","last_synced_at":"2026-01-15T03:55:56.197Z","repository":{"id":56954988,"uuid":"36574020","full_name":"codeburnerframework/router","owner":"codeburnerframework","description":"The blazing fast CodeBurner Routing system.","archived":false,"fork":false,"pushed_at":"2016-08-15T02:16:16.000Z","size":201,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-19T07:36:18.189Z","etag":null,"topics":["component","fast","php","router","routing"],"latest_commit_sha":null,"homepage":null,"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/codeburnerframework.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":"2015-05-30T20:15:08.000Z","updated_at":"2025-02-16T04:09:05.000Z","dependencies_parsed_at":"2022-08-21T08:50:13.774Z","dependency_job_id":null,"html_url":"https://github.com/codeburnerframework/router","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/codeburnerframework/router","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeburnerframework%2Frouter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeburnerframework%2Frouter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeburnerframework%2Frouter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeburnerframework%2Frouter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codeburnerframework","download_url":"https://codeload.github.com/codeburnerframework/router/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeburnerframework%2Frouter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28419272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["component","fast","php","router","routing"],"created_at":"2024-08-01T05:02:11.891Z","updated_at":"2026-01-15T03:55:56.180Z","avatar_url":"https://github.com/codeburnerframework.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"# Codeburner Router\n\n[![Latest Stable Version](https://poser.pugx.org/codeburner/router/v/stable)](https://packagist.org/packages/codeburner/router)\n[![Build Status](https://travis-ci.org/codeburnerframework/router.svg?branch=master)](https://travis-ci.org/codeburnerframework/router)\n[![Code Coverage](https://scrutinizer-ci.com/g/codeburnerframework/routing/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/codeburnerframework/routing/?branch=master)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/codeburnerframework/routing/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/codeburnerframework/routing/?branch=master)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)\n\n[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d96c4a67-982b-4e16-a24d-7b490bf11bc7/big.png)](https://insight.sensiolabs.com/projects/d96c4a67-982b-4e16-a24d-7b490bf11bc7)\n\nAn blazing fast PHP router system with amazing features and abstraction.\n\nThank's to [Nikita Popov's](https://github.com/nikic/) for motivate me with [this post](https://nikic.github.io/2014/02/18/Fast-request-Router-using-regular-expressions.html).\n\n## Installation\n\nAdd `codeburner/router` to your `composer.json` file, and update or install composer dependencies.\n\n```json\n{\n    \"require\": {\n        \"codeburner/router\": \"^2.0\"\n    }\n}\n```\n\nor via CLI:\n\n```bash\n$ composer require codeburner/router --save\n```\n\n## Table of Content\n\n- [Introduction](#introduction)\n    - [Performance](#performance)\n    - [Concepts](#concepts)\n    - [Usage](#usage)\n- [Routes](#routes)\n    - [Patterns](#patterns)\n        - [Constraints](#constraints)\n            - [Wildcards](#wildcards)\n        - [Optional Segments](#optional-segments)\n    - [Actions](#actions)\n        - [Strategies](#strategies)\n            - [Enhancers](#enhancers)\n            - [PSR7](#psr7)\n        - [Default Arguments](#default-arguments)\n        - [Container Integration](#container-integration)\n    - [Names](#names)\n    - [Metadata](#metadata)\n- [Collector](#collector)\n    - [Groups](#groups)\n    - [Resources](#resources)\n        - [Restricting Actions](#restricting-actions)\n        - [Prefixing Resources](#prefixing-resources)\n            - [Ignoring Resource Name](#ignoring-resource-name)\n        - [Nested Resources](#nested-resources)\n            - [Nesting Limit](#nesting-limit)\n                - [Shallow Resources](#shallow-resources)\n            - [Adding More Actions](#adding-more-actions)\n        - [Resources Route Names](#resources-route-names)\n        - [Translated Patterns](#translated-patterns)\n    - [Controllers](#controllers)\n        - [Annotated Definition](#annotated-definition)\n        - [Prefixing Controllers](#prefixing-controllers)\n            - [Ignoring Controller Name](#ignoring-controller-name)\n        - [Changing Pattern Join](#changing-pattern-join)\n- [Matcher](#matcher)\n    - [Exceptions](#exceptions)\n        - [Method not Allowed](#method-not-allowed)\n        - [List of Exceptions](#list-of-exceptions)\n    - [Basepath](#basepath)\n\n## Introduction\n\nWelcome to the fastest PHP router system docs! Before starting the usage is recommended understand the main goal and mission of all parts of this package.\n\n### Performance\n\nCodeburner project create packages with performance in focus, the Codeburner Router was compared with [Nikic's fast route](https://github.com/nikic/fastroute) a fast and base package for several route systems, including the [Laravel](http://laravel.com) and [SlimFramework](http://slimframework.com).\n\nThe Tests reveals that Codeburner Router can be in average **70% faster** while give a full abstraction level in handling routes. More details about the benchmark including the comparisons using [blackfire](http://blackfire.io) of [scripts that maps 100 routes with several arguments and execute them](https://gist.github.com/alexrohleder96/bc302708653b68d1b053), can be found [here](https://blackfire.io/profiles/compare/b861281b-b6d4-4015-b25b-fd9399e789ba...914e81ac-0898-4633-81b1-6c9f1bbfab69/graph?settings%5Bdimension%5D=wt\u0026settings%5Bdisplay%5D=landscape\u0026settings%5BtabPane%5D=nodes\u0026selected=\u0026callname=main()).\n\n\n### Concepts\n\nThe router recognize requests and maps to a logic, an action. For example, when the application receive an incoming request for:\n\n```php\n\"GET\" \"/article/17\"\n```\n\nIt asks the router to match it to a action, if the first matching route is:\n\n```php\n$collector-\u003eget(\"/article/{id}\", \"ArticleResource::show\");\n```\n\nThe request is dispatched to the `ArticleResource`'s `show` method with `17` as parameter.\n\n\n## Usage\n\nAfter a successful installation via composer, or a manual including of `Collector.php` and `Matcher.php` you can begin using the package.\n\n```php\ninclude \"vendor/autoload.php\";\n\nuse Codeburner\\Router\\Collector;\nuse Codeburner\\Router\\Matcher;\n\n$collector = new Collector();\n$matcher   = new Matcher($collector);\n\n$collector-\u003eget(\"/\", function () {\n    echo \"Hello World!\";\n});\n\n$route = $matcher-\u003ematch(\"get\", \"/\");\n$route-\u003ecall();\n```\n\nMore examples can be found [here](https://www.github.com/codeburnerframework/router/tree/examples).\n\n\n## Routes\n\nAfter the release of v2.0.0 all routes are objects, and can be handled in groups. All route attributes can be modified at run time, and you can store a route created in the `Codeburner\\Router\\Collector` in a var. Every time you create a route by any `Codeburner\\Router\\Collector` method, a new `Route` object is created and by default a `Group` is returned containing these route.\n\n\n### Patterns\n\nPatterns are representation of request paths, it follows the popular definitions created by [FastRoute](https://github.com/nikic/FastRoute), if you are familiar with [Laravel](laravel.com) or [Slim Framework](slimframework.com) you will not have problems here.\n\nIf you not, all you need to know for now, is that dynamic segments in patterns, or vars or even parameters if you prefer, are defined inside `{` and `}`. All parts of pattern inside this will be captured by the matcher and passed to the action.\n\n\n#### Constraints\n\nRoutes can define dynamic pattern segments, and that can have a constraint of match, in other words you could define that these segment must be an `int` or a `uid`. The constraint definition follows the pattern adopted by most of routers, for example, to enforce the format of slugs the constraint must be something that have letters, numbers and hyphens, not more.\n\n```php\n\"/articles/{article:[a-z0-9-]+}\"\n```\n\n\u003e **NOTE:** As a constraint is essentially a portion of a bigger REGEX there is a restriction of use of capturing groups. For example `{lang:(en|de)}` is not a valid placeholder, because `()` is a capturing group. Instead you can use either `{lang:en|de}` or `{lang:(?:en|de)}`.\n\n\n##### Wildcards\n\nTHe collector came with support to wildcards in place of regexes in constraints, you can define your own wildcards with the `setWildcard(string name, string regex)` collector's method. There are 8 wildcards with more 3 aliases in a total of 11 wildcards, that are listed bellow:\n\n- uid: `uid-[a-zA-Z0-9]`\n- slug: `[a-z0-9-]`\n- string: `\\w`\n- int or integer: `\\d`\n- float or double: `[-+]?\\d*?[.]?\\d`\n- hex: `0[xX][0-9a-fA-F]`\n- octal: `0[1-7][0-7]`\n- bool or boolean: `1|0|true|false|yes|no`\n\n\u003e **NOTE:** All the build-in **wildcards came with no quantifier**, but support [quantifiers](https://msdn.microsoft.com/en-us/library/3206d374.aspx) after they use, it's not a rule.\n\n\n#### Optional Segments\n\nYou can define several patterns at once, with optional segments that can be nested. For optinal segments in your routes use the `[` and `]` statement to embrace the optional part. Optional segments must only be in the end of pattern and close all opened `[` with `]`. For example:\n\n```php\n\"/user/photos[/{id:uid}]\"\n```\n\n\n### Actions\n\nRoutes define what request must execute what action. An action support all the definitions ways of a [callables](http://php.net/manual/language.types.callable.php) of PHP.\n\nAll the parameters defined on the route pattern are accessible to be used on a dynamic action definition. All parameters will be snake-cased, and words separator are identified by a \"-\" character. In the example bellow if we request `/photos/get/30` the `PhotosResource`'s `getLimited` method will be called with `30` as parameter.\n\n```php\n\"/{resource:string+}/get/{count:int+}\" \"{resource}Controller::getLimited\"\n```\n\n\n#### Strategies\n\nA route must be able to execute the action. By default the action is executed by a simple `call_user_func_array` call, but you can define a more specific way to do that individually for each route or group with the `setStrategy` method, so each route can have different behaviors.\n\nTo define a new strategy simply create a class that implements the `Codeburner\\Router\\Strategies\\StrategyInterface` interface and the `call` method that receives the `Codeburner\\Router\\Route` matched as unique parameter. A strategy can receive the `Codeburner\\Router\\Matcher` using the interface `Codeburner\\Router\\Strategy\\MatcherAwareInterface`.\n\n\n##### Enhancers\n\nThe route enhancer strategy act like a bridge between one route and it dispatch strategy. In this \"bridge\" operations are made manipulating the route object to adapt it, it's common to use the [metadata information](#metadata) in this place.\n\nThe real strategy is defined in the route metadata, using the key `strategy`, after the execution of enhancement logic the real strategy will be called.\n\nTo create one enhancer you only need to extends the `Codeburner\\Router\\Strategies\\EnhancerAbstractStrategy`.\n\n\n##### PSR7\n\nCodeburner have support to [psr7 objects](http://www.php-fig.org/psr/psr-7/), there are at this version two strategies that give your actions a `request` and `response` objects and handle generated `response` objects. Both `Codeburner\\Router\\Strategies\\RequestResponseStrategy` and `Codeburner\\Router\\Strategies\\RequestJsonStrategy` receive one `Psr\\Http\\Message\\RequestInterface` and one `Psr\\Http\\Message\\ResponseInterface`, and make the `matcher`'s `call` method return a `Psr\\Http\\Message\\ResponseInterface`.\n\n```php\n$collector-\u003eget(\"/article/{id:int{5}}\", function (RequestInterface $request, ResponseInterface $response, array $args) {\n    return (string) getCommentById($args[\"id\"]);\n})-\u003esetStrategy(new RequestResponseStrategy($request, $response));\n```\n\n```php\n$collector-\u003eget(\"/article/{id:int{5}}\", function (RequestInterface $request, array $args) {\n    return (array) getCommentById($args[\"id\"]);\n})-\u003esetStrategy(new RequestJsonStrategy($request, $response));\n```\n\nInstead of creating strategy objects by yourself, you could use a [container wrapper](#container-integration) on `call` method.\n\n```php\n$route = $collector-\u003eget(\"/{id:int{5}}\", function (RequestInterface $request, ResponseInterface $response, array $args) {\n    return $args[\"id\"];\n});\n\n$route-\u003ecall(function ($class) use ($container) {\n    return $container-\u003eget($class);\n});\n```\n\n\n#### Default Arguments\n\nIf is necessary to define arguments that are not found on the pattern, use the `setDefault(string key, mixed value)` method. These arguments will be merged with the given from the pattern.\n\n```php\n$collector-\u003eget(\"/\", function ($arg) {\n    echo $arg;\n})-\u003esetDefault(\"arg\", \"hello world\");\n```\n\n\n#### Container Integration\n\nIf is necessary to inject dependencies on controllers, resources, or even strategies, you can tell the `call` method on `Route` objects to use a closure that receives the class name and return one instance of these class.\n\n```php\n$route-\u003ecall(function ($class) use ($container) {\n    return $container-\u003eget($class);\n});\n```\n\n\n### Names\n\nAll the routes allow you to apply names to then, this names can be used to find a route in the `Collector` or to generate links with `Path`'s method `to(string name, array args = [])`. E.g.\n\n```php\n// ...\n// The Path class will create several links for us, just give they new object a instance of the collector.\n$path = new Codeburner\\Router\\Path($collector);\n// ...\n// Setting the name of route to blog.article\n$collector-\u003eget(\"/blog/{article:slug+}\", \"blog::show\")-\u003esetName(\"blog.article\");\n// ...\n// this will print an anchor tag with \"/blog/my-first-article\" in href.\necho \"\u003ca href='\", $path-\u003eto(\"blog.article\", [\"article\" =\u003e \"my-first-article\"]), \"'\u003eMy First Article\u003c/a\u003e\";\n```\n\n\u003e **NOTE:** For best practice use the dot for delimiting namespaces in your route names, so you can group and find they names easily. The [resource](#resources-route-names) collector adopt this concept.\n\n\n### Metadata\n\nSometimes you want to delegate more information to a route, for post match filters or action execution strategies. For persist data that will not be passed to action but used in somewhere before the execution use the `setMetadata(string key, mixed value)` method.\n\nFor getting the metadata use the `Codeburner\\Router\\Route`'s `getMetadataArray()` method for getting all of each, and `getMetadata(string key)` to get a specific metadata, you can check if a metadata exists with `hasMetadata(string key)` method.\n\n\n## Collector\n\nThe collector hold all routes and give to the matcher, and more important than that, implements all the abstraction layer of defining routes.\n\n\n### Groups\n\nAll routes returned by the collector are `Codeburner\\Router\\Group` instances, even if it's a single route. With these groups you can use most of the `Codeburner\\Router\\Route` methods but applying the changes to all routes in the group. You can create groups with the `Codeburner\\Router\\Collector`'s `group` method that receive an array of routes or instantiating a new instance of `Codeburner\\Router\\Group` and add all routes with `set` method.\n\n\n### Resources\n\nResource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index, show, make, edit, create, update and destroy actions, a resourceful route declares them in a single line of code.\n\n```php\n$collector-\u003eresource('PhotosResource');\n```\n\nThe collector will create seven new routes for `PhotosResource`, as listed bellow:\n\nMethod   |Path               |Controller::Action         |Used For\n---------|-------------------|---------------------------|---------------------------------------------\nGET      | /photos           | PhotosResource::index     | Display a list of all photos\nGET      | /photos/make      | PhotosResource::make      | Return an HTML form for creating a new photo\nPOST     | /photos           | PhotosResource::create    | Create a new photo\nGET      | /photos/{id}      | PhotosResource::show      | Display a specific photo\nGET      | /photos/{id}/edit | PhotosResource::edit      | Return an HTML form for editing a photo\nPUT      | /photos/{id}      | PhotosResource::update    | Update a specific photo\nDELETE   | /photos/{id}      | PhotosResource::destroy   | Delete a specific photo\n\n\u003e **NOTE:** Because the router uses the HTTP verb and URL to match inbound requests, four URLs map to seven different actions.\n\n\n#### Restricting Actions\n\nThere is two ways to define what of the seven resource routes should be created, with the `only` or `except` as option in `resource(string resource, array options = null)` method, \n\n```php\n// create only the index and show routes.\n$collector-\u003eresource(\"ArticleResource\", [\"only\" =\u003e [\"index\", \"show\"]]);\n\n// create only the index and show routes too, because all the others should not be created.\n$collector-\u003eresource(\"ArticleResource\", [\"except\" =\u003e [\"make\", \"create\", \"destroy\", \"update\", \"edit\"]]);\n```\n\nor with the `only` and `except` methods of `Codeburner\\Router\\Resource` object returned by the `resource(string resource, array options = null)` method.\n\n```php\n// create only the index and show routes.\n$collector-\u003eresource(\"ArticleResource\")-\u003eonly([\"index\", \"show\"]);\n\n// create only the index and show routes too, because all the others should not be created.\n$collector-\u003eresource(\"ArticleResource\")-\u003eexcept[\"make\", \"create\", \"destroy\", \"update\", \"edit\"]);\n```\n\n\n#### Prefixing Resources\n\nBy default all resource patterns receive the resource name as prefix, on previous example the `UserResource` generate a `/user` prefix. To alter this pass an array with `as` option to the `resource(string resource, array option = null)` method, these option will be used as prefix. eg.\n\n```php\n// now the pattern for make action will be /account/make\n$collector-\u003eresource(\"UserResource\", [\"as\" =\u003e \"account\"]);\n```\n\n\n##### Ignoring Resource Name\n\nYou can avoid this by using the `resourceWithoutPrefix(string resource)` instead of `resource(string resource, array option = null)` method, the same way for multiple matching methods `resources(string[] resource)` and `resourcesWithoutPrefix(string[] resources)`.\n\n\n#### Nested Resources\n\nIt's common to have resources that are logically children of other resources. For example one `article` always have one `category`. Nested routes allow you to capture this relationship in your routing. In this case, you could include this route declaration:\n\n```php\n$collector-\u003eresource(\"CategoryResource\")-\u003enest(\n    $collector-\u003eresource(\"ArticleResource\")\n);\n```\n\nIn addition to the routes for `CategoryResource`, this declaration will also route to `ArticleResource` with one category as parameter.\n\nMethod   |Path                                          |Controller::Action          |Used For\n---------|----------------------------------------------|----------------------------|-----------------------------------------------\nGET      | /category/{category_id}/article              | ArticleResource::index     | Display a list of all Article\nGET      | /category/{category_id}/article/make         | ArticleResource::make      | Return an HTML form for creating a new article\nPOST     | /category/{category_id}/article              | ArticleResource::create    | Create a new article\nGET      | /category/{category_id}/article/{id}         | ArticleResource::show      | Display a specific article\nGET      | /category/{category_id}/article/{id}/edit    | ArticleResource::edit      | Return an HTML form for editing a article\nPUT      | /category/{category_id}/article/{id}         | ArticleResource::update    | Update a specific article\nDELETE   | /category/{category_id}/article/{id}         | ArticleResource::destroy   | Delete a specific article\n\n##### Nesting Limit\n\nYou can nest resources within other nested resources if you like. For example:\n\n```php\n$collector-\u003eresource(\"CategoryResource\")-\u003enest(\n    $collector-\u003eresource(\"ArticleResource\")-\u003enest(\n        $collector-\u003eresource(\"CommentResource\")\n    )\n);\n```\nDeeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize paths such as:\n\n```php\n\"/category/1/article/2/comment/3\"\n```\n\n\u003e **TIP:** Resources should never be nested more than 1 level deep.\n\n###### Shallow Resources\n\nOne way to avoid deep nesting (as recommended above) is to generate the collection actions scoped under the parent, so as to get a sense of the hierarchy, but to not nest the member actions. In other words, to only build routes with the minimal amount of information to uniquely identify the resource, like this:\n\n```php\n$collector-\u003eresource(\"ArticleResource\")-\u003enest(\n    $collector-\u003eresource(\"CommentResource\")-\u003eonly([\"index\", \"make\", \"create\"]);\n);\n\n$collector-\u003eresource(\"CommentResource\")-\u003eexcept([\"index\", \"make\", \"create\"]);\n```\n\nThis idea strikes a balance between descriptive routes and deep nesting. There exists shorthand syntax to achieve just that, via the `shallow` method in `Codeburner\\Router\\Resource`:\n\n```php\n$collector-\u003eresource(\"ArticleResource\")-\u003eshallow(\n    $collector-\u003eresource(\"CommentResource\")\n);\n```\n\nThis will generate the exact same routes as the first example.\n\n\u003e **NOTE:** `shallow` method act the same way as `nest` method, so you can always nest these methods, and use one with each other. \n\n##### Adding More Actions\n\nYou are not limited to the seven routes that RESTFul routing creates by default. If you like, you may add additional routes that apply to the `Codeburner\\Router\\Resource`. The example above will create an additional route with `/photos/{id}/preview` pattern in `get` method.\n\n```php\n$collector-\u003eresource(\"PhotosResource\")-\u003emember(\n    $collector-\u003eget(\"/preview\", \"PhotosResource::preview\")\n);\n```\n\n\n#### Resources Route Names\n\nAll the routes in resource receive a [name](#names) that will be composed by the resource name or prefix, a dot and the action name. e.g.\n\n```php\nclass PhotosResource {\n    public function index() {\n    \n    }\n}\n\n$collector-\u003eresource(\"PhotosResource\")-\u003eonly(\"index\");\n$collector-\u003eresource(\"PhotosResource\", [\"as\" =\u003e \"picture\"])-\u003eonly(\"index\");\n\necho $path-\u003eto(\"photos.index\"), \"\u003cbr\u003e\", $path-\u003eto(\"picture.index\");\n```\n\n\n#### Translated Patterns\n\nIf you prefer to translate the patterns generated by the resource, just define an `translate` option that receives an array with one or the two keys, `new` and `edit`.\n\n```php\n$collector-\u003eresource(\"ArticleResource\", [\"as\" =\u003e \"kategorien\", \"translate\" =\u003e [\"new\" =\u003e \"neu\", \"edit\": \"bearbeiten\"]);\n```\n\nOr using the `translate(array translations)` method of `Codeburner\\Router\\Resource`.\n\n```php\n$collector-\u003eresource(\"ArticleResource\", [\"as\" =\u003e \"kategorien\"])-\u003etranslate([\"new\" =\u003e \"neu\", \"edit\": \"bearbeiten\"]);\n``` \n\nThe two examples above translate `ArticleResource` routes to german, changing the prefix to `kategorien` and the `new` and `edit` keywords to `neu` and `bearbeiten` respectively.\n\n\n### Controllers\n\nControllers can be fully mapped by the `Codeburner\\Router\\Collector`, avoiding the manually description of routes to controller actions. To reach this abstraction some definitions must be respected:\n\n- Methods that can be matched **must** begin with the corresponding HTTP method, like `get`, `post`, `put`, `patch` and `delete`.\n- Camelcased method name will be converted to pattern, each word by default will receive `/` by prefix.\n\n```php\nclass UserController\n{\n    public function getName()\n    {\n        // the same as $collector-\u003eget(\"/user/name\", \"UserController::getName\")\n    }\n}\n```\n\n\n#### Annotated Information\n\nAll the [PHPDoc @param](http://www.phpdoc.org/docs/latest/references/phpdoc/tags/param.html) are parsed and the methods arguments receive a [constraint](#constraints). All the [wildcards](#wildcards) are allowed here, and you can set the type of argument as an [constraint](#constraints) too.\n\nA new annotation is available for defining [strategies](#strategies) to specific methods. For this use the `@strategy` annotation.\n\n```php\nclass BlogController\n{\n    /**\n     * @param int $id\n     * @annotation MyActionExcecutorStrategy\n     */\n    public function getPost($id)\n    {\n        // the same as $collector-\u003eget(\"/blog/post/{id:int+}\", \"BlogController::getPost\")\n        //                       -\u003esetStrategy(\"MyActionExecutorStrategy\")\n    }\n}\n```\n\n\n#### Prefixing Controllers\n\nAct the same way of [prefixing resources](#prefixing-resources), passing the option `as` to `controller(string controller, array options = null)` method.\n\n\n##### Ignoring Controller Name\n\nSame way of [ignoring resource name](#ignoring-resource-name), use the `controllerWithoutPrefix(string controller)` method, or the `controllersWithoutPrefix(string[] controllers)` method.\n\n\n#### Changing Pattern Join\n\nIf you wanna change the default pattern joiner `/` by another join like `-`, you only need to define that before the call of `Codeburner\\Router\\Collector`'s `controller` method.\n\nIn the example bellow the pattern constructed by the `getName` method of `UserController` will be `/user-name` instead of `/user/name`.\n\n```php\n$collector-\u003esetControllerActionJoin(\"-\");\n$collector-\u003econtroller(\"UserController\");\n```\n\n\n## Matcher\n\nThe matcher is responsible for determining which route should be executed for a given request information.\n\n\n### Basepath\n\nAn important point of matcher is that it can remove the basepath prefix from the routes patterns, for this the first parameter of the matcher constructor should be a string with the basepath.\n\nSo if you want to declare routes for a blog system living in `https://www.yourdomain.com/blog` create a new matcher that ignore the `/blog`, so all you declarations can skip this segment.\n\n\n### Exceptions\n\nThere are several exceptions for HTTP errors provided by the codeburner router system, but there are special exceptions, that have methods for determining the logic of failure.\n\n\n#### Method not Allowed\nRoute method is wrong `Codeburner\\Router\\Exceptions\\Http\\MethodNotAllowedException`\n\n```php\n$collector-\u003eget(\"/foo\", \"controller::action\");\n\ntry {\n    $matcher-\u003ematch(\"post\", \"/foo\");\n} catch (Codeburner\\Router\\Exceptions\\MethodNotAllowedException $e) {\n    // You can for example, redirect to the correct request.\n    // this if verify if the requested route can serve get requests.\n    if ($e-\u003ecan(\"get\")) {\n        // if so, dispatch into get method.\n        $matcher-\u003ematch(\"get\", $e-\u003erequested_uri);\n    }\n}\n```\n\n#### List of Exceptions\n\n- Codeburner\\Router\\Exceptions\\BadRouteException\n    - Codeburner\\Router\\Exceptions\\MethodNotSupportedException\n- Codeburner\\Router\\Exceptions\\Http\\HttpExceptionAbstract\n    - Codeburner\\Router\\Exceptions\\Http\\BadRequestException\n    - Codeburner\\Router\\Exceptions\\Http\\ConflictException\n    - Codeburner\\Router\\Exceptions\\Http\\ForbiddenException\n    - Codeburner\\Router\\Exceptions\\Http\\GoneException\n    - Codeburner\\Router\\Exceptions\\Http\\LengthRequiredException\n    - Codeburner\\Router\\Exceptions\\Http\\MethodNotAllowedException\n    - Codeburner\\Router\\Exceptions\\Http\\NotAcceptableException\n    - Codeburner\\Router\\Exceptions\\Http\\NotFoundException\n    - Codeburner\\Router\\Exceptions\\Http\\PaymentRequiredException\n    - Codeburner\\Router\\Exceptions\\Http\\PreconditionFailedException\n    - Codeburner\\Router\\Exceptions\\Http\\RequestTimeOutException\n    - Codeburner\\Router\\Exceptions\\Http\\ServiceUnavailableException\n    - Codeburner\\Router\\Exceptions\\Http\\UnauthorizedException\n    - Codeburner\\Router\\Exceptions\\Http\\UnsupportedMediaTypeException\n\n\u003e **NOTE:** The HTTP specification requires that a `405 Method Not Allowed` response include the\n`Allow:` header to detail available methods for the requested resource. For this you can get a\nstring with a processed allowed methods by using the `allowed` method of this exception.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeburnerframework%2Frouter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodeburnerframework%2Frouter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeburnerframework%2Frouter/lists"}