Routing
All HTTP routes are defined in a single file — routes/web.php. Each route maps one URI pattern to one action class.
Defining routes
<?php
use App\Actions\HomeAction;
use App\Actions\AboutAction;
use System\Routing\Route;
Route::get("/", HomeAction::class)->name("home");
Route::get("/about/{id}/get/{text}", AboutAction::class)->name("about");
Supported verbs
Route::get($uri, $action);
Route::post($uri, $action);
Route::put($uri, $action);
Route::patch($uri, $action);
Route::delete($uri, $action);
Each verb is a static factory over a shared Route::add($method, $uri, $handler) registration.
Rules & behavior
- The
$actionmust be the fully-qualified class name of an action class. - If the class doesn’t exist, an
AppExceptionis thrown at registration time — fail fast. {param}segments are compiled to regex([^/]+)captures; the matched values (URL-decoded) are passed tomain().- Matching is first-match-wins within the same HTTP verb. No match →
NotFoundException. - Duplicate route names throw an
AppException. - Routes are static and global — register them at the top level of
routes/web.php.
Because action classes are validated during registration, a typo in a class name blows up as soon as routes load — not on the first request that happens to hit it.
Route parameters
Placeholders in the URI become an array passed to main($params):
// routes/web.php
Route::get("/about/{id}/get/{text}", AboutAction::class)->name("about");
// app/Actions/AboutAction.php
public function main(array $params) {
$params["id"]; // "45"
$params["text"]; // "hello"
}
The current route’s parameters are also available anywhere via Route::params():
Route::params(); // [ "id" => 45, "text" => "hello" ]
Named routes
Give a route a name, then generate URLs from it instead of hard-coding paths:
Route::get("/about/{id}/get/{text}", AboutAction::class)->name("about");
// Generate a URL
route("about", ["id" => 45, "text" => "hello"]); // "/about/45/get/hello"
Unmatched {placeholders} are left as-is in generated URLs — always pass every param the route declares.
Current route helpers
route(); // "home", "about", ... or null
route_is("home"); // true if the current route is "home"
route_in(["home", "about"]);// true if current route is in the list
url(); // "http://example.com/current/path"
Redirects and status codes
Redirecting between named routes is a common pattern in actions:
return response()->redirect(route("products.index"));
return response()->redirect("/login", 301); // permanent
return response()->back(); // HTTP_REFERER, or "/"
See Actions & Responses for the full response API.
How dispatch works
Route::dispatch()
├─ match REQUEST_METHOD + REQUEST_URI against registered routes
│ (compiled regex, first-match-wins)
└─ Route::executeHandler()
├─ new Action
├─ boot() (optional setup)
├─ middlewares() → MiddlewarePipeline (onion)
└─ main($params) → result is echoed
Route is a final class holding static state (routes, named
routes, current route). That’s a non-issue under standard Apache/PHP-FPM
per-request processes.
Part of the Lunaris documentation · Source on Codeberg · MIT License