PHP Luminova: HTTP Base Controller
The HTTP Base Controller is the starting point for building web and API controllers in Luminova. It helps you handle incoming requests, run your app’s logic, and send responses back to the client.
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 Base Controller, 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$inputload 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 base controller without extra setup.
- Supports both simple MVC and more modular HMVC structures, great for small apps or large projects.
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\ViewGreat 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\ResponseinstanceAny class implementing
Luminova\Interface\ViewResponseInterfaceSTATUS_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.
Examples
In Luminova, creating a controller is simple: extend Luminova\Base\Controller.This gives your controller built-in framework features and ensures your methods follow the correct conventions.
Best Practices:
- Keep your controllers thin by delegating business logic to services or models.
- Use dependency injection where applicable.
- Override
onCreatefor 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.
MVC Controller
A basic MVC controller example:
// /app/Controllers/Http/MainController.php
namespace App\Controllers\Http;
use Luminova\Base\Controller;
use Luminova\Attributes\Route;
use Luminova\Attributes\Prefix;
use App\Errors\Controllers\ErrorController;
#[Prefix(pattern: '/(:root)', onError: [ErrorController::class, 'onWebError'])]
class MainController extends Controller
{
/**
* Called during initialization.
*/
protected function onCreate(): void
{
// Optional: initialize data here
}
/**
* Index page
*/
#[Route('/', methods: ['GET'])]
public function index(): int
{
return $this->view('index');
// Loads /resources/Views/index.php
}
/**
* About page
*/
#[Route('/about', methods: ['GET'])]
public function about(): int
{
return $this->view('about');
// Loads /resources/Views/about.php
}
}HMVC Controllers
HMVC controllers are similar to MVC, but:
- Namespaces differ
- Modules require registration in the application class
- Non-root module controllers must define their module name and controllers namespace
- Each module contains it own template view directory
Root Module Example:
// /app/Modules/Controllers/Http/MainController.php
namespace App\Modules\Controllers\Http;
use Luminova\Base\Controller;
use Luminova\Attributes\Route;
use Luminova\Attributes\Prefix;
use App\Errors\Controllers\ErrorController;
#[Prefix(pattern: '/(:root)', onError: [ErrorController::class, 'onWebError'])]
class MainController extends Controller
{
protected function onCreate(): void
{
// Optional initialization
}
/**
* Index page
*/
#[Route('/', methods: ['GET'])]
public function index(): int
{
return $this->view('index');
// Loads /app/Modules/Views/index.php
}
/**
* About page
*/
#[Route('/about', methods: ['GET'])]
public function about(): int
{
return $this->view('about');
// Loads /app/Modules/Views/about.php
}
}Custom Module Example:
// /app/Modules/Post/Controllers/Http/PostController.php
namespace App\Modules\Post\Controllers\Http;
use Luminova\Base\Controller;
use Luminova\Attributes\Route;
use Luminova\Attributes\Prefix;
use App\Errors\Controllers\ErrorController;
#[Prefix(pattern: '/post/(:root)', onError: [ErrorController::class, 'onWebError'])]
class PostController extends Controller
{
protected function onCreate(): void
{
// Register the module (matches directory name)
$this->app->view->setModule('Post');
// Optional: other initialization
}
/**
* Index list all posts
*/
#[Route('/post', methods: ['GET'])]
public function posts(): int
{
return $this->view('posts');
// Loads /app/Modules/Post/Views/posts.php
}
/**
* About post
*/
#[Route('/post/(:integer)', methods: ['GET'])]
public function about(int $postId): int
{
return $this->view('post');
// Loads /app/Modules/Post/Views/post.php
}
}Register Custom Module Namespace
Register namespace for HMVC Post module controllers:
// /app/Application.php
namespace App;
class Application extends Luminova\Foundation\Core\Application
{
protected function onCreate(): void
{
$this->router->addNamespace('\\App\\Modules\\Post\\Controllers\\');
}
}Template Contents
Example of a simple template file for an index page:
<!-- 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 a View
Render a template by passing its name without the .php extension:
#[Route('/', methods: ['GET'])]
public function mainIndex(): int
{
return $this->view('index', [
'theme' => 'dark'
], 'html', 200);
}Using the application instance:
#[Route('/', methods: ['GET'])]
public function mainIndex(): int
{
return $this->app->view->view('index', 'html')->render([
'theme' => 'dark'
], 200);
}Returning View Content
If you want the rendered content without sending it directly, use respond():
#[Route('/', methods: ['GET'])]
public function mainIndex(): int
{
$content = $this->respond('index', [
'theme' => 'dark'
], 'html', 200);
// You can process or log $content here
return STATUS_SUCCESS;
}Equivalent using the application instance:
#[Route('/', methods: ['GET'])]
public function mainIndex(): int
{
$content = $this->app->view->view('index', 'html')->respond([
'theme' => 'dark'
], 200);
return STATUS_SUCCESS;
}Useful for sending templates as emails or saving output for later.
Response Handling
Returning a Response Object
You can return a Response object directly:
use Luminova\Template\Response;
#[Route('/foo', methods: ['GET'])]
public function foo(): Luminova\Interface\ViewResponseInterface
{
return new Response(200, content: ['data' => 'Hello World!']);
// Alternative using helper:
// return Luminova\Funcs\response()->content(['data' => 'Hello World!']);
}Middleware Example
Return a response from middleware logic:
use Luminova\Template\Response;
#[Route('/(:root)', methods: ['ANY'], middleware: Route::HTTP_BEFORE_MIDDLEWARE)]
public function middleware(): Luminova\Interface\ViewResponseInterface|int
{
// Assuming session is initialized in "App/Application" class
if ($this->app->session->isOnline()) {
return STATUS_SUCCESS;
}
return (new Response(401, content: ['error' => 'Access Denied!']))
->failed();
// Or return status error
// return STATUS_ERROR;
}API Response Example
Customize responses using Luminova\Template\Response:
#[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 helper:
// return Luminova\Funcs\response(200)->json(['foo' => 'Bar']);
}For more on template rendering, see Template Views documentation.
Class Definition
- Class namespace:
Luminova\Base\Controller - 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\LazyObjectInterface> $request = null;For documentation see HTTP Request Class
input
The instance of user-input validation class (lazy).
protected ?Luminova\Security\Validation<Luminova\Interface\LazyObjectInterface> $input = null;For documentation see Input Validation Class
app
The instance of application class (lazy).
protected ?App\Application<Luminova\Interface\LazyObjectInterface> $app = null;For documentation see Core Application Class
view
The instance of template view class (lazy).
public ?Luminova\Template\View<Luminova\Interface\LazyObjectInterface> $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): intParameters:
| 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_SUCCESSif the view is handled successfully,STATUS_SILENCEif 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
viewmethod 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): stringParameters:
| 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
respondmethod 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(): voidonDestroy
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(): voidonMiddlewareFailure
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): voidParameters:
| 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\Controller;
use Luminova\Attributes\Route;
class AccountController extends Controller
{
#[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');
}
}