Routing
Routing
The router orchestrates HTTP traffic by mapping URIs to controller methods, executing middleware, and normalising responses.
Defining Routes
Routes live in routes/web.php
and use familiar HTTP verb helpers:
use Zero\Lib\Router;
use App\Controllers\HomeController;
Router::get('/', [HomeController::class, 'index']);
Router::post('/profiles', [ProfilesController::class, 'store']);
Route Groups, Prefixes, and Middleware
Group routes with shared attributes:
Router::group(['prefix' => '/dashboard', 'middleware' => AuthMiddleware::class], function () {
Router::get('/', [DashboardController::class, 'index']);
Router::get('/reports', [ReportsController::class, 'index']);
});
prefix
strings are concatenated for nested groups.middleware
can be a single class or an array. Each middleware class must expose ahandle()
method.
Parameter Binding
Path segments wrapped in {}
are captured and passed to the controller in order. The router uses reflection to type-cast route parameters:
Router::get('/users/{id}', [UsersController::class, 'show']);
class UsersController
{
public function show(int $id)
{
return DBML::table('users')->where('id', $id)->first();
}
}
Dependency Injection
Controllers and middleware can type-hint Zero\Lib\Http\Request
. The router detects non-built-in parameter types and injects the shared request instance automatically.
Middleware Short-Circuiting
If a middleware returns a value, the router resolves it into a Response
and stops invoking further middlewares or the controller. This pattern is ideal for authentication checks:
class AuthMiddleware
{
public function handle(Request $request)
{
if (!Session::has('user')) {
return Response::redirect('/login');
}
Request::set('current_user', Session::get('user'));
}
}
Middleware can use request attributes to share expensive work with controllers or subsequent middleware. See Request Attributes for the full API.
You can also pass parameters to middleware when registering routes:
Router::group(['middleware' => [AuthMiddleware::class, [RoleMiddleware::class, 'admin']]], function () {
Router::get('/dashboard', [DashboardController::class, 'index']);
});
In this example RoleMiddleware::handle()
receives the current request followed by 'admin'
. Any additional arguments declared after the request will be resolved from the route definition order.
Group Name Prefixes
Route groups accept a name
attribute that composes a dot-notated prefix for every nested route:
Router::group(['prefix' => '/auth', 'name' => 'auth'], function () {
Router::get('/login', [AuthController::class, 'showLogin'])->name('login.show');
Router::post('/login', [AuthController::class, 'login'])->name('login.attempt');
});
The example above registers the auth.login.show
and auth.login.attempt
route names while still applying the /auth
URI prefix.
Named Routes and URL Generation
Assign a name to any route definition to reference it later:
Router::get('/profile/{user}', [ProfileController::class, 'show'])
->name('profile.show');
- Route names must be unique; reusing a name for a different path or HTTP verb raises an exception during bootstrap.
- Nested group prefixes automatically prepend to route names (see Group Name Prefixes).
Generate URLs via the global route($name, $parameters = [], $absolute = true)
helper or the underlying Router::route()
method:
$url = route('profile.show', ['user' => 42]); // https://example.com/profile/42
Response::redirectRoute('profile.show', ['user' => 42]);
Placeholders are replaced with URL-encoded parameters and removed from the query string. Any remaining array values are appended as standard ?key=value
pairs. Pass false
as the third argument to receive a relative path (/profile/42
).
Error Handling
Unexpected exceptions during route matching or controller execution are logged via the configurable logger and rendered through the central error handler (JSON for API clients, HTML error views otherwise).