Luminova Framework

PHP Luminova: Abstract Base View Controller for Routable HTTP Controllers

Last updated: 2025-08-20 22:07:02

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 the response() 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.

  1. Faster with Lazy Loading

    • Properties like $app, $request, and $validate load only when you use them, saving memory and improving performance.
  2. Works Seamlessly with Routing

    • Automatically links to Luminova’s routing system.
    • Makes it easy to handle requests, validate data, and send responses.
  3. 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.
  4. 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.
  5. Flexible Responses

    Easily return different formats using

    • Luminova\Template\Response - Great for APIs, web pages, or mixed apps
    • Luminova\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 instance

  • Any 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


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:

ParameterTypeDescription
$templatestringThe template file name without the extension (e.g., index).
$optionsarray<string,mixed>Optional scope data to pass to the template.
$typestringThe content type (default: View::HTML).
$statusintHTTP 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:

ParameterTypeDescription
$templatestringThe template file name without the extension (e.g., index).
$optionsarray<string,mixed>Optional scope data to pass to the template.
$typestringThe content type (default: View::HTML).
$statusintHTTP 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:

ParameterTypeDescription
$uristringThe request URI, useful for logging or triggering an error view.
$metadataarray<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');
   }
}