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

DupalCon Barcelona 2015 - The journey from the request to the response

Sarah KHALIL
September 30, 2015

DupalCon Barcelona 2015 - The journey from the request to the response

Let’s get in an adventure! Basically, what happens when a request is done until the response is rendered? When I first asked this question to a teammate, it was a pretext to see how I can learn most of concepts applied in the Symfony2 framework. This talk is about discovering (or re-discovering) how Symfony2 performs things internally to render a response: by going through a winding road, we’ll see how you can teach to your colleagues all of this.

Sarah KHALIL

September 30, 2015
Tweet

More Decks by Sarah KHALIL

Other Decks in Technology

Transcript

  1. WHO AM I? • Head of • Trainer & Developer

    • Enjoying sharer • Contributor to
  2. WHAT’S THE PLAN? • The philosophy of Symfony • Heart

    of Drupal : Dependency Injection Component • And Templating?
  3. request GET /users HTTP/1.1 Host: 127.0.0.1:8000 User-Agent: curl/7.37.1 response HTTP/1.1

    200 OK Host: 127.0.0.1:8000 Content-Type: text/html; <html>Some content</html>
  4. request GET /users HTTP/1.1 Host: 127.0.0.1:8000 User-Agent: curl/7.37.1 response HTTP/1.1

    200 OK Host: 127.0.0.1:8000 Content-Type: text/html; <html>Some content</html> Symfony is an HTTP framework.
  5. HTTP request View Model Controller Routing component HTTP response front

    controller HttpKernel event listener HttpFoundation request HttpFoundation response
  6. HTTP request View Model Controller Routing component HTTP response front

    controller HttpKernel event listener HttpFoundation request HttpFoundation response
  7. • HttpFoundation • Abstraction of the Request & the Response

    • HttpKernel • Turns the Request in a response COMPONENTS INVOLVED
  8. • Maps a URL to a set of parameters ROUTING

    COMPONENT homepage:      path:          /      defaults:  {  _controller:  Todo\Controller\TodoController::indexAction  }
  9. • A callable responsible of communication with the Model and

    the View layers. • It must return an HttpFoundation response. CONTROLLER
  10. CONTROLLER namespace  Todo\Controller;   use  Symfony\Component\HttpFoundation\Request;   use  Symfony\Component\HttpFoundation\Response; class

     TodoController   {        public  function  hello(Request  $request)        {                return  new  Response('Some  content');        }   }
  11. HTTP request View Model Controller Routing component HTTP response front

    controller HttpKernel HttpFoundation request HttpFoundation response
  12. HTTP request View Model Controller Routing component HTTP response front

    controller HttpKernel HttpFoundation request HttpFoundation response
  13. HTTP request View Model Controller Routing component HTTP response front

    controller HttpKernel HttpFoundation request HttpFoundation response event system
  14. EVENT DISPATCHER COMPONENT Allows to easily decouple code and plugin

    new features to an object without using inheritance.
  15. 1. EVENT The dispatched event is an object which carries

    all the needed data to retrieve into each listener.
  16. 2. LISTENER The listener can be any valid PHP «

    callable » like a function name, an instance method, a static method or a closure.
  17. EVENT SUBSCRIBER 1/2 namespace  SensioLabs\Article\Listener;   use  Symfony\Component\EventDispatcher\EventSubscriberInterface;   class

     ArticleListener  implements  EventSubscriberInterface   {   //  ...          public  static  function  getSubscribedEvents()          {                  return  [                          'article.save'    =>  [                                  [  'onInsertArticle',  10  ],                                  [  'onUpdateArticle',  5  ],                          ],                          'article.delete'  =>  [  'onDeleteArticle',  0  ],                  ];          }   }
  18. EVENT LISTENER 1/2 namespace  SensioLabs\Article\EventListener;   use  Symfony\Component\HttpFoundation\Response;   use

     Symfony\Component\HttpKernel\Event\GetResponseEvent;   class  MyListener   {          public  function  onKernelRequest(GetResponseEvent  $event)          {                  if  (!$event-­‐>isMasterRequest())  {                          return;                  }                  $request  =  $event-­‐>getRequest();                  if  ($file  =  $request-­‐>attributes-­‐>get('_file'))  {                          $event-­‐>setResponse(new  Response('Some  content'));                  }          }   }
  19. EVENT LISTENER 2/2 use  Symfony\Component\EventDispatcher\Event;   use  Symfony\Component\EventDispatcher\EventDispatcher;   $dispatcher

     =  new  EventDispatcher();   $dispatcher-­‐>addListener(          KernelEvents::REQUEST,          [  new  MyListener(),  'onKernelRequest'  ]   );  
  20. EVENT DISPATCHER COMPONENT use  Symfony\Component\EventDispatcher\Event;   use  Symfony\Component\EventDispatcher\EventDispatcher;   $dp

     =  new  EventDispatcher();   //  Add  event  listeners  and/or  event  subscribers   $dp-­‐>dispatch('event.name',  new  Event());
  21. IN DRUPAL? services:      weather.job_listener:        

     class:  Drupal\weather\Listener\AddJobHeaderListener          arguments:  ['[email protected]']          tags:              -­‐  {  name:  event_subscriber  } services:      weather.job_listener:          class:  Drupal\weather\Listener\AddJobHeaderListener          arguments:  ['[email protected]']          tags:              -­‐  {  name:  kernel.event_listener,  event:   kernel.request,  method:  onKernelRequest  }
  22. HTTP request View Model Controller Routing component HTTP response front

    controller HttpKernel HttpFoundation request HttpFoundation response
  23. HTTP request View Model Controller Routing component HTTP response front

    controller HttpKernel event listener HttpFoundation request HttpFoundation response
  24. DEPENDENCY INJECTION The DI component allows you to standardize and

    centralize the way objects are constructed in your application.
  25. 1. SERVICE CONTAINER Manages the instantiation of your service. Makes

    sure that there is only one instance of a service. Stores the parameters.
  26. parameters:      weather_endpoint:  'http://api.openweathermap.org'      admin_email:  '[email protected]'  

    services:      weather.forecasts:          class:  Drupal\weather\Services\ForecastService          arguments:  ['@http_client',  '%weather_endpoint%']            weather.job_listener:              class:  Drupal\weather\Listener\AddJobHeaderListener              arguments:  ['%admin_email%']              tags:                  -­‐  {  name:  event_subscriber  }
  27. #  views/layout.twig   <!DOCTYPE  html>   <html>      

       <head>                  <meta  http-­‐equiv="Content-­‐Type"  content="text/html;   charset=UTF-­‐8">                  <title>{%  block  title  'Todo  Application'  %}</title>                  <link  rel="stylesheet"  media="screen"  type="text/css"  href="/   style.css"/>                  {%  block  stylesheets  ''  %}          </head>          <body>                  <div  id="container">                          <h1>                                  <a  href="index.php">My  Todos  List</a>                          </h1>                          <div  id="content">                                  {%  block  content  %}{%  endblock  %}                          </div>                          <div  id="footer">                                  (c)  copyright  -­‐  not  sensio                          </div>                  </div>                  {%  block  javascripts  ''  %}          </body>   </html>
  28. block title block stylesheets block content <html> </html> <head> </head>

    <body> </body> <!-- some html code --> block javascripts <!-- some html code -->
  29. #  views/home.twig   {%  extends  'layout.twig'  %}   {%  block

     title  'Tasks  Management'  %}   {%  block  content  %}          <form  action="/index.php/todo/new"  method="post">              <div>                  <label  for="title">Title:</label>                  <input  type="text"  id="title"  name="title"  size="45"/>                  <input  type="hidden"  name="action"  value="create"/>                  <button  type="submit">send</button>              </div>          </form>          <p>              There  are  <strong>{{  count  }}</strong>  tasks.          </p>   {%  endblock  %}
  30. IN DRUPAL? 2/3 //  weather.module   /**    *  Implements

     hook_theme().    */   function  weather_theme()  {      $theme['forecasts']  =  [          'variables'  =>  ['country'  =>  NULL,  'city'  =>  NULL,  'forecast'  =>  NULL],           'template'  =>  'forecasts',      ];      return  $theme;   }
  31. IN DRUPAL?3/3 //  In  the  Controller   public  function  forecasts($country,

     $city)   {      $forecast  =  $this-­‐>forecastService-­‐>getForecasts($country,  $city);      return  [           '#theme'  =>  'forecasts',          '#country'  =>  $country,          '#city'  =>  $city,          '#forecast'  =>  $forecast,      ];    }
  32. Come see us at the SensioLabs booth! Wanna make jokes

    or know more about Lannister? @catlannister