ft / just-routes
A library simply for routing requests. Simple. Light. Fast
Requires
- ft/attributes: ^2.2
- ft/request-response: ^2.0
Requires (Dev)
- phpunit/phpunit: ^9.5
README
A extremely lightweight, fast and focused PHP library strictly for routing requests. No hassle, no framework required.
Just attributes, plain old PHP, and just routes
Usage
composer require ft/just-routes
- Create controller[s]
- Register controller[s]
- Add optional methods
- Dispatch Request
Create Controllers
final class MyController { }
- Annotate your controller with request mapping
#[RequestMapping(value: "/foobar")] final class MyController { }
- Add routes as methods to controller
#[RequestMapping(value: "/foobar")] final class MyController { #[GetMapping] function voidMethod() { // maps to GET /foobar } #[GetMapping(value: "/bazz")] function get_bazz() { // maps to GET /foobar/bazz echo "bazz"; } }
Register Controllers
RouteFactory::registerController(MyController::class);
Customize
You can customize a few control flow patterns:
- Exceptions
- Not Found Paths
Exceptions
You can catch exceptions at the controller layer or globally via RouteFactory
scoped exception handling via controller annotation
#[RequestMapping(value: "/foobar")] final class MyController { #[GetMapping] function voidMethod() { // maps to GET /foobar throw new IllegalArgumentException("Illegal"); } #[GetMapping(value: "/bazz")] function get_bazz() { // maps to GET /foobar/bazz throw new IllegalArgumentException("Illegal"); } #[ExceptionHandler(IllegalArgumentException::class)] function handle_illegal_arg_exc(IllegalArgumentException $exc, string $path) { //swallowed IllegalArgumentException only from this controller's routes } }
globally catching exceptions
RouteFactory::registerController(MyController::class); RouteFactory::onException(IllegalArgumentException::class, function (string $path) { echo "Caught globally"; });
Not Found
globally handle
RouteFactory::registerController(MyController::class); RouteFactory::onNotFound(function ($path) { echo "$path not found"; });
The End
That's it to get routing configured. Now simply dispatch the request
RouteFactory::registerController(MyController::class); RouteFactory::dispatch();
Miscellaneous
Semantic Attributes
- #[GetMapping]
- #[PutMapping]
- #[PostMapping]
- #[DeleteMapping]
Other Attributes
-
#[RequestMapping]
-
#[ExceptionHandler]
-
#[RequestParam] - Inject a request parameter directly as a method parameter
#[RequestMapping(value: "/foobar")] final class MyController { #[GetMapping("/id/{id}")] public function get_foo(int $id, #[RequestParam] string $internal, #[RequestParam] array $foos) { // Example req: // GET /foobar/id/1?internal=true&foos[]=1&foos[]=2&foos[]=3 } }
-
#[RequestHeader] - Inject a header directly as a method parameter
#[RequestMapping(value: "/foobar")] final class MyController { #[GetMapping("/id/{id}")] public function get_foo(int $id, #[RequestHeader] string $referer) { } }
Route Syntax
Routes are separated by /
, must start with /
and must not duplicate for HTTP method types
Routes may contain path variables. A path variable is encapsulated by {}
curly braces.
Routes with path variables must have parameters in the route method signature
For example:
#[RequestMapping(value: "/foobar")] final class MyController { #[GetMapping(value: "/name/{name}/age/{age}")] function get_for_name_age(string $name, int $age) { // example req // GET /foobar/name/John/age/18 } }