PHP Luminova: URI Prefix Attributes for HTTP Controllers
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()
inErrorController
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:
Parameter | Type | Description |
---|---|---|
$pattern | string | The URI prefix or pattern controller handles (e.g., /user/(:root) , /user or /user/?.* ). |
$onError | callable|null | Optional error handler for routing errors. Can be a callable or a (e.g, [class, method] ) array. |
Throws
- Luminova\Exceptions\RouterException - If the provided error handler is not a valid callable.
Note:Only one
Prefix
attribute can be be assigned to a controller.And you can optionally define error handler without needingError
attribute class.