Skip to main content
Version: v2.0 (upcoming)

Application Kernel

The src/KernelFactory.php file is how you will modify the behaviour of your application. This file is responsible for creating the application container and the base kernel for the application that will process requests using middleware and return a response.

KernelFactory has three static methods, each building on the previous:

MethodReturnsPurpose
getPackages()arrayReturns the list of package config files to load into the container.
createApplicationContainer()ContainerInterfaceBuilds and compiles the PHP-DI container from all packages and services.php.
createHttpKernel()KernelCreates the container, then constructs the HTTP kernel and registers all middleware.

Adding a package

getPackages() returns the ordered list of config/packages/*.php files that are loaded into the container. To enable an optional package, add its path to the array:

public static function getPackages(): array
{
$packages = [
// ... existing packages ...
__DIR__ . '/../config/packages/security.php',
__DIR__ . '/../config/packages/oauth.php',
];

// ...

return $packages;
}

Environment-specific packages

Packages that should only be active in development are added conditionally. The standard install already does this for development.php (Whoops error pages) and generator.php (code generation commands):

if ((bool) ('dev' === $_ENV['ENVIRONMENT'])) {
$packages[] = __DIR__ . '/../config/packages/development.php';
$packages[] = __DIR__ . '/../config/packages/generator.php';
}

Apply the same pattern for any package that should not be loaded in production.

Package load order

Packages are loaded in the order they appear in the array. Because each file can add values to shared lists (using PHP-DI's add()), later packages can depend on services defined by earlier ones. config/services.php is always loaded last and takes precedence over everything — use it for application-level overrides.


Adding middleware

createHttpKernel() builds the HTTP kernel and registers middleware by calling $kernel->addMiddleware(). Middleware is executed in the order it is added for incoming requests, and in reverse order for outgoing responses.

public static function createHttpKernel(): Kernel
{
$container = self::createApplicationContainer();
$kernel = new Kernel(
$container,
$container->get(EventDispatcherInterface::class),
$container->get(LoggerInterface::class)
);

$kernel->addMiddleware(MyMiddleware::class);

return $kernel;
}

The class name passed to addMiddleware() is resolved from the container, so any middleware that declares constructor dependencies will have them autowired automatically.

Default middleware stack

The standard install registers the following middleware in this order:

MiddlewareConditionDescription
WhoopsMiddlewareapp.debug onlyCatches unhandled exceptions and renders a Whoops error page.
DefaultCacheMiddlewareAlwaysAdds default Cache-Control headers to responses.
GeneratedByMiddlewareAlwaysAppends an X-Generated-By header identifying the framework.
AllowedHostMiddlewareAlwaysRejects requests with an untrusted Host header (400).
CorsMiddlewareAlwaysHandles CORS preflight requests and injects CORS response headers.
GraphiQLMiddlewareapp.debug onlyServes the GraphiQL in-browser IDE at a well-known path.
TrailingSlashMiddlewareAlwaysRedirects requests with a trailing slash to the canonical path.
GraphQLMiddlewareAlwaysHandles requests to the GraphQL endpoint.
RoutingMiddlewareAlwaysDispatches all other requests to the matched HTTP controller.

Adding custom middleware

Insert your middleware at the appropriate position in the stack. For example, to add a session middleware that must run after security but before routing:

// Security middlewares.
$kernel->addMiddleware(AllowedHostMiddleware::class);
$kernel->addMiddleware(CorsMiddleware::class);

// Session handling.
$kernel->addMiddleware(\Application\Middleware\SessionMiddleware::class);

// The main routing middlewares.
$kernel->addMiddleware(TrailingSlashMiddleware::class);
$kernel->addMiddleware(GraphQLMiddleware::class);
$kernel->addMiddleware(RoutingMiddleware::class);

Container compilation

In non-development environments createApplicationContainer() enables two PHP-DI optimisations:

if (!(bool) ('dev' === $_ENV['ENVIRONMENT'])) {
$builder->writeProxiesToFile(true, __DIR__ . '/../var/cache/proxies');
$builder->enableCompilation(__DIR__ . '/../var/cache');
}
OptimisationPathDescription
Proxy generationvar/cache/proxies/Writes lazy-loading proxy classes to disk instead of generating them at runtime.
Container compilationvar/cache/Compiles the full container definition into a single CompiledContainer.php file for maximum performance.

These are disabled in dev so that container changes (new services, changed definitions) are picked up immediately without a cache-clear step. Run cache:clear after any deployment to production to regenerate the compiled container.