The life of a request

The life of a request

In Magento a request goes through the FrontController, the router list and the action's execute(). In Symfony HttpKernel follows the same path, but every step is an event anyone can subscribe to: routing, security, argument conversion, exception handling. Understand this diagram, and most of Symfony's "magic" becomes ordinary event listeners.

flowchart TD
  A["public/index.php"] --> B["Kernel::handle(Request)"]
  B --> C{{"kernel.request"}}
  C -->|"RouterListener finds the route"| C2["Firewall: who the user is"]
  C2 --> D{{"kernel.controller"}}
  D --> E["ArgumentResolver: Request, entities, DTOs"]
  E --> F["Controller"]
  F -->|"returned a Response"| H{{"kernel.response"}}
  F -->|"returned something else"| G{{"kernel.view"}}
  G --> H
  H --> I["Response::send()"]
  I --> J{{"kernel.terminate"}}
  F -. "exception" .-> X{{"kernel.exception"}}
  X --> H
Symfony step Closest in Magento What happens there
public/index.php, Kernel pub/index.php, Bootstrap, App\Http::launch() Loading the compiled container.
kernel.request: RouterListener (priority 32) FrontController::dispatch(), RouterList::match() The route is written into the Request attributes.
kernel.request: Firewall (priority 8) area + session, admin authentication plugin Authentication, the user token.
kernel.controller controller_action_predispatch, plugins on dispatch() This is where #[IsGranted], #[Cache] fire.
ArgumentResolver none; getParam() by hand An entity by id, a DTO from JSON, the current user.
Controller ActionInterface::execute() Your code.
kernel.view none Turning a non-Response into a Response, e.g. #[Template].
kernel.response controller_front_send_response_before Headers, cookies, the Web Profiler toolbar.
kernel.terminate none Work after the response is sent: logs, emails.
kernel.exception ExceptionHandler, noroute 404/403/500, error pages.

To see all listeners and their priorities: bin/console debug:event-dispatcher kernel.request.