Luminova Framework

PHP Luminova: Core Application Architecture

Last updated: 2026-04-19 11:59:51

The Luminova Core Application provides the foundational structure used to build and extend your application logic.

The Luminova Core Application is the base class that every Luminova application is built on. It defines the fundamental structure, patterns, and core features required to build both simple and complex applications.

Think of it as the foundation that holds your application together.

The default application class must be named Application and placed in the /app/ directory.

If you need a custom application class for different environments, it must be implemented in the Service Kernel via Kernel::getApplication(), to resolve based on request environment (e.g, HTTP or CLI).


Usage

Access via Boot

Returns the shared instance of the application class configured in the service kernel.

If Kernel::getApplication() returns null, the system falls back to app/Application.php.

use Luminova\Boot;

$app = Boot::application();

Access via Helper Function

Provides direct access to the application instance with additional control:

  • Use shared: true to retrieve the shared instance
  • Use new to replace the existing shared instance with a new one
use function Luminova\Funcs\app;

$app = app(shared: true, new: null);

Access via Service Kernel

Access the application instance directly from the Service Kernel.

use App\Kernel;

$app = Kernel::create(shared: true)->getApplication();

Note:

The fallback resolution if no custom application is defined is not supported.


Extending Application Class

A custom application class extends the core application and is used to configure routing, services, and other bootstrap logic.

The most common use case is registering HMVC module namespaces and initializing application-level services.


Using the Constructor

You can use __construct() to initialize the parent class and register custom logic immediately.

// /app/Application.php
namespace App;

use Luminova\Foundation\Core\Application as CoreApplication;

class Application extends CoreApplication
{
  public function __construct()
  {
    parent::__construct();

    // Register HMVC module namespace
    $this->router->addNamespace('\\App\\Modules\\Blogs\\Controllers\\');

    // Additional setup...
  }
}

This approach is explicit and runs during object creation after onPreCreate and onCreate method is executed.


A cleaner approach is to override the onCreate() lifecycle hook. It is executed after the core application is fully initialized.

// /app/Application.php
namespace App;

use Luminova\Foundation\Core\Application as CoreApplication;

class Application extends CoreApplication
{
  protected function onCreate(): void
  {
    // Register HMVC module namespace
    $this->router->addNamespace('\\App\\Modules\\Blogs\\Controllers\\');

    // Additional setup...
  }
}

Using the onCreate() keeps constructor logic untouched and ensures all internal services are already initialized before you modify routing or register modules.

Overriding __construct() should only be done when you must intercept the earliest stage of object creation.


Class Definition

  • Class namespace: Luminova\Foundation\Core\Application
  • This class is an Abstract class

Properties

router

Instance of application routing system.

public ?Luminova\Interface\RouterInterface $router = null;

For more information about Luminova Routing System documentation.


Methods

setInstance

Set or replace the singleton instance with a new application object.

public static setInstance(Luminova\Foundation\Core\Application $app): static

Parameters:

ParameterTypeDescription
$appApplicationThe new application object.

Return Value:

static - Return the updated shared application instance.


getInstance

Retrieve the shared application instance.

If the Application has already been created, this method will not trigger onPreCreate or onCreate creation lifecycle again.

This guarantees that the core services come from the initial Application object, while additional instances simply reuse them.

public static getInstance(): static

Return Value:

static - Return a shared application instance.


getUri

Get the current request URI.

public final getUri(): string

Return Value:

string - Return the URI of the current request.

Note

This method will return __cli__ if called in CLI environment.


bind

Bind a class or interface for dependency injection (DI) in controller methods.

This allows you to map an interface or class name to a concrete implementation or a closure.When a controller method type-hints a dependency, this binding ensures the right object is injected.

public final bind(string $abstract, Closure|string $resolver): self 

Parameters:

ParameterTypeDescription
$abstractstringThe interface or class name to bind.
$resolverClosure|stringThe concrete class or closure returning the instance.

Return Value:

self - Return instance of application class.

Examples:

Simple and advanced bindings:

// /app/Application.php

namespace App;

use App\Models\Users;
use App\Interface\UsersModelInterface;
use Luminova\Foundation\Core\Application as CoreApplication;

class Application extends CoreApplication
{
  protected function onPreCreate(): void 
  {
    // Bind interface to implementation
    $this->bind(UsersModelInterface::class, Users::class);

    // Bind with custom initialization logic.
    $this->bind(UsersModelInterface::class, function () {
      return new Users(...);
    });
  }
}

Controller Usage:

// /app/Controllers/Http/MainController.php 

namespace App\Controllers\Http;

use Luminova\Base\Controller;
use Luminova\Attributes\Route;
use Luminova\Attributes\Prefix;
use App\Interface\UsersModelInterface;

#[Prefix(pattern: '/users/(:base)')]
class UserController extends Controller
{
  #[Route('/users/(string)', methods: ['GET'])]
  public function user(string $id, UsersModelInterface $user): int 
  {
    $data = $user->find($id);

    return $this->view('profile', [
      'data' => $data
    ]);
  }
}

trigger

Trigger protected application lifecycle hooks.

This method calls the matching on* method if it is supported. Unknown hooks throws an exception.For onTerminated, the first argument is normalized with a default uri.

Supported Hooks:

  • onPreCreate
  • onCreate
  • onStart
  • onFinish
  • onRouteResolved
  • onTerminated
  • onShutdown
public trigger(string $hook, mixed ...$arguments): void 

Parameters:

ParameterTypeDescription
$hookstringHook method name (e.g. onCreate, onDestroy).
...$arguments[mixed ...$]Optional arguments passed to the hook.

Throws


onPreCreate

Application pre create lifecycle hook.

The onPreCreate hook is triggered once, immediately after application class is initialized before routing system runs.

This allows you to override or create a custom initialization logic before routing system starts.

protected onPreCreate(): void

Example:

Using Luminova Rate Limiter:

use Luminova\Security\RateLimiter;

protected function onPreCreate(): void 
{
  $rate = new RateLimiter();
  if(!$rate->check('key')->isAllowed()){
    $rate->respond();

    Luminova::terminate(429, 'Too many request'); // Optionally terminate application.
  }
}

onCreate

Application post create lifecycle hook.

The onCreate hook is triggered once, after application class is initialized and routing system initialized.

This allows you to override properties and initialize other function requires in application.

protected onCreate(): void

Example:

use Luminova\Sessions\Session;

protected ?Session $session = null;

protected function onCreate(): void 
{
  if(Luminova::isUriPrefix(['dashboard', 'account'])){
    $this->session = new Session();
    $this->session->setStorage("my_storage");
    $this->session->start();
  }
}

onDestroy

Application destruction lifecycle hook.

The onDestroy hook is triggered once on object destruction.Override in subclasses for custom cleanup or logging.

protected onDestroy(): void

Example:

Forces collection of any existing garbage cycles.

protected function onDestroy(): void 
{
  gc_collect_cycles();
}

onStart

Application pre request handling lifecycle hook.

The onStart hook is triggered when the application routing starts handling incoming requests.

Possible Info keys:

  • context - The application context (CLI or HTTP).
  • method - The HTTP request method.
  • uri - The request URI.
  • module - The HMVC URI module (same as prefix).
  • prefix - The URI prefix.
protected onStart(array $info): void {}

Parameters:

ParameterTypeDescription
$infoarray<string,mixed>Request state information.

onFinish

Application post request handling lifecycle hook.

The onFinish lifecycle hook is triggered after a request is handled, regardless of success or failure.

Possible Info keys:

  • filename (string|null) Optional controller class file name.
  • namespace (string|null) Optional controller class namespace.
  • method (string|null) Optional controller class method name.
  • command (array|null) Optional executed command for CLI.
  • controllers (int) Number of controller files scanned for matched attributes.
  • isCache (bool) Whether cached version rendered or new content.
  • isStaticCache (bool) Whether a static cached version was served (e.g, page.html) or regular cache (e.g, page).
protected onFinish(array $info): void {}

Parameters:

ParameterTypeDescription
$infoarray<string,mixed>The handled request and controller information.

onRouteResolved

Application method-based routes lifecycle hook.

The onRouteResolved lifecycle hook is triggered after a method-based route context is resolved via (/routes/), based on URI prefix or CLI.

protected onRouteResolved(string $context): void

Parameters:

ParameterTypeDescription
$contextstringThe resolved prefix or context name loaded.

onTerminated

Application termination lifecycle hook.

The onTerminated lifecycle hook is triggered after the application terminates.

Info array keys:

  • status (int) Termination status (HTTP or exit code)
  • message (string) Termination message
  • title (string|null) Optional title
  • uri (string|null) Optional URI
  • context (string) Execution context (http or cli)

Use it for final cleanup, logging, or notifications.

protected onTerminated(array $info): void 

Parameters:

ParameterTypeDescription
$infoarray<string,mixed>Additional termination information.

Examples:

Terminate application.

if ($this->instance->ofSomethingIsTrue()) {
  Luminova::terminate(500, 'Error...');
}

Handle application termination cleanup or logging.

namespace App;

class Application extends Luminova\Foundation\Core\Application
{
  protected function onTerminated(array $info): void
  {
    Logger::debug('Application terminated', $info);
  }
}

Note:

Triggered whenever \Luminova\Luminova::terminate() is called.


onShutdown

Application error shutdown lifecycle hook.

The onShutdown hook is triggered after script shutdown triggered by a fatal error or forced termination.

This hook gives the application a final chance to inspect the shutdown state.If it returns false, the framework will skip further error handling—allowingthe application to take full control (e.g., for custom logging or rendering).

public static onShutdown(array $error): bool

Parameters:

ParameterTypeDescription
$errorarray<string,mixed>The last recorded error before shutdown (if any).

Return Value:

bool - Return false to take over shutdown handling, true to let the framework proceed.

Note:

This hook only get called if shutting down because of an error.Returning true lets the framework continue with its default error page or logging flow.