Application Core
ApplicationContext, kernels, runtime lifecycle, načítání konfigurace a orchestrace service providerů.
Runtime model
Application Core is composed from ApplicationContext, Framework, HTTP Kernel, CliKernel, Config, ControllerResolver, service providers and container services. HTTP and CLI share the same context/config/provider model, but use different entry kernels.
ApplicationContext
ApplicationContext stores environment (Environment), debug mode (DebugMode) and resolved paths (Path). It is shared by HTTP and CLI runtimes and exposes helpers such as environment(), debug(), basePath(), path(), appPath(), configPath(), storagePath(), resolveWritablePath(), resolveLogPath(), resolveUploadPath() and resolveCachePath().
use Lemonade\Framework\Core\Context\ApplicationContextFactory;
$context = (new ApplicationContextFactory())->fromGlobals(__DIR__);
$context->environment();
$context->debug();
$context->basePath();
$context->configPath('Routing.php');
Context factory
ApplicationContextFactory::fromGlobals($basePath) normalizes the base path, loads .env, then reads APP_ENV, APP_DEBUG and optional APP_BASE_PATH from $_ENV, $_SERVER or getenv(). APP_ENV maps to dev, test or prod; debug defaults to enabled outside production unless APP_DEBUG overrides it.
Kernel roles
Kernel is the HTTP runtime: it loads HTTP app config, bootstraps providers, loads routes from app/Config/Routing.php, runs the framework request pipeline and emits responses through handle(). CliKernel is the CLI runtime: it loads CLI app config, bootstraps providers, builds CommandRegistry, runs CommandInterface::run() and returns an exit code.
Bootstrap internals
KernelBootstrapTrait is an internal shared implementation detail used by both kernels. It applies runtime app.* config, registers core diagnostic providers, registers configured framework providers from framework.providers and then registers application providers from providers.
Config loading
Framework creates an empty Config service during construction and loads framework defaults. ConfigLoader then reads app/Config/Config.php, combines shared with the current entrypoint section (http or cli), and loads each listed config file through Framework::configFromFile() with optional root-key wrapping.
$framework->config([
'app' => [
'name' => 'Example',
],
]);
$framework->configFromFile($context->configPath('Queue.php'), 'queue');
Providers
Providers implement ServiceProviderInterface and register container bindings. Core diagnostic providers (CoreServiceProvider, filesystem, cache and logging) are registered first, HTTP or console provider is registered by the matching kernel, common framework providers come from framework.providers, and application providers come from providers.
use Lemonade\Framework\Container\ContainerInterface;
use Lemonade\Framework\Core\ServiceProviderInterface;
final class ExampleProvider implements ServiceProviderInterface
{
public function register(ContainerInterface $container): void
{
$container->singleton(ExampleService::class, ExampleService::class);
}
}
Container
ContainerInterface extends PSR-11 Psr\Container\ContainerInterface and adds set(), singleton(), isBound() and diagnostic logger support. Container can autowire concrete classes by constructor types as a fallback, but stable framework bootstrapping relies on explicit provider bindings, especially for interfaces.
Controller dispatch
ControllerResolver::handle(RouteMatch $match, ServerRequestInterface $request) binds the live request for dispatch, resolves the controller from the container, validates the action method, maps route params to action arguments, injects ServerRequestInterface when requested and normalizes scalar/stringable/null action results to a PSR-7 HTML response.
$response = $resolver->handle($match, $request);
// Action return values may be ResponseInterface, scalar, stringable or null.
HTTP flow
HTTP entrypoints create context through ApplicationContextFactory, create a kernel through KernelFactory and call Kernel::handle(). Kernel::handle() creates a request from globals when needed, calls Kernel::run(), then emits through ResponseEmitter. Framework::run() builds the global PSR-15 middleware pipeline and falls back to DispatchRequestHandler, which matches a route, applies route middleware and dispatches the controller.
public/index.php
-> ApplicationContextFactory::fromGlobals()
-> KernelFactory::create()
-> Kernel::handle()
-> Kernel::bootstrap()
-> Framework::run()
-> MiddlewarePipeline
-> DispatchRequestHandler
-> ControllerResolver
-> ResponseEmitter
CLI flow
The Composer binary vendor/bin/lemonade proxies to the framework CLI entrypoint. It resolves the application base path, builds ApplicationContext, creates CliKernel through CliKernelFactory, forwards argv to CliKernel::handle() and exits with the returned code.
vendor/bin/lemonade
-> CliEnvironmentResolver::resolveBasePath()
-> ApplicationContextFactory::fromGlobals()
-> CliKernelFactory::create()
-> CliKernel::handle($argv)
-> CliKernel::bootstrap()
-> CommandRegistry
-> CommandInterface::run($args)
-> exit code
HTTP entrypoint
A minimal HTTP entrypoint delegates bootstrapping to context and kernel factories.
<?php
declare(strict_types=1);
use Lemonade\Framework\Core\Context\ApplicationContextFactory;
use Lemonade\Framework\Core\KernelFactory;
require __DIR__ . '/../vendor/autoload.php';
$context = (new ApplicationContextFactory())->fromGlobals(dirname(__DIR__));
(new KernelFactory())
->create($context)
->handle();
CLI entrypoint
Application code normally runs CLI through vendor/bin/lemonade. If a custom CLI entrypoint is needed, use CliKernelFactory instead of manually wiring container/framework/kernel objects.
<?php
declare(strict_types=1);
use Lemonade\Framework\Core\CliKernelFactory;
use Lemonade\Framework\Core\Context\ApplicationContextFactory;
require __DIR__ . '/../vendor/autoload.php';
$context = (new ApplicationContextFactory())->fromGlobals(dirname(__DIR__));
$argv = $_SERVER['argv'] ?? [];
exit((new CliKernelFactory())->create($context)->handle(array_values($argv)));
Error boundaries
Kernel::run() catches route-not-found and unexpected exceptions that escape the middleware pipeline, logs them through ExceptionLogger and returns debug-aware 404/500 text responses. ErrorHandlingMiddleware handles normal HTTP pipeline exceptions as HTML responses. CliKernel catches exceptions, logs through ExceptionLogger, writes an error to stderr and returns exit code 1.
Boundary
Core runtime defines bootstrapping, configuration, container wiring and dispatch mechanics. Application routes, controllers, views, domain services and business workflows are intentionally outside this overview and belong to their dedicated documentation pages or application code.