Omega MVC — Application Package Manual
The Omega\Application package is the application kernel. It builds the base, wires path bindings, registers providers, boots the framework, and exposes the global app(). ApplicationInterface extends the container contract, so the application is the container: everything resolved through app()->get(...) comes from the single container instance.
The class hierarchy
Omega\Container\Container
│
└── Omega\Application\AbstractApplication implements Omega\Application\ApplicationInterface
│
└── Omega\Application\Application (concrete runtime)Container implements PSR-11 (get/has) plus the Omega\Container\ContainerInterface contract — autowiring, call, alias, bindings, request-scoped singletons, etc. The ApplicationInterface adds the kernel duties: bootstrapping, provider registration, environment, maintenance mode, abort, terminate.
Creating the application
use Omega\Application\Application;
$app = new Application(__DIR__ . '/../'); // absolute base pathThe constructor:
- sets the
path.basebinding to<base>/; - calls
setConfigPath()(bindspath.config=<base>/config/); - registers the special bindings (
app,ApplicationInterface::class,ApplicationManifest::class); - calls
registerAlias()(see Aliases); - binds every standard path from
setDefinitions()(see Paths).
Only one app can live at a time. Constructing a new Application flushes any previous instance (via flush()) and becomes the new singleton — so repeated construction for tests is safe. The app must be a concrete Application; a custom class extending AbstractApplication is rejected with a LogicException (setBaseBinding()).
Getting the application
use function Omega\Application\app;
$app = app(); // Application (singleton)
$app->getInstance(); // ?Application — null before construction
$app->getName(); // from binding app.name
$app->getVersion(); // from binding app.version
$app->getEnvironment(); // from binding environment ('dev'/'prod'/...)
$app->isDev(); // getEnvironment() === 'dev'
$app->isProduction(); // getEnvironment() === 'prod'
$app->isDebugMode(); // from binding app.debug (bool)app() throws Omega\Exceptions\ApplicationNotAvailableException (Application not start yet!) when no instance is set. The helpers is_dev() and is_production() (same namespace) wrap the corresponding app methods.
Environment
The environment is not read from $_ENV directly: it is a container binding set by loadConfig() from the config repository:
use Omega\Config\ConfigRepository;
$app->loadConfig($configs); // binds config, environment, app.name, app.version, app.debugloadConfig(ConfigRepository $configs) binds config (closure → repo), then environment = $configs['environment'], app.name = $configs['name'], app.version = $configs['version'], app.debug = $configs['debug'].
Paths
setDefinitions() registers these bindings (all absolute, with leading/trailing separators):
| Binding | Resolves to |
|---|---|
boot.cache | <base>/bootstrap.cache/ |
path.app | <base>/app/ |
path.cache | <base>/storage/app/cache/ |
path.command, path.controller, path.middleware, path.model, path.provider, path.exception | the matching app/... subfolders |
path.component, path.view | <base>/resources/components/, <base>/resources/views/ |
path.storage, path.logs | <base>/storage/, <base>/storage/logs/ |
path.public | <base>/public/ |
path.migrations, path.seeder, path.database | <base>/database/... |
path.compiled_view_path | <base>/storage/app/view/ |
paths.view | array with the view path |
path.config | <base>/config/ (set by setConfigPath()) |
Read them with the helpers:
use function Omega\Application\{path, get_path, set_path, slash};
get_path('path.storage'); // '<base>/storage/'
get_path('path.storage', 'logs'); // '<base>/storage/logs' (appends suffix)
get_path(['path.app', 'path.view']); // maps arrays
path('app.config'); // relative: 'app/config/'
set_path('app.config'); // absolute-styled: '/app/config/'
slash('/a/b'); // forward slashes → DIRECTORY_SEPARATOR
os_detect(); // 'windows'|'linux'|'mac'|'bsd'|'solaris'|'unknown'All helpers live in namespace Omega\Application — import them with use function or call fully qualified. set_path() throws InvalidArgumentException on an empty key.
Container bindings
The container alphabet, inherited from ContainerInterface:
$app->bind(Interface::class, Implementation::class, shared: true); // shared singleton
$app->set('some.value', $value); // store a value directly
$app->alias(Interface::class, 'some.name'); // name → interface
$app->make(Class::class); // fresh instance (bypasses cache)
$app->get(Class::class); // cached if shared
$app->call($callable); // call with auto-DI
$app->has($abstract); $app->bound($abstract); $app->resolved($abstract);
$app->getBindings();Aliases registered by registerAlias():
request→Omega\Http\Request::classview.instance→Omega\View\Templator::classvite.gets→Omega\View\Vite::classconfig→Omega\Config\ConfigRepository::class
Bootstrap sequence
use Omega\Application\Bootstrapper\RegisterProviders;
use Omega\Application\Bootstrapper\BootProviders;
$app->bootstrapWith([RegisterProviders::class, BootProviders::class]);bootstrapWith() make()-s each bootstrapper and calls ->bootstrap($app). The framework sequence:
- RegisterProviders — union of
getCoreProviders()+ configproviders+ package providers (from the manifest), filtered to realAbstractServiceProvidersubclasses and deduplicated, each passed to$app->register($p). - BootProviders — delegates to
$app->bootProvider().
bootProvider() runs booting() callbacks, then boots each core provider not yet booted, then runs booted() callbacks, then marks the app booted.
Lifecycle callbacks
$app->bootingCallback(fn () => ...); // before providers boot
$app->bootedCallback(fn () => ...); // after providers boot (runs immediately if already booted)
$app->registerTerminate(fn () => ...); // end-of-request cleanup (chainable)
$app->terminate(); // runs all terminate callbacksLate providers
register(string $provider) is idempotent: registering an already-loaded provider returns a fresh instance without re-registering. A provider registered after the app is booted is booted immediately (synchronously).
Persistent workers
resetForRequest() is the per-request reset for RoadRunner/Swoole:
$app->resetForRequest();It clears terminate/booting/booted callbacks, resetRequestScope() (drops cached request-scoped singletons), Router::reset(), AbstractFacade::flushInstance(), clears the Templator's clearables, and re-registers web routes. flush() (used also by a new construction) additionally nulls the shared instance and resets provider lists.
Maintenance mode
$app->isDownMaintenanceMode(); // true when <storage>/app/maintenance.php exists
$app->getDownData(); // ['redirect'=>null,'retry'=>null,'status'=>503,'template'=>null]getDownData() includes the <storage>/app/down file (no .php extension) and merges its returned array over the defaults.
Abort
$app->abort(404, 'Not found', ['X-Foo' => 'bar']);Always throws Omega\Http\Exceptions\HttpException($code, $message, null, $headers); you can catch it and read getStatusCode() / getHeaders().
Package manifest
ApplicationManifest discovers Composer packages that ship service providers:
providers(): array— provider class-string fromextra.omega-mvcof each installed package.build(): array— scans<base>/vendor/composer/installed.json, keeps packages withextra['omega-mvc'], writes<bootstrap.cache>/packages.php(<?php return [...] ;), returns the map.- Constructor:
(string $basePath, string $applicationCachePath, ?string $vendorPath = null).
The disk cache short-circuits installed.json reads; delete packages.php (or call build()) to refresh. It is wired as container binding ApplicationManifest::class (a factory closure) by the constructor.
Core providers
getCoreProviders() returns the providers list of the concrete Application (booted in this order):
WhoopsServiceProvider, LoggingServiceProvider, EventServiceProvider,
CronServiceProvider, HashServiceProvider, RouteServiceProvider,
SessionServiceProvider, DatabaseServiceProvider, ViewServiceProvider,
CacheServiceProvider, RateLimiterServiceProvider, RedisServiceProvider,
Http\MacroServiceProvider, CsrfServiceProviderExceptions
| Exception | When thrown |
|---|---|
Omega\Exceptions\ApplicationNotAvailableException (RuntimeException) | app() before any application is constructed — Application not start yet! |
Omega\Http\Exceptions\HttpException (RuntimeException) | abort() — carries getStatusCode(), getHeaders() |
LogicException | constructing a non-concrete AbstractApplication subclass |
InvalidArgumentException | set_path('') with an empty key |
| Container exceptions | any get/make/alias failure (EntryNotFoundException, BindingResolutionException, CircularAliasException, AliasException) |
Notes
- The Application package defines no events; lifecycle is callback-based (
booting/booted/terminate/resetForRequest). - There is no top-level
Application::run()/bootstrap()convenience method; the entry sequence isnew Application($base),bootstrapWith([...]), and a web/server loop callingterminate()/resetForRequest()at boundaries. - Helpers are namespaced (
Omega\Application) and must be imported withuse function. - Environment/debug/name/version are container bindings, not env reads.
Reference
ApplicationInterface.php,AbstractApplication.php,Application.phpApplicationManifest.php,helper.phpBootstrapper/RegisterProviders.php,Bootstrapper/BootProviders.php- Depends on:
Omega\Container,Omega\Config\ConfigRepository,Omega\Router,Omega\Facade,Omega\View\Templator,Omega\Http\Exceptions - Tests:
tests/Unit/Application/,tests/Unit/Container/ - License: GPL-3.0+