Luminova Framework

PHP Luminova: URI Prefix Attributes for HTTP Controllers

Last updated: 2025-08-21 19:52:25

Learn how to use Luminova’s Prefix attribute to group controller routes and assign custom error handlers per prefix. Keep your route logic clean, efficient, and centralized.

The Prefix attribute in Luminova lets you define a URI prefix or pattern directly at the HTTP controller class level.

Like method-based URI prefixing, attribute prefixing can also define an error handler for the given prefix. It’s perfect for grouping related routes inside a single controller, much like using a prefix context file (for example, /routes/web.php).

This prefix isn’t just about keeping things neat — it also improves performance. By narrowing down which controller should handle a request, the routing system resolves routes faster during attribute tokenization. In production, this mapping is done once, then cached for quick lookups.

Important: The Prefix attribute doesn’t automatically apply its base path to every method inside the controller. In other words, if your controller prefix is /api, you still need to include /api on each route method you declare.

The Prefix attribute supports:

  • Static prefixes like /api or /panel
  • Regular expressions for advanced matching
  • Dynamic URI placeholders for maximum flexibility (void named-placeholder (e.g {segment}))

When attribute routing is enabled, Prefix offers a cleaner alternative to method-based routing. You can keep routes organized without repeating yourself in every method call.

Think of it as assigning your controller to a specific “block” in the city. Every method still has its own house number, but they all share the same street.


Examples

The following example demonstrates how to use the Prefix attribute to define a URI pattern or placeholder for handling routes.

Prefixing the Application Entry

In this example, we configure a prefix at the application’s main entry point. The controller will handle all non-custom prefixes (e.g., everything except /api) while allowing you to route /api requests elsewhere.

// /app/Controllers/Http/WebsiteController.php

namespace App\Controllers\Http;

use Luminova\Base\BaseController;
use Luminova\Attributes\Prefix;

#[Prefix(pattern: '/(?!api).*')]
class WebsiteController extends BaseController
{
    // Methods here will handle all website routes, excluding /api
}

Here, the WebsiteController will automatically handle every URI that does not start with /api.This setup keeps your standard web routes separate from API routes — making your routing cleaner, faster, and easier to maintain.


API Prefixing

This example shows how to configure a prefix for all API routes, ensuring they are grouped under a dedicated controller.

// /app/Controllers/Http/ResetController.php

namespace App\Controllers\Http;

use Luminova\Base\BaseController;
use Luminova\Attributes\Prefix;

#[Prefix(pattern: '/api/(:root)')]
class ResetController extends BaseController
{
   // Methods here handle all /api/... routes
}

In this example, the ResetController automatically handles every request URI that begins with /api.This keeps your API endpoints organized and improves routing performance.


Prefix Exclusion

It’s a good idea to update your main entry controller so it ignores any custom prefixes already handled by dedicated controllers.This prevents overlapping routes, improves routing performance, and avoids unexpected matches.

The cleanest way to do this is by using a pattern placeholder helper to manage complex patterns:

// /app/Application.php

namespace App;

use Luminova\Routing\Router;
use Luminova\Foundation\CoreApplication;

class Application extends CoreApplication
{
   protected function onCreate(): void 
   {
      // Define a placeholder pattern for routes that are not API, console, admin, etc.
      Router::pattern('home', '(?!api|console|admin|users|foo).*');
   }
}

Apply Pattern

Now apply your new home pattern to your main application controller:

// /app/Controllers/Http/WebsiteController.php

namespace App\Controllers\Http;

use Luminova\Base\BaseController;
use Luminova\Attributes\Prefix;

#[Prefix(pattern: '/(:home)')]
class WebsiteController extends BaseController
{
    // Methods here handle all website routes except excluded prefixes
}

Result:Your WebsiteController will handle every route except those starting with /api, /console, /admin, /users, or /foo — keeping your controllers cleanly separated.


Here’s your section rewritten with better structure, clearer explanations, and a friendlier tone without losing the professional touch:


Prefix with Global Error Handler

You can also attach a custom error handler directly to a prefix.This is useful when you want all routes under a certain controller to use the same fallback logic if something goes wrong.

// /app/Controllers/Http/AdminController.php

namespace App\Controllers\Http;

use Luminova\Base\BaseController;
use Luminova\Attributes\Prefix;
use App\Errors\Controllers\ErrorController;

#[Prefix(
   pattern: '/panel/(:root)', 
   onError: [ErrorController::class, 'onPanelError']
)]
class AdminController extends BaseController
{
   // Routes handled by this controller will use onRestError() for failures
}

What’s happening here?

  • The prefix /panel/(:root) means this controller is responsible for handling all panel root-level routes.
  • If any route inside this controller fails to resolve, the method onPanelError() in ErrorController will automatically handle it.

Important:

This error handler only applies to routes within this controller’s prefix.It does not affect other controllers or act as a global fallback — you’d still need to define separate error handling elsewhere if required.


Class Definition

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

Attribute Constructor

Defines a non-repeatable routing prefix for HTTP controller classes.

This attribute assigns a URI prefix to a controller and optionally sets an error handler. It helps centralize error management and organize controllers when compiling attributes to routes for performance.

public __construct(string $pattern, string|array|null $onError = null)

Parameters:

ParameterTypeDescription
$patternstringThe URI prefix or pattern controller handles (e.g., /user/(:root), /user or /user/?.*).
$onErrorcallable|nullOptional error handler for routing errors.
Can be a callable or a (e.g, [class, method]) array.

Throws

Note:Only one Prefix attribute can be be assigned to a controller.And you can optionally define error handler without needing Error attribute class.