Overview
The Router class handles HTTP request routing in Lyger. It supports dynamic route parameters, controller-based routing, and automatic dependency injection through the container.
Constructor
Create a new Router instance with dependency injection support.
public function __construct(Container $container)
Container instance for dependency injection
Example
use Lyger\Routing\Router;
use Lyger\Container\Container;
$container = new Container();
$router = new Router($container);
Route Registration
registerRoute
Register a route with a specific HTTP method and handler.
public function registerRoute(string $method, string $path, callable|array $handler): void
HTTP method (GET, POST, PUT, DELETE)
Route path pattern, supports dynamic parameters with {param} syntax
Route handler - can be a closure or controller array [ControllerClass, 'method']
Example
Closure Handler
Controller Handler
Multiple Parameters
use Lyger\Http\Request;
use Lyger\Http\Response;
$router->registerRoute('GET', '/users/{id}', function(Request $request, $id) {
return Response::json([
'user_id' => $id,
'name' => 'John Doe'
]);
});
use App\Controllers\UserController;
$router->registerRoute('GET', '/users/{id}', [UserController::class, 'show']);
// In UserController.php:
class UserController {
public function show(Request $request, $id) {
return Response::json(['id' => $id]);
}
}
$router->registerRoute('GET', '/posts/{postId}/comments/{commentId}',
function(Request $request, $postId, $commentId) {
return Response::json([
'post_id' => $postId,
'comment_id' => $commentId
]);
}
);
loadRoutesFromFile
Load routes from a PHP file using the Route facade.
public function loadRoutesFromFile(string $filePath): void
Example
// In your bootstrap/app setup:
$router->loadRoutesFromFile(__DIR__ . '/routes/web.php');
// In routes/web.php:
use Lyger\Routing\Route;
Route::get('/', function($request) {
return Response::html('<h1>Welcome to Lyger</h1>');
});
Route::get('/api/users', [UserController::class, 'index']);
Route::post('/api/users', [UserController::class, 'store']);
Route::get('/api/users/{id}', [UserController::class, 'show']);
Request Dispatching
dispatch
Match a request to a registered route and execute its handler.
public function dispatch(Request $request): Response
The HTTP request to dispatch
Returns
Response object from the matched handler, or 404 error if no route matches
The router automatically passes the Request object as the first parameter to all handlers, followed by any route parameters.
Example
use Lyger\Http\Request;
$request = Request::capture();
$response = $router->dispatch($request);
$response->send();
Route Facade
The Route class provides a convenient facade for defining routes that can be loaded by the router.
Static Methods
Route::get(string $path, callable|array $handler): void
Register a GET route.use Lyger\Routing\Route;
Route::get('/users', function($request) {
return Response::json(['users' => []]);
});
Route::post(string $path, callable|array $handler): void
Register a POST route.Route::post('/users', function($request) {
$data = $request->all();
return Response::json(['created' => true]);
});
Route::put(string $path, callable|array $handler): void
Register a PUT route.Route::put('/users/{id}', function($request, $id) {
return Response::json(['updated' => $id]);
});
Route::delete(string $path, callable|array $handler): void
Register a DELETE route.Route::delete('/users/{id}', function($request, $id) {
return Response::json(['deleted' => $id]);
});
Route Parameters
Routes support dynamic parameters using curly brace syntax {param}.
Single Parameter
Route::get('/users/{id}', function($request, $id) {
return Response::json(['user_id' => $id]);
});
// Matches: /users/123
// $id = "123"
Multiple Parameters
Route::get('/users/{userId}/posts/{postId}', function($request, $userId, $postId) {
return Response::json([
'user_id' => $userId,
'post_id' => $postId
]);
});
// Matches: /users/42/posts/789
// $userId = "42", $postId = "789"
Controller Integration
Controllers are automatically instantiated with dependency injection when using array handlers.
Example
// routes/api.php
use App\Controllers\PostController;
use Lyger\Routing\Route;
Route::get('/posts', [PostController::class, 'index']);
Route::post('/posts', [PostController::class, 'store']);
Route::get('/posts/{id}', [PostController::class, 'show']);
Route::put('/posts/{id}', [PostController::class, 'update']);
Route::delete('/posts/{id}', [PostController::class, 'destroy']);
// App/Controllers/PostController.php
namespace App\Controllers;
use Lyger\Http\Request;
use Lyger\Http\Response;
class PostController
{
public function index(Request $request): Response
{
$posts = // ... fetch posts
return Response::json(['posts' => $posts]);
}
public function show(Request $request, string $id): Response
{
$post = // ... fetch post by $id
return Response::json(['post' => $post]);
}
public function store(Request $request): Response
{
$data = $request->all();
// ... create post
return Response::json(['created' => true], 201);
}
public function update(Request $request, string $id): Response
{
$data = $request->all();
// ... update post
return Response::json(['updated' => true]);
}
public function destroy(Request $request, string $id): Response
{
// ... delete post
return Response::json(['deleted' => true]);
}
}
The router automatically formats handler return values:
Response Object
Array
String
Route::get('/users', function($request) {
return Response::json(['users' => []]);
});
// Returns as-is
Route::get('/users', function($request) {
return ['users' => []];
});
// Automatically converted to Response::json()
Route::get('/', function($request) {
return '<h1>Welcome</h1>';
});
// Automatically converted to Response::html()
Error Handling
The router handles errors gracefully:
- 404 Not Found: Returned when no route matches the request
- 500 Internal Server Error: Returned when handler execution fails
// No matching route
GET /non-existent
// Returns: Response::error('Not Found', 404)
// Handler throws exception
Route::get('/error', function() {
throw new \Exception('Something went wrong');
});
// Returns: Response::error('Internal Server Error: Something went wrong', 500)
Complete Example
use Lyger\Routing\Router;
use Lyger\Routing\Route;
use Lyger\Container\Container;
use Lyger\Http\Request;
// Create router with container
$container = new Container();
$router = new Router($container);
// Define routes using facade
Route::get('/', function($request) {
return Response::html('<h1>Lyger API</h1>');
});
Route::get('/api/users', function($request) {
return ['users' => ['John', 'Jane', 'Bob']];
});
Route::get('/api/users/{id}', function($request, $id) {
return Response::json(['id' => $id, 'name' => 'User ' . $id]);
});
Route::post('/api/users', function($request) {
$data = $request->all();
return Response::json(['created' => true, 'data' => $data], 201);
});
// Load routes into router
$routes = Route::getRoutes();
foreach ($routes as $route) {
$router->registerRoute($route['method'], $route['path'], $route['handler']);
}
// Dispatch request
$request = Request::capture();
$response = $router->dispatch($request);
$response->send();