Skip to main content
Routes aren’t declared in a file. Each request handler carries attributes describing its path, method and middleware, and the router discovers them by scanning src/ plus any directory a plugin or theme registers.

Discovery

At bootstrap, an attribute mapper scans the source directory for classes with route attributes. The result is cached when CACHE=true and DEBUG=false.
That’s also how plugins and themes add their own handlers. See Routes and request handlers.
A new route on a cached installation isn’t visible until the cache is cleared. Development should run with CACHE=false.

Attributes

Path syntax

locale is a custom match type registered at bootstrap, matching language codes like en-US. Route parameters arrive as request attributes:
Higher priorities are matched first, which is how a specific route beats a catch-all.

Groups

Handlers inherit their prefix and middleware from the class they extend: Handlers that extend none of these get a root path and no middleware at all, which is what webhook and embed endpoints use deliberately.

The middleware pipeline

Middleware from a parent class runs before a child’s, so the outermost layer is always error handling.

A request end to end

POST /admin/api/categories: After the response is emitted, the entity manager is flushed.

Responses

Errors

ExceptionMiddleware maps exceptions to responses: With DEBUG on, unhandled exceptions are rethrown instead, so you see the stack trace.