Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Symfony Internals

Symfony Internals

PHPBenelux 2018

Andreas Hucks

January 27, 2018
Tweet

More Decks by Andreas Hucks

Other Decks in Programming

Transcript

  1. The Request $kernel = new Kernel($env, $debug); $request = Request::createFromGlobals();

    $response = $kernel->handle($request); $response->send();
  2. GetResponseEvent class GetResponseEvent extends KernelEvent { public function getResponse() {

    return $this->response; } public function setResponse(Response $response) { $this->response = $response; $this->stopPropagation(); } kernel.request
  3. RouterListener /** * @Route(path="/books/{id}", name="book_show") */ $params = [ '_controller'

    => ‘App\Controller\BookController::showAction’, '_route' => 'book_show', '_route_params' => [ 'id' => '37' ], 'id' => ’37' ]; kernel.request
  4. Customize! • Content Negotiation - Parse headers and add attribute

    • Verify signed Cookies • Redirects based on arbitrary criteria • Custom Locale stuff • … ?
  5. FilterControllerEvent class FilterControllerEvent extends KernelEvent { public function getController() {

    return $this->controller; } public function setController(callable $controller) { $this->controller = $controller; } kernel.controller
  6. ControllerListener class ControllerListener implements EventSubscriberInterface { public function __construct(Reader $reader)

    { $this->reader = $reader; } public function onKernelController(FilterControllerEvent $event) { $controller = $event->getController(); // read annotations for class and method $request = $event->getRequest(); foreach ($configurations as $key => $attributes) { $request->attributes->set($key, $attributes); } kernel.controller
  7. GetResponseForControllerResultEvent class GetResponseForControllerResultEvent extends GetResponseEvent { public function getControllerResult() {

    return $this->controllerResult; } public function setControllerResult($controllerResult) { $this->controllerResult = $controllerResult; } kernel.view
  8. TemplateListener public function onKernelView( GetResponseForControllerResultEvent $event ) { /* @var

    Template $template */ $request = $event->getRequest(); $template = $request->attributes->get(‘_template'); // … $event->setResponse( new Response( $this->twig->render($template->getTemplate()), $parameters ) ); kernel.view
  9. Customize! • Auto serializing and encoding for web service responses

    • Together with kernel.controller: 
 Action Domain Responder, other patterns?
  10. ExceptionListener public function onKernelException( GetResponseForExceptionEvent $event ) { $exception =

    $event->getException(); $request = $event->getRequest(); $this->logException($exception kernel.exception
  11. Customize! • Customize for every exception type you like •

    Redirect for some errors • “were you looking for…” suggestions on 404 pages • Custom alerts • … ?
  12. FilterResponseEvent class FilterResponseEvent extends KernelEvent { public function getResponse() {

    return $this->response; } public function setResponse(Response $response) { $this->response = $response; } kernel.response
  13. SaveSessionListener $session = $event->getRequest()->getSession(); if ($session && $session->isStarted()) { $session->save();

    $event->getResponse() ->setPrivate() ->setMaxAge(0) ->headers->addCacheControlDirective('must-revalidate'); } kernel.response
  14. Container & Cache protected function getRouterService() { $this->services[‘router'] = $instance

    = new \Symfony\Bundle\…\Router( $this, ‘/app/config/routing_dev.yml' ) // [snip] return $instance; }
  15. Container & Cache Cache class for this request? Does it

    exists? require() it yes Build Container no
  16. Container & Cache Cache class for this request? Does it

    exists? require() it yes Build Container no
  17. Container Build Register Bundles Register Extensions & Compiler Passes Register

    Project Config Run Extensions Run compiler Passes Dump Container Run Cache Warmers (quite a few)
  18. Container Build Register Bundles Register Extensions & Compiler Passes Register

    Project Config Run Extensions Run compiler Passes Dump Container Run Cache Warmers
  19. Registering Bundles public function registerBundles() { $bundles = [ new

    Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(), new Symfony\Bundle\TwigBundle\TwigBundle(), // [snip] ]; return $bundles; }
  20. Container Build Register Bundles Register Extensions & Compiler Passes Register

    Project Config Run Extensions Run compiler Passes Dump Container Run Cache Warmers
  21. Registering Extensions protected function prepareContainer(ContainerBuilder $container) { $extensions = array();

    foreach ($this->bundles as $bundle) { if ($extension = $bundle->getContainerExtension()) { $container->registerExtension($extension); $extensions[] = $extension->getAlias(); } // [snip] }
  22. Container Build Register Bundles Register Extensions & Compiler Passes Register

    Project Config Run Extensions Run compiler Passes Dump Container Run Cache Warmers
  23. Register Project-Level Container Config public function registerContainerConfiguration( LoaderInterface $loader )

    { $loader->load( $this->getRootDir(). ’/config/config_’.$this->getEnvironment().'.yml' ); }
  24. Container Build Register Bundles Register Extensions & Compiler Passes Register

    Project Config Run Extensions Run compiler Passes Dump Container Run Cache Warmers
  25. Extensions class TwigExtension extends Extension { public function load(array $configs,

    ContainerBuilder $container) { $loader = new XmlFileLoader( $container, new FileLocator(__DIR__.’/../Resources/config') ); $loader->load('twig.xml');
  26. Customize! • Load config files • Do not load config

    files depending on parameter • Set Parameters, manipulate parameters • BETTER NOT manipulate services (they are not complete at this point, see next slides)
  27. Container Build Register Bundles Register Extensions & Compiler Passes Register

    Project Config Run Extensions Run compiler Passes Dump Container Run Cache Warmers
  28. Compiler Passes public function process(ContainerBuilder $container) { if (!$container->has('app.myservice')) {

    return; } $definition = $container->findDefinition( 'app.myservice' ); // find formatter service $definition->addMethodCall( 'addFormatter', array(new Reference($formatterId)) ); }
  29. (A few) Compiler Passes • ServiceLocatorTagPass • DecoratorServicePass • ResolveParameterPlaceHoldersPass

    • ResolveFactoryClassPass • ResolveNamedArgumentsPass • AutowirePass • RemovePrivateAliasesPass • ReplaceAliasByActualDefinitionPass • RemoveAbstractDefinitionsPass • InlineServiceDefinitionsPass • RemoveUnusedDefinitionsPass
  30. (A few) Compiler Passes • ServiceLocatorTagPass • DecoratorServicePass • ResolveParameterPlaceHoldersPass

    • ResolveFactoryClassPass • ResolveNamedArgumentsPass • AutowirePass • RemovePrivateAliasesPass • ReplaceAliasByActualDefinitionPass • RemoveAbstractDefinitionsPass • InlineServiceDefinitionsPass • RemoveUnusedDefinitionsPass
  31. Customize! • Add method calls to services based on tags

    • Manipulate services that depend on the full service config
  32. Container Build Register Bundles Register Extensions & Compiler Passes Register

    Project Config Run Extensions Run compiler Passes Dump Container Run Cache Warmers
  33. Dump Container protected function dumpContainer( ConfigCache $cache, ContainerBuilder $container, $class,

    $baseClass ) { $dumper = new PhpDumper($container); $content = $dumper->dump(/*…*/);
  34. Container Build Register Bundles Register Extensions & Compiler Passes Register

    Project Config Run Extensions Run compiler Passes Dump Container Run Cache Warmers
  35. Cache Warmers public function warmUp($cacheDir) { $filesystem = new Filesystem();

    $templates = array(); foreach ($this->finder->findAllTemplates() as $template) { // [snip] } // [snip] $this->writeCacheFile($cacheDir.’/templates.php', // [snip] }
  36. Customize! • You have full access to services, the container

    in ready • Create custom caches your application needs • Prefetch and cache data from external sources