PHP Luminova: Routing Overview for HTTP and CLI Controllers
The Luminova routing system helps your app handle web and CLI requests by linking each URL or command to the right controller and method.
The Routing System is a core part of Luminova. It connects incoming requests to the correct controller methods and supports static cache delivery as well as request-level middleware, making it easy to run checks (like authentication) before a request is handled.
It works with both:
- HTTP controllers Luminova Base Controller
- CLI command controllers Luminova Base Command
The router only loads the relevant controller or route context based on the request URI prefix or command group, then dispatches to the correct method. Middleware is applied automatically when required.
URI Prefixing
URI prefixes help the framework load only the routes that matter for a specific request — instead of scanning every route — which makes routing faster and more efficient.
You can configure prefixes in two ways:
Method-Based Request URI Prefix:Group routes under a shared prefix and store them in a dedicated file:
routes/<URI-Prefix>.php
Attribute-Based Request URI Prefix:Use the Prefix attribute to define allowed prefixes directly on a controller class.
Method Return Types
The Luminova routing system supports two types of return values for controller methods: Integer status codes and Response objects.
1. Integer Type
This is the simplest pattern, especially when:
- Using the Template View Class to render templates which required
int
return type. - Writing CLI (command-line) controllers.
The routing system uses special constants to indicate whether a controller method or middleware passed, failed, or handled its own output.
For HTTP Controllers
STATUS_SUCCESS
- In a regular method: The request was handled successfully.
- In a middleware: Authentication or checks passed — routing continues.
STATUS_ERROR
- In a regular method: Something failed — routing triggers an error response.
- In a middleware: Authentication failed — routing stops immediately.
STATUS_SILENCE
- In a regular method: The request was handled internally (e.g., custom error page shown).
- In a middleware: Treated as failed authentication — routing stops. (Use
STATUS_SUCCESS
orSTATUS_ERROR
instead for middleware.)
For CLI Controllers
Routable methods in CLI controllers can return an integer exit code:
STATUS_SUCCESS
- In a regular method: The command was recognized and executed.
- In a middleware: Authentication passed — command continues.
STATUS_ERROR
- In a regular method: The command was invalid or failed.
- In a middleware: Authentication failed — command stops.
2. Response Object Type
The routing system also supports returning a Luminova\Template\Response
object or any class implementing Luminova\Interface\ViewResponseInterface
.
This is useful when:
- You need full control over output (HTML, JSON, files).
- You’re working with JavaScript frameworks like React, Vue, Next.js, or Nuxt.
Example:
use Luminova\Template\Response;
public function myMethod(): Response
{
return new Response(200, '<h1>Hello World!</h1>');
}
Configurations
The Luminova routing system comes with several optional features. You can turn them on or off in your Environment Configuration (.env
) file depending on your needs.
Dependency Injection
You can use dependency injection in your routable controller methods.If you type-hint a class in your method parameters, Luminova will automatically provide an instance of that class when the method is called.
By default, this feature is off. To enable it, add this to your env:
feature.route.dependency.injection = enable
To manage dependency injections and dynamic arguments DI System documentation.
PHP Attribute Routing
Luminova supports Route
, Prefix
, Error
, and Group
attributes that let you define routes directly inside your HTTP or CLI controllers.This approach is cleaner and easier to maintain than defining routes manually.
Route
— define individual method routes.Prefix
andError
— apply to entire HTTP controller classes.Group
— apply to CLI command classes.
For examples and full usage details, see the Route Attribute documentation.
Caching Attributes
For better performance in production, you can cache route attributes so they aren’t parsed on every request:
feature.route.cache.attributes = enable
Note:When caching is enabled, new or modified routes won’t take effect until you clear the cache.To apply changes, manually delete cached files from:
/writeable/caches/routes/*
Disabling Attribute Routing
Attribute routing is enabled by default.If you prefer to define routes manually, you can turn it off:
feature.route.attributes = disable
Dynamic Segment Capturing
URI Segment capturing allows you to extract parts of the request URI and pass them as arguments to your controller methods for further processing.
There are several ways to define capture patterns:
Regular Expressions
Example:/foo/([a-zA-Z0-9]+)/([0-9]+)
Named Placeholders
Example:/foo/{title}/{id}
Predefined Pattern Placeholders
Example:/foo/(:string)/(:int)
While regular expressions provide maximum flexibility, named and predefine placeholders offer a more convenient and readable approach, making them especially ideal for beginners and maintaining cleaner route definitions.
Register Custom Placeholder:
Router::pattern('slug', '[a-z0-9-]+');
For more information see Dynamic URI Placeholder Pattern documentation.
Controller Class Handlers
When defining route handlers, you can use either a Closure or a string reference pointing to a controller method. Luminova supports:
- Static-style references (
ControllerName::method
) - Notation-style references (
ControllerName@method
)
You don’t need to type the full namespace (e.g, App\Controllers\Http\WebController
or App\Controllers\Cli\CommandController
), just the controller’s base name and method.The routing system automatically resolves the full namespace from the registered controller list.
Class Definition
- Class namespace:
\Luminova\Routing\Router
- This class implements: Luminova\Interface\RouterInterface
- This class is marked as final and can't be subclassed
Implementations
- HTTP Controllers:
- Learn how to handle web requests and return responses by following the HTTP Routing guide.
- CLI Command Controllers:
- Learn how to build and route console commands by following the CLI Routing guide.
Methods
pattern
Register a custom route placeholder with an optional grouping mode.
Allows you to replace placeholders like (:slug)
with your own regex. You may choose whether the pattern should be raw, non-capturing, or capturing.
This method makes your routing clean, by providing alias to a long pattern or repeatable patterns.
public static pattern(string $name, string $pattern, ?int $group = null): void
Parameters:
Parameter | Type | Description |
---|---|---|
$name | string | Placeholder name (e.g. "slug"). |
$pattern | string | Regular expression pattern (e.g [a-z0-9-]+ ) |
$group | int|null | Grouping mode: - null: use pattern as-is. - 0: wrap as non-capturing group (?:pattern) .- 1: wrap as capturing group (pattern) .If the pattern already starts with ( , no extra wrapping is applied. |
Throws:
- Luminova\Exceptions\RouterException - If empty placeholder name was provided or
root
is used as placeholder name.
Examples:
Router::pattern('slug', '[a-z0-9-]+'); // raw pattern
Router::pattern('slug', '[a-z0-9-]+', 0); // non-capturing (?:[a-z0-9-]+)
Router::pattern('slug', '[a-z0-9-]+', 1); // capturing ([a-z0-9-]+)
Router::pattern('custom', '([a-z]+)-(\d+)', 1); // stays unchanged
Usages:
// /routes/
#[Luminova\Attributes\Route('/blog/(:slug)', methods: ['GET'])]
public function blog(string $slug): int
{
//
}
// /routes/
$router->get('/blog/(:slug)', 'BlogController::view');
addNamespace
Registers an MVC
or HMVC
controller namespace group for application routing.
This method allows the registration of new routable namespaces, making controllers within those namespaces accessible for routing in both HMVC and MVC applications.
Namespace Pattern:
Register your namespace up to the controller path, excluding the Http
and Cli
suffixes.
- HMVC Example: Use
App\Modules\FooModule\Controllers\
instead ofApp\Modules\FooModule\Controllers\Http
.
This allows the router to capture bothHttp
andCli
namespaces under the registered group.
public addNamespace(string $namespace): self
Parameters:
Parameter | Type | Description |
---|---|---|
$namespace | string | The namespace to register (e.g., App\Controllers\ , App\Modules\FooModule\Controllers\ ). |
Return Value:
self
- Returns the instance of the router class.
Throws:
- Luminova\Exceptions\RouterException - If the namespace is empty or invalid.
Example:
Registering namespaces for module controllers:
This setup is typically implemented in your application class, either within the constructor
or the onCreate
method.
// /app/Application.php
namespace App;
use Luminova\Foundation\CoreApplication;
class Application extends CoreApplication
{
protected function onCreate(): void
{
// Register HMVC module namespaces
$this->router->addNamespace('\\App\\Modules\\Admins\\Controllers\\');
$this->router->addNamespace('\\App\\Modules\\Users\\Controllers\\');
}
}
Note: For MVC and HMVC applications, base controllers are already defined in the Luminova\Foundation\CoreApplication
class. Use addNamespace
only to extend routing for additional modules or custom namespaces.
context
Registers the application routing context based on URI prefixes (e.g., web
, cli
, api
, console
) or custom prefix names.
The context
method is an essential part of Luminova’s routing optimization strategy. It initializes and loads routes based on a given URI prefix, allowing the framework to load only the relevant route files (like routes/web.php
, routes/api.php
, or routes/cli.php
) at runtime. This method improves performance by avoiding loading all routes at once.
If no specific prefix is matched, the default web
context handles the request.
The context
method also supports defining custom error handlers for each prefix, similar to using attribute-based routing. It accepts a flexible input: either a Luminova\Routing\Prefix
object or an array describing the prefix and error handler. If you're using PHP attributes to define routes, simply leave it blank.
Tip: Using an array for context definition is particularly useful in large applications with many route groups. It helps improve maintainability and scalability.
public context(Luminova\Routing\Prefix|array<string,mixed> ...$contexts): self
Parameters:
Parameter | Type | Description |
---|---|---|
$contexts | Luminova\Routing\Prefix|array<string,mixed> | Optional arguments containing routes prefix object, an array of prefix or leave blank when using attribute routing. |
Return Value
self
- Return router instance class.
Throws:
- Luminova\Exceptions\RouterException - Thrown if no context arguments are passed and route attributes are not enabled.
Note:
The prefix name must be unique and reflect your URL structure accurately.
Avoid mixingPrefix
objects and array definitions in the same call, as it may lead to unintended errors.
See Also:
- Method-Based Routing URI Prefixing — How prefixes work and how to configure them.
- Front Controller Setup — Example of setting up the main application handler.
run
Execute application routes and handle incoming requests.
This method processes all defined routes and dispatches incoming HTTP or CLI requests to the appropriatecontroller methods. It also finalize application profiling, ensuring computed profiling data is sent to the UI for debugging and triggers the onFinish
application event before termination.
public run(): void
Throws:
- Luminova\Exceptions\RouterException – If an error occurs during request processing or route resolution.
Example:
// /public/index.php
declare(strict_types=1);
use Luminova\Boot;
require_once __DIR__ . '/../system/Boot.php';
// Set the correct working directory if launched via CLI
if (getcwd() . DIRECTORY_SEPARATOR !== DOCUMENT_ROOT) {
chdir(DOCUMENT_ROOT);
}
// Initialize context and run the router
Boot::http()->router->context(...)->run();
Note: This method is typically invoked once in the (
/public/index.php
) file, which serves as the application front controller.