A minimalistic HTTP router for proof-of-concept projects and decoupled controllers.
composer require gacela-project/routerPut this in index.php:
<?php
require __DIR__ . '/vendor/autoload.php';
use Gacela\Router\Configure\Routes;
use Gacela\Router\Router;
$router = new Router(static function (Routes $routes): void {
$routes->get('/', static fn (): string => 'Hello world');
$routes->get('users/{id}', static fn (int $id): string => "User #{$id}");
});
$router->run();Then start PHP's built-in server and open http://localhost:8000/users/7:
php -S localhost:8000 index.phpRequires PHP >=8.3. The only runtime dependency is gacela-project/container.
Routers that come with a framework, such as Symfony or Laravel, bring many features and dependencies that a proof of concept does not need. Gacela Router keeps the minimum: routes, controllers, middleware and error handlers.
- Routes for every HTTP verb, plus
any()andmatch(), with{param}and{optional?}path segments. Routing - Typed parameters. A path value reaches the action as
string,int,float,boolor a backed enum, and a value that does not fit gives a 404. - Controllers as a class (its dependencies are wired for you), an object or a closure. Returning an array sends JSON. Responses
- Route groups with a shared prefix, and named routes that build their own URLs. Named routes and URLs
- Middleware for every route, one route, or a named group. Middleware
- Error handlers chosen by exception class. A known path with the wrong method answers 405 with an
Allowheader, andHEADis served by the matchingGETroute. Error handling - Gacela integration, optional, through
gacela-project/gacela: ^2.4. Use it within Gacela
// Ask only for the configurators you need: Routes, Bindings, Handlers, Middlewares.
// All except Routes are optional, and they can come in any order.
$router = new Router(function (Routes $routes, Bindings $bindings, Handlers $handlers, Middlewares $middlewares) {
// Redirect
$routes->redirect('docs', 'https://gacela-project.com/');
// One HTTP method, or any
$routes->get('custom', CustomController::class, '__invoke');
$routes->post('custom', CustomController::class, 'customAction');
$routes->any('custom', CustomController::class);
// Several HTTP methods
$routes->match(['GET', 'POST'], '/', CustomController::class);
// Give your controllers their dependencies
$routes->get('custom/{number}', CustomControllerWithDependencies::class, 'customAction');
$bindings->bind(SomeDependencyInterface::class, SomeDependencyConcrete::class);
// Answer an exception with a class-string or a callable
$handlers->handle(NotFound404Exception::class, NotFound404ExceptionHandler::class);
// Middleware for every route
$middlewares->add(new GlobalMiddleware());
// Middleware for one route
$routes->get('admin', AdminController::class)->middleware(new AuthMiddleware());
// A named group of middleware, applied to a route
$middlewares->group('web', [
new SessionMiddleware(),
new CsrfMiddleware(),
]);
$routes->get('/', Controller::class)->middleware('web');
});
$router->run();All pages are in docs/:
- Getting started: install, a minimal app, how to run it
- Routing: HTTP methods, controllers, path patterns, parameters, groups
- Responses: strings, arrays,
Stringable,Response,JsonResponse - Named routes and URLs: naming a route and building its URL
- The request: reading input and injecting
Request - Middleware: global, per-route and grouped
- Error handling: mapping exceptions to handlers
- Use it within Gacela: the
RouterGacelaConfigadapter and plugins
composer serveThis serves example/example.php on http://localhost:8081. Each route has a comment with a URL to try.
Bug reports and pull requests are welcome. CONTRIBUTING.md lists the setup, the checks to run, and the commit style.
MIT. See LICENSE.