Slide 1

Slide 1 text

Into the kernel and back Jakub Zalas Lisbon, 8.03.2014

Slide 2

Slide 2 text

Olá! I work @SensioLabsUK I tweet @jakub_zalas I code @jakzal

Slide 3

Slide 3 text

HttpKernelInterface

Slide 4

Slide 4 text

namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; interface HttpKernelInterface { const MASTER_REQUEST = 1; const SUB_REQUEST = 2; /** * @return Response */ public function handle( Request $request, $type = self::MASTER_REQUEST, $catch = true ); }

Slide 5

Slide 5 text

namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; interface HttpKernelInterface { const MASTER_REQUEST = 1; const SUB_REQUEST = 2; /** * @return Response */ public function handle( Request $request, $type = self::MASTER_REQUEST, $catch = true ); }

Slide 6

Slide 6 text

Request Response /hello/sfdaypt

Slide 7

Slide 7 text

$response = $kernel->handle($request);

Slide 8

Slide 8 text

use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); $kernel = new SimpleKernel(); $response = $kernel->handle($request); $response->send();

Slide 9

Slide 9 text

use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class SimpleKernel implements HttpKernelInterface { public function handle(Request $request /*,...*/) { return new Response('Hello Portugal'); } }

Slide 10

Slide 10 text

use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class SimpleKernel implements HttpKernelInterface { public function handle(Request $request /*,...*/) { return new Response('Hello Portugal'); } }

Slide 11

Slide 11 text

Routing

Slide 12

Slide 12 text

Request Response callable   callable   callable   callable   / /hello/{name} /contact /events Router /hello/sfdaypt

Slide 13

Slide 13 text

public function handle(Request $request /*,...*/) { $controller = $this->matchRequest($request); $response = call_user_func($controller): return $response; } private function matchRequest(Request $request) { $map = array( '/' => array(new Homepage(), 'indexAction'), '/contact' => array(new Contact(), 'formAction') ); return $map[$request->getPathInfo()]; }

Slide 14

Slide 14 text

public function handle(Request $request /*,...*/) { $controller = $this->matchRequest($request); $response = call_user_func($controller): return $response; } private function matchRequest(Request $request) { $map = array( '/' => array(new Homepage(), 'indexAction'), '/contact' => array(new Contact(), 'formAction') ); return $map[$request->getPathInfo()]; }

Slide 15

Slide 15 text

private function matchRequest(Request $request) { $routes = $this->getRoutes(); $context = new RequestContext(); $context->fromRequest($request); $urlMatcher = new UrlMatcher($routes, $context); return $urlMatcher->matchRequest($request); } private function getRoutes() { $routes = new RouteCollection(); $routes->add('homepage', new Route('/', array('_controller' => 'Homepage::indexAction'))); $routes->add('contact', new Route('/', array('_controller' => 'Contact::formAction'))); return $routes; }

Slide 16

Slide 16 text

private function matchRequest(Request $request) { $routes = $this->getRoutes(); $context = new RequestContext(); $context->fromRequest($request); $urlMatcher = new UrlMatcher($routes, $context); return $urlMatcher->matchRequest($request); } private function getRoutes() { $routes = new RouteCollection(); $routes->add('homepage', new Route('/', array('_controller' => 'Homepage::indexAction'))); $routes->add('contact', new Route('/', array('_controller' => 'Contact::formAction'))); return $routes; }

Slide 17

Slide 17 text

private function matchRequest(Request $request) { $routes = $this->getRoutes(); $context = new RequestContext(); $context->fromRequest($request); $urlMatcher = new UrlMatcher($routes, $context); return $urlMatcher->matchRequest($request); } private function getRoutes() { $routes = new RouteCollection(); $routes->add('homepage', new Route('/', array('_controller' => 'Homepage::indexAction'))); $routes->add('contact', new Route('/', array('_controller' => 'Contact::formAction'))); return $routes; }

Slide 18

Slide 18 text

hello: path: /hello/{name} defaults: _controller: 'DemoController::helloAction'

Slide 19

Slide 19 text

private function getRoutes() { $locator = new FileLocator(array(__DIR__)); $loader = new YamlFileLoader($locator); $routes = $loader->load('routes.yml'); return $routes; }

Slide 20

Slide 20 text

public function handle(Request $request /*,...*/) { // ['_controller' => 'Homepage::indexAction'] $parameters = $this->matchRequest($request); // [new Homepage(), 'indexAction'] $controller = ??? $response = call_user_func($controller): return $response; }

Slide 21

Slide 21 text

Controller resolver

Slide 22

Slide 22 text

Request Response callable   callable   callable   callable   / /hello/{name} /contact /events Router /hello/sfdaypt Controller Resolver

Slide 23

Slide 23 text

public function handle(Request $request /*,...*/) { $parameters = $this->matchRequest($request); $controller = $this->resolveController($parameters); $response = call_user_func($controller): return $response; } private function resolveController($parameters) { // i.e. Homepage::indexAction $controller = $parameters['_controller']; list($class, $method) = explode('::', $controller); $controller = new $class(); return array($class, $method); }

Slide 24

Slide 24 text

public function handle(Request $request /*,...*/) { $parameters = $this->matchRequest($request); $controller = $this->resolveController($parameters); $response = call_user_func($controller): return $response; } private function resolveController($parameters) { // i.e. Homepage::indexAction $controller = $parameters['_controller']; list($class, $method) = explode('::', $controller); $controller = new $class(); return array($class, $method); }

Slide 25

Slide 25 text

public function handle(Request $request /*,...*/) { $parameters = $this->matchRequest($request); $controller = $this->resolveController($parameters); $response = call_user_func($controller): return $response; } private function resolveController($parameters) { // i.e. Homepage::indexAction $controller = $parameters['_controller']; list($class, $method) = explode('::', $controller); $controller = new $class(); return array($class, $method); }

Slide 26

Slide 26 text

use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; public function __construct( RequestMatcherInterface $matcher, ControllerResolverInterface $resolver ) { $this->matcher = $matcher; $this->resolver = $resolver; }

Slide 27

Slide 27 text

public function handle(Request $request /*,...*/) { $parameters = $this->matcher->matchRequest($request); $request->attributes->add($parameters); $controller = $this->resolver->resolve($request); $response = call_user_func($controller): return $response; }

Slide 28

Slide 28 text

public function handle(Request $request /*,...*/) { $parameters = $this->matcher->matchRequest($request); $request->attributes->add($parameters); $controller = $this->resolver->resolve($request); $response = call_user_func($controller): return $response; }

Slide 29

Slide 29 text

EventDispatcherInterface

Slide 30

Slide 30 text

Handle Request Execute  a   controller   Geoip  lookup   Mobile   redirect   Authen6cate   ?   ?   Add     debug  to   response   ?   Match  a   request  

Slide 31

Slide 31 text

Request Response Router Controller Resolver Event Dispatcher GeoipListener SessionListener LocaleListener Firewall kernel.request TemplateListener ControllerListener ParamConverter Listener TemplateListener

Slide 32

Slide 32 text

Request Response Router Controller Resolver Event Dispatcher GeoipListener SessionListener LocaleListener Firewall kernel.request TemplateListener ControllerListener ParamConverter Listener TemplateListener

Slide 33

Slide 33 text

use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; public function __construct( EventDispatcherInterface $dispatcher, RequestMatcherInterface $matcher, ControllerResolverInterface $resolver ) { $this->eventDispatcher = $dispatcher; $this->matcher = $matcher; $this->resolver = $resolver; }

Slide 34

Slide 34 text

public function handle(Request $request, $type, $catch) { $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.request', $event); $parameters = $this->matcher->matchRequest($request); $request->attributes->add($parameters); $controller = $this->resolver->resolve($request); $response = call_user_func($controller): return $response; }

Slide 35

Slide 35 text

public function handle(Request $request, $type, $catch) { $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.request', $event); $parameters = $this->matcher->matchRequest($request); $request->attributes->add($parameters); $controller = $this->resolver->resolve($request); $response = call_user_func($controller): return $response; }

Slide 36

Slide 36 text

Request Response Router Controller Resolver Event Dispatcher GeoipListener SessionListener LocaleListener Firewall kernel.request

Slide 37

Slide 37 text

Request Response Controller Resolver Event Dispatcher kernel.request GeoipListener SessionListener LocaleListener RouterListener Firewall

Slide 38

Slide 38 text

use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; public function __construct( EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver ) { $this->eventDispatcher = $dispatcher; $this->resolver = $resolver; }

Slide 39

Slide 39 text

public function handle(Request $request, $type, $catch) { $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.request', $event); $parameters = $this->matcher->matchRequest($request); $request->attributes->add($parameters); $controller = $this->resolver->resolve($request); $response = call_user_func($controller): return $response; }

Slide 40

Slide 40 text

class RouterListener { public function __construct( RequestMatcherInterface $matcher ) { $this->matcher = $matcher } function onKernelRequest(GetResponseEvent $event) { // ... } }

Slide 41

Slide 41 text

// RouterListener public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); if ($request->attributes->has('_controller')) { // routing is already done return; } $parameters = $this->matcher->matchRequest($request); $request->attributes->add($parameters); }

Slide 42

Slide 42 text

// RouterListener public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); if ($request->attributes->has('_controller')) { // routing is already done return; } $parameters = $this->matcher->matchRequest($request); $request->attributes->add($parameters); }

Slide 43

Slide 43 text

Request Response Controller Resolver Event Dispatcher kernel.request GeoipListener SessionListener LocaleListener RouterListener Firewall

Slide 44

Slide 44 text

Request Response Controller Resolver Event Dispatcher kernel.request GeoipListener SessionListener LocaleListener RouterListener Firewall

Slide 45

Slide 45 text

// RedirectListener public function onKernelRequest(GetResponseEvent $event) { $event->setResponse( new RedirectResponse('http://www.symfonyday.pt/') ); }

Slide 46

Slide 46 text

// HttpKernel public function handle(Request $request, $type, $catch) { $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.request', $event); if ($event->hasResponse()) { return $event->getResponse(); } $controller = $this->resolver->resolve($request); $response = call_user_func($controller); return $response; }

Slide 47

Slide 47 text

Request Response Controller Resolver Event Dispatcher kernel.response CacheListener ResponseListener ProfilerListener WebDebugToolbar Listener

Slide 48

Slide 48 text

Request Response Controller Resolver Event Dispatcher kernel.finish_request LocaleListener RouterListener Firewall

Slide 49

Slide 49 text

Request Response Controller Resolver Event Dispatcher kernel.finish_request LocaleListener RouterListener Firewall

Slide 50

Slide 50 text

public function handle(Request $request, $type, $catch) { $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.request', $event); if ($event->hasResponse()) { return $this->filterResponse($event->getResponse(), $request, $type); } $controller = $this->resolver->resolve($request); $response = call_user_func($controller); return $this->filterResponse($response, $request, $type); } private function filterResponse(Response $response, Request $request, $type) { $event = new FilterResponseEvent( $this, $request, $type, $response ); $this->dispatcher->dispatch('kernel.response', $event); $response = $event->getResponse(); $event = new FinishRequestEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.finish_request', $event); return $response; }

Slide 51

Slide 51 text

public function handle(Request $request, $type, $catch) { $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.request', $event); if ($event->hasResponse()) { return $this->filterResponse($event->getResponse(), $request, $type); } $controller = $this->resolver->resolve($request); $response = call_user_func($controller); return $this->filterResponse($response, $request, $type); } private function filterResponse(Response $response, Request $request, $type) { $event = new FilterResponseEvent( $this, $request, $type, $response ); $this->dispatcher->dispatch('kernel.response', $event); $response = $event->getResponse(); $event = new FinishRequestEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.finish_request', $event); return $response; }

Slide 52

Slide 52 text

public function handle(Request $request, $type, $catch) { $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.request', $event); if ($event->hasResponse()) { return $this->filterResponse($event->getResponse(), $request, $type); } $controller = $this->resolver->resolve($request); $response = call_user_func($controller); return $this->filterResponse($response, $request, $type); } private function filterResponse(Response $response, Response $response, $type) { $event = new FilterResponseEvent( $this, $request, $type, $response ); $this->dispatcher->dispatch('kernel.response', $event); $response = $event->getResponse(); $event = new FinishRequestEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.finish_request', $event); return $response; }

Slide 53

Slide 53 text

public function handle(Request $request, $type, $catch) { $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.request', $event); if ($event->hasResponse()) { return $this->filterResponse($event->getResponse(), $request, $type); } $controller = $this->resolver->resolve($request); $response = call_user_func($controller); return $this->filterResponse($response, $request, $type); } private function filterResponse(Response $response, Response $response, $type) { $event = new FilterResponseEvent( $this, $request, $type, $response ); $this->dispatcher->dispatch('kernel.response', $event); $response = $event->getResponse(); $event = new FinishRequestEvent($this, $request, $type); $this->dispatcher->dispatch('kernel.finish_request', $event); return $response; }

Slide 54

Slide 54 text

Request Response Controller Resolver Event Dispatcher ControllerListener kernel.controller RequestDataCollector Listener ParamConverter Listener TemplateListener

Slide 55

Slide 55 text

public function handle(Request $request, $type, $catch) { // ... $controller = $this->resolver->resolve($request); $event = new FilterControllerEvent( $this, $controller, $request, $type ); $this->dispatcher->dispatch( 'kernel.controller', $event ); $controller = $event->getController(); $response = call_user_func($controller); return $this->filterResponse($response, $request, $type); }

Slide 56

Slide 56 text

public function handle(Request $request, $type, $catch) { // ... $controller = $this->resolver->resolve($request); $event = new FilterControllerEvent( $this, $controller, $request, $type ); $this->dispatcher->dispatch( 'kernel.controller', $event ); $controller = $event->getController(); $response = call_user_func($controller); return $this->filterResponse($response, $request, $type); }

Slide 57

Slide 57 text

public function handle(Request $request, $type, $catch) { // ... $controller = $this->resolver->resolve($request); $event = new FilterControllerEvent( $this, $controller, $request, $type ); $this->dispatcher->dispatch('kernel.controller', $event); $controller = $event->getController(); $arguments = $this->resolver->getArguments( $request, $controller ); $response = call_user_func($controller, $arguments); return $this->filterResponse($response, $request, $type); }

Slide 58

Slide 58 text

Request Response Controller Resolver Event Dispatcher TemplateListener kernel.view

Slide 59

Slide 59 text

public function handle(Request $request, $type, $catch) { // ... $response = call_user_func($controller, $arguments); if (!$response instance of Response) { $event = new GetResponseForControllerResultEvent( $this, $request, $type, $response ); $this->dispatcher->dispatch( 'kernel.view', $event ); $response = $event->getResponse(); } return $this->filterResponse($response, $request, $type); }

Slide 60

Slide 60 text

public function handle(Request $request, $type, $catch) { // ... $response = call_user_func($controller, $arguments); if (!$response instance of Response) { $event = new GetResponseForControllerResultEvent( $this, $request, $type, $response ); $this->dispatcher->dispatch( 'kernel.view', $event ); $response = $event->getResponse(); } return $this->filterResponse($response, $request, $type); }

Slide 61

Slide 61 text

Build-in events

Slide 62

Slide 62 text

The usual path

Slide 63

Slide 63 text

Request Response Controller Resolver Event Dispatcher kernel.request FragmentListener SessionListener LocaleListener RouterListener Firewall

Slide 64

Slide 64 text

Request Response Controller Resolver Event Dispatcher ControllerListener kernel.controller RequestDataCollector Listener ParamConverter Listener TemplateListener

Slide 65

Slide 65 text

Request Response Controller Resolver Event Dispatcher kernel.response CacheListener ResponseListener ProfilerListener WebDebugToolbar Listener

Slide 66

Slide 66 text

Request Response Controller Resolver Event Dispatcher kernel.finish_request LocaleListener RouterListener Firewall

Slide 67

Slide 67 text

Request Response Controller Resolver Event Dispatcher TemplateListener kernel.view

Slide 68

Slide 68 text

Request Response Controller Resolver Event Dispatcher kernel.terminate ProfilerListener EmailSenderListener

Slide 69

Slide 69 text

A Response set during kernel.request

Slide 70

Slide 70 text

Request Response Controller Resolver Event Dispatcher kernel.request FragmentListener SessionListener LocaleListener RouterListener Firewall

Slide 71

Slide 71 text

Request Response Controller Resolver Event Dispatcher kernel.response CacheListener ResponseListener ProfilerListener WebDebugToolbar Listener

Slide 72

Slide 72 text

Request Response Controller Resolver Event Dispatcher kernel.finish_request LocaleListener RouterListener Firewall

Slide 73

Slide 73 text

Request Response Controller Resolver Event Dispatcher kernel.finish_request LocaleListener RouterListener Firewall

Slide 74

Slide 74 text

Request Response Controller Resolver Event Dispatcher kernel.terminate TraceableEvent Dispatcher ProfilerListener EmailSenderListener

Slide 75

Slide 75 text

An exception thrown during handling a request

Slide 76

Slide 76 text

Request Response Controller Resolver Event Dispatcher kernel.request FragmentListener SessionListener LocaleListener RouterListener Firewall

Slide 77

Slide 77 text

Request Response Controller Resolver Event Dispatcher ExceptionListener AccessDeniedListener ProfilerListener kernel.exception

Slide 78

Slide 78 text

Symfony\Component\HttpKernel\HttpKernel Read more...

Slide 79

Slide 79 text

KernelInterface

Slide 80

Slide 80 text

interface KernelInterface extends HttpKernelInterface, \Serializable { public function registerBundles(); public function registerContainerConfiguration( LoaderInterface $loader); public function boot(); public function shutdown(); public function getBundles(); public function isClassInActiveBundle($class); public function getBundle($name, $first = true); public function locateResource($name, $dir = null, $first = true); public function getName(); public function getEnvironment(); public function isDebug(); public function getRootDir(); public function getContainer(); public function getStartTime(); public function getCacheDir(); public function getLogDir(); public function getCharset(); }

Slide 81

Slide 81 text

H

Slide 82

Slide 82 text

H

Slide 83

Slide 83 text

class Kernel implements KernelInterface { public function handle( Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) ) { if (false === $this->booted) { $this->boot(); } return $this->container->get('http_kernel') ->handle($request, $type, $catch); } }

Slide 84

Slide 84 text

class Kernel implements KernelInterface { public function handle( Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) ) { if (false === $this->booted) { $this->boot(); } return $this->container->get('http_kernel') ->handle($request, $type, $catch); } }

Slide 85

Slide 85 text

class Kernel implements KernelInterface { public function handle( Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) ) { if (false === $this->booted) { $this->boot(); } return $this->container->get('http_kernel') ->handle($request, $type, $catch); } }

Slide 86

Slide 86 text

public function boot() { $this->initializeBundles(); $this->initializeContainer(); foreach ($this->getBundles() as $bundle) { $bundle->setContainer($this->container); $bundle->boot(); } $this->booted = true; }

Slide 87

Slide 87 text

protected function initializeContainer() { // ... if (!$cache->isFresh()) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container/*…*/); } require_once $cache; $this->container = new $class(); $this->container->set('kernel', $this); // ... }

Slide 88

Slide 88 text

protected function initializeContainer() { // ... if (!$cache->isFresh()) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container/*…*/); } require_once $cache; $this->container = new $class(); $this->container->set('kernel', $this); // ... }

Slide 89

Slide 89 text

class appDevDebugProjectContainer extends Container { // ... protected function getLoggerService() { $this->services['logger'] = $instance = new \Symfony\Bridge\Monolog\Logger('app'); $instance->pushHandler($this->get('monolog.handler.console')); $instance->pushHandler($this->get('monolog.handler.main')); $instance->pushHandler($this->get('monolog.handler.debug')); return $instance; } // ... }

Slide 90

Slide 90 text

protected function initializeContainer() { // ... if (!$cache->isFresh()) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container/*…*/); } require_once $cache; $this->container = new $class(); $this->container->set('kernel', $this); // ... }

Slide 91

Slide 91 text

protected function initializeContainer() { // ... if (!$cache->isFresh()) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container/*…*/); } require_once $cache; $this->container = new $class(); $this->container->set('kernel', $this); // ... }

Slide 92

Slide 92 text

Container and events in a legacy application

Slide 93

Slide 93 text

$kernel = new \AppKernel('dev', true); $kernel->boot(); $request = Request::createFromGlobals(); $request->attributes->set('is_legacy', true); $container = $kernel->getContainer(); $container->enterScope('request'); $container->get('request_stack')->push($request); $event = new GetResponseEvent( $kernel, $request, HttpKernelInterface::MASTER_REQUEST ); $container->get('event_dispatcher'); ->dispatch('kernel.request', $event);

Slide 94

Slide 94 text

$kernel = new \AppKernel('dev', true); $kernel->boot(); $request = Request::createFromGlobals(); $request->attributes->set('is_legacy', true); $container = $kernel->getContainer(); $container->enterScope('request'); $container->get('request_stack')->push($request); $event = new GetResponseEvent( $kernel, $request, HttpKernelInterface::MASTER_REQUEST ); $container->get('event_dispatcher'); ->dispatch('kernel.request', $event);

Slide 95

Slide 95 text

$kernel = new \AppKernel('dev', true); $kernel->boot(); $request = Request::createFromGlobals(); $request->attributes->set('is_legacy', true); $container = $kernel->getContainer(); $container->enterScope('request'); $container->get('request_stack')->push($request); $event = new GetResponseEvent( $kernel, $request, HttpKernelInterface::MASTER_REQUEST ); $container->get('event_dispatcher'); ->dispatch('kernel.request', $event);

Slide 96

Slide 96 text

$kernel = new \AppKernel('dev', true); $kernel->boot(); $request = Request::createFromGlobals(); $request->attributes->set('is_legacy', true); $container = $kernel->getContainer(); $container->enterScope('request'); $container->get('request_stack')->push($request); $event = new GetResponseEvent( $kernel, $request, HttpKernelInterface::MASTER_REQUEST ); $container->get('event_dispatcher'); ->dispatch('kernel.request', $event);

Slide 97

Slide 97 text

$kernel = new \AppKernel('dev', true); $kernel->boot(); $request = Request::createFromGlobals(); $request->attributes->set('is_legacy', true); $container = $kernel->getContainer(); $container->enterScope('request'); $container->get('request_stack')->push($request); $event = new GetResponseEvent( $kernel, $request, HttpKernelInterface::MASTER_REQUEST ); $container->get('event_dispatcher'); ->dispatch('kernel.request', $event);

Slide 98

Slide 98 text

class RouterListener extends BaseRouterListener { public function onKernelRequest( GetResponseEvent $event ) { $request = $event->getRequest(); try { parent::onKernelRequest($event); } catch (NotFoundHttpException $e) { if (!$request->attributes->get('is_legacy')) { throw $e; } } } }

Slide 99

Slide 99 text

Thank you! https://joind.in/10782