PHP Luminova: Abstract Base View Controller for Routable HTTP Controllers
The BaseController is the starting point for building your own HTTP controllers in Luminova. It helps you handle incoming requests, run your app’s logic, and send responses back to the user.
The Base Controller is the foundation for building HTTP controllers in Luminova.It supports both MVC (Model-View-Controller) and HMVC (Hierarchical MVC) structures, serving as the link between your application logic and the routing system. Its primary role is to handle incoming requests and generate the correct response back to the client.
What does the Base Controller do?
- Handles Requests – Receives and processes incoming HTTP requests.
- Executes Application Logic – Works with models, services, and utilities to perform operations.
- Generates Responses – Returns templates using the
view()
method or raw output using theresponse()
helper.
Key Features
When you extend BaseController
, you get built-in features that reduce repetitive code and keep your application consistent. You spend less time on setup and more time writing your app logic.
Faster with Lazy Loading
- Properties like
$app
,$request
, and$validate
load only when you use them, saving memory and improving performance.
- Properties like
Works Seamlessly with Routing
- Automatically links to Luminova’s routing system.
- Makes it easy to handle requests, validate data, and send responses.
Easy to Extend and Organize
- Build your own controllers on top of
BaseController
without extra setup. - Supports both simple MVC and more modular HMVC structures, great for small apps or large projects.
- Build your own controllers on top of
Cleaner Route Definitions with PHP Attributes
Define routes directly in your controller with simple annotations:
Luminova\Attributes\Route
- For URI routing view handling.Luminova\Attributes\Error
- For controller scope error handling.Luminova\Attributes\Prefix
- For controller scope allowed URI prefixing.
Flexible Responses
Easily return different formats using
Luminova\Template\Response
- Great for APIs, web pages, or mixed appsLuminova\Template\View
Great for Templates, Web pages or mixed apps
Routable Methods Return Type
A routable method in a controller can return:
An integer status exit code (e.g.,
STATUS_SUCCESS
,STATUS_ERROR
)A
Luminova\Template\Response
instanceAny class implementing
Luminova\Interface\ViewResponseInterface
STATUS_SUCCESS
(0
)The request was handled correctly, and the response was rendered successfully.- Common after loading a view or completing an action.
- In middleware, this lets the request continue to the next controller or action.
STATUS_ERROR
(1
)The request could not be handled properly.- The routing system responds with a 404 View Not Found error.
- Use this when processing fails, authentication blocks access, or no valid view is found.
STATUS_SILENCE
(2
)The request was processed, but nothing was explicitly returned or displayed.- The router takes no further action.
- Useful for background tasks, APIs with no visible output, or cases where an empty response is expected.
- If nothing is rendered, the user may see a blank page.
Usages
To create a controller in Luminova, simply extend BaseController
.This gives your controller all the built-in features of the framework and ensures your methods follow the correct conventions.
MVC Controller
The following example demonstrates a basic implementation of an MVC controller:
// /app/Controllers/Http/MyController.php
namespace App\Controllers\Http;
use Luminova\Base\BaseController;
use Luminova\Attributes\Route;
use App\Models\User;
class MyController extends BaseController
{
// private ?User $user = null;
/**
* Called during initialization.
*/
protected function onCreate(): void
{
// Add any setup logic here
// $this->user = new User();
}
/**
* Example action: Adds a user to the database.
*
* @return int Status of the operation.
*/
#[Route('/user/add', methods: ['POST'])]
public function addUser(User $user): int
{
$name = escape($this->request->getPost('name'));
$added = $user->insert([
[
'name' => $name,
// Add other fields as needed
]
]);
return $added ? STATUS_SUCCESS : STATUS_SILENCE;
}
}
HMVC Controllers
Root Module:
Here's how to implement a root-level HMVC controller:
// /app/Modules/Controllers/Http/MyController.php
namespace App\Modules\Controllers\Http;
use Luminova\Base\BaseController;
class MyController extends BaseController
{
/**
* Called during initialization.
*/
protected function onCreate(): void
{
// Add any setup logic here
}
}
Custom Module:
Below is an example of a controller specific to an HMVC module:
// /app/Modules/FooModule/Controllers/Http/MyController.php
namespace App\Modules\FooModule\Controllers\Http;
use Luminova\Base\BaseController;
class MyController extends BaseController
{
/**
* Called during initialization.
*/
protected function onCreate(): void
{
// Same as the directory name (app/Modules/FooModule) use `FooModule`
$this->app->setModule('FooModule');
// Add any setup logic here
}
}
Best Practices:
- Keep your controllers thin by delegating business logic to services or models.
- Use dependency injection where applicable.
- Override
onCreate
for setup tasks specific to your controller.- Place your controllers in the appropriate directory based on the architecture (MVC or HMVC).
- Use descriptive module names for better organization.
Template & View Response
Below is an example of using a template view file to handle an index page.
Template File Example:
<!-- File: resources/View/index.php -->
<!DOCTYPE html>
<html lang="en">
<head><title>Index Example</title></head>
<body>
Current Theme: <?= $this->theme; ?>
</body>
</html>
Template Handling
Rendering View
To render a template, simply pass the template file name without the extension as show below:
#[Route('/', methods: ['GET'])]
public function mainIndex(): int
{
return $this->view('index', [
'theme' => 'dark'
], 'html', 200);
}
Equivalent example using the application instance:
#[Route('/', methods: ['GET'])]
public function mainIndex(): int
{
return $this->app->view->view('index', 'html')->render([
'theme' => 'dark'
], 200);
}
Return View Contents
If you need to return the rendered view content instead of sending it directly to the client, you can do the following:
#[Route('/', methods: ['GET'])]
public function mainIndex(): int
{
$content = $this->respond('index', [
'theme' => 'dark'
], 'html', 200);
// Process or log the content here if needed
return STATUS_SUCCESS;
}
Equivalent example using the application instance:
#[Route('/', methods: ['GET'])]
public function mainIndex(): int
{
$content = $this->app->view->view('index', 'html')->respond([
'theme' => 'dark'
], 200);
// Process or log the content here if needed
return STATUS_SUCCESS;
}
This can be useful when you want to send the entire content as an email template.
Response Handling
Response Object
Return a Response object:
#[Route('/foo', methods: ['GET'])]
public function foo(): Luminova\Interface\ViewResponseInterface
{
return new Response(200, content: ['status' => 'OK']);
// Alternative using the global helper function
// return response()->content(['status' => 'OK']);
}
Middleware Response object:
#[Route('/(:root)', methods: ['GET'], middleware: Route::HTTP_BEFORE_MIDDLEWARE)]
public function middleware(): Luminova\Interface\ViewResponseInterface
{
if($this->app->session->isOnline()){
return STATUS_ERROR;
}
return (new Response(200, content: ['status' => 'OK']))
->failed();
}
API Response
You can customize responses by interacting with the Luminova\Template\Response
class:
#[Route('/', methods: ['GET'])]
public function mainIndex(Luminova\Template\Response $response): int
{
$response->setStatus(200);
$response->header('Content-Type', 'application/json');
return $response->json([
'foo' => 'Bar'
]);
// Alternative using the global helper function
// return response(200)->json(['foo' => 'Bar']);
}
Class Definition
- Class namespace:
\Luminova\Base\BaseController
- This class implements: Luminova\Interface\RoutableInterface
- This class is an Abstract class
Properties
request
The instance of HTTP request object (lazy).
protected ?Luminova\Http\Request<Luminova\Interface\LazyInterface> $request = null;
For documentation see HTTP Request Class
validate
The instance of user-input validation class (lazy).
protected ?Luminova\Security\Validation<Luminova\Interface\LazyInterface> $validate = null;
For documentation see Input Validation Class
app
The instance of application class (lazy).
protected ?App\Application<Luminova\Interface\LazyInterface> $app = null;
For documentation see Core Application Class
view
The instance of template view class (lazy).
public ?Luminova\Template\View<Luminova\Interface\LazyInterface> $view = null;
For documentation see Template View Class
Methods
view
Render a template within the controller.
This method will render specified template and send the output to browser or system
protected final view(string $template, array $options = [], string $type = View::HTML, int $status = 200): int
Parameters:
Parameter | Type | Description |
---|---|---|
$template | string | The template file name without the extension (e.g., index ). |
$options | array<string,mixed> | Optional scope data to pass to the template. |
$type | string | The content type (default: View::HTML ). |
$status | int | HTTP status code to response (default: 200 OK).. |
Return Value:
int
- Return one of the following status codes:
STATUS_SUCCESS
if the view is handled successfully,STATUS_SILENCE
if failed, silently terminate without error page allowing you to manually handle the state.
Examples:
Render view within controller method:
$this->view('template-name', [...], View::HTML, 200);
Equivalent to the above example:
$this->app->view->view('template-name', View::HTML)->render([...], 200);
The
view
method serves as a convenient alias or shorthand for rendering views within the controller class.
respond
Render template and return content as a string.
Unlike the view
method, the respond
method will render specified template and return the output instead of directly sending to browser or system.
View Types:
Any of these types are supported view type argument for respond
and view
method.
html
- View will render HTML content.json
- View will render JSON content.text
- View will render Plain text content.
See documentation for more information about Template View Class.
protected final respond(string $template, array $options = [], string $type = View::HTML, int $status = 200): string
Parameters:
Parameter | Type | Description |
---|---|---|
$template | string | The template file name without the extension (e.g., index ). |
$options | array<string,mixed> | Optional scope data to pass to the template. |
$type | string | The content type (default: View::HTML ). |
$status | int | HTTP status code to response (default: 200 OK).. |
Return Value:
string
- Return the rendered template content as string.
Examples:
Process view and return contents:
$content = $this->respond('view-name', [...], View::HTML, 200);
Equivalent to the above example:
$content = $this->app->view->view('view-name', View::HTML)
->respond([...], 200);
The
respond
method is also a convenient alias or shorthand for returning view contents within the controller class.
onCreate
The onCreate
method in the controller serves as an alternative to __construct
. It is invoked after the controller class has completed its initialization via the constructor method. When using this method for initialization, there is no need to explicitly call parent::__construct()
.
protected onCreate(): void
onDestroy
The onDestroy
method in the controller acts as an alternative to __destruct
. It is called after the __destruct
method has completed its execution.
protected onDestroy(): void
onMiddlewareFailure
Handles the failure of the middleware
check in the controller.
Invoked when the middleware
method returns STATUS_ERROR
, this allows you render a custom view or display an error message.
protected onMiddlewareFailure(string $uri, array $metadata): void
Parameters:
Parameter | Type | Description |
---|---|---|
$uri | string | The request URI, useful for logging or triggering an error view. |
$metadata | array<string,mixed> | Information about the class where the middleware check failed. |
Example:
Render View on Middleware Failure
namespace App\Controllers\Http;
use Luminova\Base\BaseController;
use Luminova\Attributes\Route;
class AccountController extends BaseController
{
#[Route('/account/(:root)', methods: ['ANY'], middleware: Route::HTTP_BEFORE_MIDDLEWARE)]
public function middleware(): int
{
return $this->app->session->online() ? STATUS_SUCCESS : STATUS_ERROR;
}
protected function onMiddlewareFailure(string $uri, array $metadata): void
{
$this->view('login');
}
}