PHP Luminova: Core Application Architecture
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: trueto retrieve the shared instance - Use
newto 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
onPreCreateandonCreatemethod is executed.
Using Application Hook (Recommended)
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): staticParameters:
| Parameter | Type | Description |
|---|---|---|
$app | Application | The 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(): staticReturn Value:
static - Return a shared application instance.
getUri
Get the current request URI.
public final getUri(): stringReturn 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:
| Parameter | Type | Description |
|---|---|---|
$abstract | string | The interface or class name to bind. |
$resolver | Closure|string | The 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:
onPreCreateonCreateonStartonFinishonRouteResolvedonTerminatedonShutdown
public trigger(string $hook, mixed ...$arguments): void Parameters:
| Parameter | Type | Description |
|---|---|---|
$hook | string | Hook method name (e.g. onCreate, onDestroy). |
...$arguments | [mixed ...$] | Optional arguments passed to the hook. |
Throws
- \Luminova\Exceptions\BadMethodCallException If invalid event hook is provided.
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(): voidExample:
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(): voidExample:
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(): voidExample:
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:
| Parameter | Type | Description |
|---|---|---|
$info | array<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:
| Parameter | Type | Description |
|---|---|---|
$info | array<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): voidParameters:
| Parameter | Type | Description |
|---|---|---|
$context | string | The 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 messagetitle(string|null) Optional titleuri(string|null) Optional URIcontext(string) Execution context (httporcli)
Use it for final cleanup, logging, or notifications.
protected onTerminated(array $info): void Parameters:
| Parameter | Type | Description |
|---|---|---|
$info | array<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): boolParameters:
| Parameter | Type | Description |
|---|---|---|
$error | array<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
truelets the framework continue with its default error page or logging flow.