Core

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.