Luminova Framework

PHP Luminova: Unified Route Attribute for HTTP and CLI

Last updated: 2025-04-30 20:05:28

Leverage the power and flexibility of route attribute, in Luminova, making your routing logic cleaner and maintainable.

The Route attribute in Luminova provides a convenient way to define HTTP and CLI routes directly within your controller methods. It is repeatable and can be applied to multiple methods, offering flexible and straightforward routing for both web and CLI applications.

Luminova uses PHPToken to process controller classes and match the appropriate controller to handle a given request.
While this may seem intensive, Luminova offers optional attribute caching in production environments to avoid re-parsing attributes on every request, significantly enhancing performance.

Additionally, Luminova provides a helpful command through NovaKit to generate routes based on attribute definitions.
This is particularly useful for larger projects where you want to compare the performance of using attributes versus the default context-based routing system.

You can run the following command to export and cache attribute-based routes:

php novakit context --export-attr

This command will:

  • Export all attributes into the necessary files.
  • Create contexts to load each route efficiently.
  • Disable the runtime use of PHP attributes for routing.

Getting Started

To start using the PHP attribute for routing in Luminova, follow these steps:

1. Enable Attribute Routing

Update your environment configuration file .env to enable attribute routing by setting the feature.route.attributes variable to enable.

feature.route.attributes = enable

2. Cache Attributes

Enabling caching of route attributes to improve performance by reducing the overhead of parsing annotations on every request. This is especially useful in production environments where routes do not change frequently.

feature.route.cache.attributes = enable

Cache storage directory /writeable/caches/routes/.

3. Configure Route Context Initialization

For optimal performance, set the route context initialization arguments to Blank or Null in public/index.php to avoid loading unnecessary contexts.

Original Configuration

If your public/index.php router context initialization looks like this:

// /public/index.php

Boot::http()->router->context(
   new Prefix(Prefix::WEB, [ErrorController::class, 'onWebError']),
   new Prefix(Prefix::API, [ErrorController::class, 'onApiError']),
   new Prefix(Prefix::CLI)
)->run();

Or you are using array context initialization like this:

// /public/index.php

Boot::http()->router->context(
   [
      'prefix' => 'web',
      'error' => [ErrorController::class, 'onWebError']
   ],
   [
      'prefix' => 'api',
      'error' => [ErrorController::class, 'onApiError']
   ],
   [
      'prefix' => 'cli',
      'error' => null
   ]
)->run();

4. Simplify the Configuration

Change the router context initialization method call to:

// /public/index.php

Boot::http()->router->context()->run();

By following these adjustment, ensures that the router does not load unnecessary contexts, which improves performance.


Class Definition

  • Class namespace: \Luminova\Attributes\Route
  • This class is marked as final and can't be subclassed

Constants

These constants represent middleware authentication types for routes:

NameValueDescriptionUse Case
BEFORE_MIDDLEWAREbeforeMiddleware executed before handling the main controller logic.HTTP authentication or pre-processing.
AFTER_MIDDLEWAREafterMiddleware executed after the main controller logic has been handled.HTTP cleanup, logging, or additional tasks.
GLOBAL_MIDDLEWAREglobalMiddleware applied globally to all commands, regardless of group.Universal CLI security checks.
GUARD_MIDDLEWAREguardMiddleware executed before commands in the same CLI group are executed.CLI group security checks.

Properties

pattern

The pattern property defines the URL or command pattern that the route should match.

Examples:

  • In HTTP Controller: '/users/([0-9]+)' - Matches a URL like https://example.com/users/123.
  • In CLI Controller: 'users/limit/(:int)' - Matches a CLI command like php index.php group-name users limit=50.

methods

The methods property specifies the HTTP methods that the route should respond to. This is particularly useful for RESTful APIs.


error

The error property indicates whether this route is an error handler. Error handler routes are used to catch and handle 404 errors for specified HTTP methods.


group

The group property defines the command group name for CLI routes. Grouping commands helps organize related commands together and the group name service as the base command before other following commands.


middleware

The middleware property specifies middleware to be applied to the route. Middleware can be used to execute code before or after the main route handler.

Examples:

  • Route::BEFORE_MIDDLEWARE - HTTP Middleware will execute before any controller route is handle.
  • Route::AFTER_MIDDLEWARE - HTTP Middleware will execute after the controller is handled.
  • Route::GLOBAL_MIDDLEWARE - CLI Middleware applies globally to all commands.
  • Route::GUARD_MIDDLEWARE - CLI Middleware applies to a specific command group.

Route Construct

Defines a repeatable attribute for registering HTTP and CLI routes.

This attribute maps controller methods to specific URI patterns and HTTP methods (for web) or command patterns (for CLI), with optional middleware and error handling support.

public __construct(
   string $pattern = '/', 
   array $methods = ['GET'], 
   bool $error = false, 
   ?string $group = null, 
   ?string $middleware = null
): mixed

Parameters:

ParameterTypeDescription
$patternstringThe route pattern for HTTP (e.g. /, /blog/([0-9-.]+))
or CLI command pattern (e.g. blogs, blogs/limit/(:int)).
$methodsarrayThe HTTP methods this route responds to (default: ['GET']).
Optionally use ['ANY'] to match all HTTP methods for enhanced performance.
$errorboolIndicates if this route-method is an error handler for HTTP routes.
$groupstring|nullThe CLI command group this route belongs to (default: null).
Applicable only to CLI command controllers.
$middlewarestring|nullOptional middleware authentication assignment e.g Route::BEFORE_MIDDLEWARE (default: null).

Throw:


HTTP Examples

The HTTP routes can respond to basic HTTP methods such as GET, POST, PUT, DELETE, OPTIONS, and more.

Setting Up HTTP

In this example, we assume you have a controller class named RequestController.

// /app/Controllers/Http/RequestController.php

namespace App\Controllers\Http;

use Luminova\Base\BaseController;
use Luminova\Attributes\Route;

class RequestController extends BaseController
{
   // Your controller methods
}

Defining Routes with Attributes

Basic HTTP Route

Defines an HTTP route that responds to GET requests at the root URL (/):

#[Route('/', methods: ['GET'])]
public function index(): int
{
   // Your code here
}

Equivalent Router Method

$route->get('/', 'RequestController::index');

HTTP Route with Middleware

Define an HTTP route with middleware that executes before the main route handler.

#[Route('/', methods: ['GET'], middleware: Route::BEFORE_MIDDLEWARE)]
public function middleware(): int
{
   // Your code here
}

Equivalent Router Method

$route->middleware('GET', '/', 'RequestController::middleware');

CLI Examples

CLI behaves differently from HTTP; methods like POST, GET, and other HTTP methods are not supported. To define commands for CLI, you can use the command method from the router class or the Route pattern argument with the group in the attribute definition.

Setting Up CLI

In this example, we assume you have a controller class named CLIController.

// app/Controllers/Cli/CommandController.php

namespace App\Controllers\Cli;

use Luminova\Base\BaseCommand;
use Luminova\Attributes\Route;
use Luminova\Attributes\Group;

#[Group(name: 'bar')]
class CommandController extends BaseCommand
{
   // Your CLI controller methods
}

Defining Routes with Attributes

Basic CLI Route

Define a CLI route for the command foo within the bar group. Command: php index.php bar foo.

#[Route('foo', group: 'bar')]
public function fooMethod(): int
{
   // Your code here
}

Equivalent Router Method

$route->group('bar', static function(Router $router) {
   $router->command('foo', 'CommandController::fooMethod');
});

CLI Route with Middleware

For CLI middleware, it support only Route::GLOBAL_MIDDLEWARE and Route::GUARD_MIDDLEWARE middleware.

Define a CLI route with middleware that executes before the command group handler.

#[Route(group: 'bar', middleware: Route::GUARD_MIDDLEWARE)]
public function middleware(): int
{
   // Your code here
}

Equivalent Router Method

$route->group('bar', static function(Router $router){
   $router->guard('bar', 'CommandController::middleware');
   // Commands
});

Global Command Middleware

Define a global command middleware that executes before any command. The middleware name can be Route::GLOBAL_MIDDLEWARE.

#[Route(group: 'bar', middleware: Route::GLOBAL_MIDDLEWARE)]
public function middleware(): int
{
   // Your code here
}

Equivalent Router Method

$router->guard('global', 'CommandController::middleware');
$route->group('group-name', static function(Router $router){
    // Commands
});

Attribute Commands

PHP attributes made it easy for routing definitions, making them more intuitive and maintainable. However, you might wonder whether using attributes provides better performance compared to traditional routing methods and context configurations in your public/index.php file.

Luminova offers a straightforward command to convert your route definitions from attributes into router-based configurations. This command helps you transition smoothly if you decide to switch from attributes to router-based routing.


Export Command

The export command extracts all route definitions specified with attributes for CLI, WEB, and API contexts. It generates the necessary files and contexts for routing and updates your environment variable feature.route.attributes to disabled. This allows you to switch to a router-based routing system while preserving your attribute-based route definitions.

To compare the performance of attributes versus router methods, you can enable performance profiling by setting the environment variable debug.show.performance.profiling to TRUE. This will display metrics such as Execution Time, Memory Usage, and Files Loaded, helping you to compare and make an informed decision.


Usage

To use the export command, open your command line tool, navigate to your project's root directory (where the novakit file is located), and run:

php novakit context --export-attr

NoteAfter exporting and converting attributes to router methods, you can further customize the generated configuration.You may also split methods based on prefixes and add more context prefixes to public/index.php to further optimize performance.

This flexibility allows you to customize the routing setup to better fit your application's needs.

Clearing Cached Attributes

When attribute caching is enabled, changes made or new attributes added will not take effect because the cache is stored permanently without an expiration time. You can manually navigate to the /writeable/caches/routes/ directory and delete the cached PHP files, or run the following command:

php novakit context --clear-attr

  • Prefix Attribute - HTTP controller class level attribute for URI prefixing.
  • Error Attribute - HTTP controller class level attribute for global URI prefix or controller error handling.
  • Group Attribute - CLI controller class level attribute for command group prefixing.