Luminova Framework

PHP Luminova: Routing Overview for HTTP and CLI Controllers

Last updated: 2025-08-21 17:45:27

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:

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 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 or STATUS_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 and Error — 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


Implementations

  • HTTP Controllers:
    • Learn how to handle web requests and return responses by following the HTTP Routing guide.
  • CLI Command Controllers:

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:

ParameterTypeDescription
$namestringPlaceholder name (e.g. "slug").
$patternstringRegular expression pattern (e.g [a-z0-9-]+)
$groupint|nullGrouping 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:

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 of App\Modules\FooModule\Controllers\Http.
    This allows the router to capture both Http and Cli namespaces under the registered group.
public addNamespace(string $namespace): self

Parameters:

ParameterTypeDescription
$namespacestringThe namespace to register (e.g., App\Controllers\, App\Modules\FooModule\Controllers\).

Return Value:

self - Returns the instance of the router class.

Throws:

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:

ParameterTypeDescription
$contextsLuminova\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:

Note:
The prefix name must be unique and reflect your URL structure accurately.
Avoid mixing Prefix objects and array definitions in the same call, as it may lead to unintended errors.

See Also:


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:

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.