O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Forget about Index.php and build you applications around HTTP - PHPers Cracow

2.987 visualizações

Publicada em

Slides from my talk at PHPers meet-up in Cracow

Publicada em: Engenharia
  • Seja o primeiro a comentar

Forget about Index.php and build you applications around HTTP - PHPers Cracow

  1. 1. FORGET ABOUT INDEX.PHP BUILD YOUR APPLICATIONS AROUND HTTP!
  2. 2. Kacper Gunia @cakper Software Engineer @SensioLabsUK Symfony Certified Developer PHPers Silesia @PHPersPL
  3. 3. Good old days flickr.com/linkahwai/5162310920
  4. 4. Hello world in PHP“ ” + tutorial
  5. 5. Gojko’s two facts about programming web: 1)Ctrl-C 2)Ctrl-V
  6. 6. <?php   $name  =  $_GET['name'];   echo  "Hello  $name!";
  7. 7. It works! :D
  8. 8. but…
  9. 9. How HTTP works? flickr.com/see-­‐through-­‐the-­‐eye-­‐of-­‐g/4278744230
  10. 10. Request Kamehameha! Response
  11. 11. This is what HTTP is about! Request Response
  12. 12. This is what Your App is about! Request Response
  13. 13. “(…) the goal of your application is always to interpret a request and create the appropriate response based on your application logic.” Symfony.com
  14. 14. HTTP is simple flickr.com/wildhaber/5936335464
  15. 15. Request flickr.com/haniamir/3318727924
  16. 16. GET  /index.php?name=Kacper  HTTP/1.1   Host:  localhost
  17. 17. GET  /index.php?name=Kacper  HTTP/1.1   Host:  localhost I want to see…
  18. 18. GET  /index.php?name=Kacper  HTTP/1.1   Host:  localhost …this resource!
  19. 19. GET  /index.php?name=Kacper  HTTP/1.1   Host:  localhost And I know it should be on localhost
  20. 20. GET  /index.php?name=Kacper  HTTP/1.1   Host:  localhost Psst, I’m using 1.1 version of HTTP protocol
  21. 21. Response flickr.com/aftab/3364835006
  22. 22. HTTP/1.1  200  OK   Content-­‐type:  text/html   Hello  Kacper!
  23. 23. HTTP/1.1  200  OK   Content-­‐type:  text/html   Hello  Kacper! OK man, I’ve found it!
  24. 24. HTTP/1.1  200  OK   Content-­‐type:  text/html   Hello  Kacper! And it’s an HTML
  25. 25. HTTP/1.1  200  OK   Content-­‐type:  text/html   Hello  Kacper! Hello World!
  26. 26. [METH]  [REQUEST-­‐URI]  HTTP/[VER]   [Field1]:  [Value1]   [Field2]:  [Value2]   [request  body,  if  any] HTTP/[VER]  [CODE]  [TEXT]   [Field1]:  [Value1]   [Field2]:  [Value2]   [response  body] ResponseRequest
  27. 27. What if we create objects from Request & Response?
  28. 28. Object-oriented HTTP flickr.com/mohammadafshar/9571051345
  29. 29. GET  /index.php?name=Kacper  HTTP/1.1   Host:  localhost $request-­‐>getMethod();      GET   $request-­‐>getPathInfo();  /
  30. 30. HTTP/1.1  200  OK   Content-­‐type:  text/html   Hello  Kacper! $response-­‐>getStatusCode();  200   $response-­‐>getContent();        Hello  Kacper!
  31. 31. HttpFoundation flickr.com/rubempjr/8050505443
  32. 32. “The HttpFoundation component defines an object-oriented
 layer for the HTTP specification” Symfony.com
  33. 33. Request flickr.com/haniamir/3318727924
  34. 34. $request  =  Request::createFromGlobals();   $request  =  new  Request(          $_GET,          $_POST,          array(),          $_COOKIE,          $_FILES,          $_SERVER   );
  35. 35.        $_GET          $request-­‐>query            $_POST        $request-­‐>request          $_COOKIE    $request-­‐>cookies          $_FILES      $request-­‐>files          $_SERVER    $request-­‐>server                              $request-­‐>headers                                $request-­‐>attributes ParameterBag instances
  36. 36. $name  =  isset($_GET['name'])                    ?  $_GET['name']                    :  "World"; $name  =  $request                  -­‐>query                  -­‐>get('name',  'World');
  37. 37. $request-­‐>isSecure(); Verify configured secure header or the standard one
  38. 38. $request-­‐>isXmlHttpRequest(); Verify AJAX request
  39. 39. $request  =  Request::create(                                      '/',                                      'GET',                                      ['name'  =>  'Kacper']                        ); Simulate a Request
  40. 40. Response flickr.com/aftab/3364835006
  41. 41. $response  =  new  Response(          ‘Hello  Kacper!’,          Response::HTTP_OK,          ['content-­‐type'  =>  'text/html']   );   $response-­‐>prepare($request);   $response-­‐>send();
  42. 42. $response  =  new  RedirectResponse(
                                'http://example.com/'                          ); Redirect Response
  43. 43. $response  =  new  JsonResponse();   $response-­‐>setData(['name'  =>  'Kacper']); JSON Response
  44. 44. Let’s use them together!
  45. 45. $kernel  =  new  AppKernel('dev',  true);   $request  =  Request::createFromGlobals();   $response  =  $kernel-­‐>handle($request);   $response-­‐>send();   $kernel-­‐>terminate($request,  $response); Symfony app_dev.php
  46. 46. $kernel  =  new  AppKernel('dev',  true);   $request  =  Request::createFromGlobals();   $response  =  $kernel-­‐>handle($request);   $response-­‐>send();   $kernel-­‐>terminate($request,  $response); Symfony app_dev.php
  47. 47. Reminds something? ;)
  48. 48. Request Kamehameha! Response
  49. 49. Front Controller flickr.com/cedwardbrice/8334047708
  50. 50. ”The Front Controller consolidates all request handling by channeling requests through a single handler object (…)” MartinFowler.com
  51. 51. $kernel  =  new  AppKernel('dev',  true);   $request  =  Request::createFromGlobals();   $response  =  $kernel-­‐>handle($request);   $response-­‐>send();   $kernel-­‐>terminate($request,  $response);
  52. 52. Let’s go deeper…
  53. 53. HTTP Kernel flickr.com/stuckincustoms/6341844005
  54. 54. “The HttpKernel component provides a structured process for converting a Request into a Response by making use of the EventDispatcher.” Symfony.com
  55. 55. interface  HttpKernelInterface   {          const  MASTER_REQUEST  =  1;          const  SUB_REQUEST  =  2;          /**            *  @return  Response  A  Response  instance            */          public  function  handle(                  Request  $request,                    $type  =  self::MASTER_REQUEST,                    $catch  =  true);   }
  56. 56. How Symfony transforms Request into Response?
  57. 57. Event Dispatcher flickr.com/parksjd/11847079564
  58. 58. “The EventDispatcher component provides tools that allow your application components to communicate with each other by dispatching events and listening to them.” Symfony.com
  59. 59. EventDispatcher is an implementation of Mediator pattern
  60. 60. $dispatcher  =  new  EventDispatcher();   $dispatcher-­‐>addListener(                            'foo.action',                              function  (Event  $event)  {                                    //  do  whatever  you  need   });   $event  =  new  Event();   $dispatcher-­‐>dispatch('foo.action',  $event);
  61. 61. The kernel.request Event flickr.com/drakegoodman/13479419575
  62. 62. Manipulate your Request here…
  63. 63. …you can even return a Response!
  64. 64. public  function  onKernelRequest(GetResponseEvent  $event)   {          $request  =  $event-­‐>getRequest();          if  ($request-­‐>query-­‐>get('name')  ===  'Kacper')  {                  $event-­‐>setResponse(                          new  Response("We  don't  like  you!")                  );          }   }
  65. 65. …or e.g. detect device, location…
  66. 66. …and routing is resolved here
  67. 67. The Routing Component flickr.com/checksam/12814058644
  68. 68. “The Routing component maps an HTTP request to a set of configuration variables.” Symfony.com
  69. 69. $route  =  new  Route('/',  array('controller'  =>  'HelloController'));   $routes  =  new  RouteCollection();   $routes-­‐>add('hello_route',  $route);   $context  =  new  RequestContext();   $context-­‐>fromRequest($request);   $matcher  =  new  UrlMatcher($routes,  $context);   $parameters  =  $matcher-­‐>match('/');   //  ['controller'  =>  'HelloController',  '_route'  =>  'hello_route']
  70. 70. $route  =  new  Route('/',  array('controller'  =>  'HelloController'));   $routes  =  new  RouteCollection();   $routes-­‐>add('hello_route',  $route);   $context  =  new  RequestContext();   $context-­‐>fromRequest($request);   $matcher  =  new  UrlMatcher($routes,  $context);   $parameters  =  $matcher-­‐>match('/');   //  ['controller'  =>  'HelloController',  '_route'  =>  'hello_route']
  71. 71. $route  =  new  Route('/',  array('controller'  =>  'HelloController'));   $routes  =  new  RouteCollection();   $routes-­‐>add('hello_route',  $route);   $context  =  new  RequestContext();   $context-­‐>fromRequest($request);   $matcher  =  new  UrlMatcher($routes,  $context);   $parameters  =  $matcher-­‐>match('/');   //  ['controller'  =>  'HelloController',  '_route'  =>  'hello_route']
  72. 72. $route  =  new  Route('/',  array('controller'  =>  'HelloController'));   $routes  =  new  RouteCollection();   $routes-­‐>add('hello_route',  $route);   $context  =  new  RequestContext();   $context-­‐>fromRequest($request);   $matcher  =  new  UrlMatcher($routes,  $context);   $parameters  =  $matcher-­‐>match('/');   //  ['controller'  =>  'HelloController',  '_route'  =>  'hello_route']
  73. 73. $route  =  new  Route('/',  array('controller'  =>  'HelloController'));   $routes  =  new  RouteCollection();   $routes-­‐>add('hello_route',  $route);   $context  =  new  RequestContext();   $context-­‐>fromRequest($request);   $matcher  =  new  UrlMatcher($routes,  $context);   $parameters  =  $matcher-­‐>match('/');   //  ['controller'  =>  'HelloController',  '_route'  =>  'hello_route']
  74. 74. Resolve Controller flickr.com/rightbrainphotography/480979176
  75. 75. interface  ControllerResolverInterface   {          public  function  getController(                                                  Request  $request                                          );          public  function  getArguments(                                                  Request  $request,                                                                    $controller                                          );   }
  76. 76. Controller is a PHP callable
  77. 77. The kernel.controller Event flickr.com/drakegoodman/12451824524
  78. 78. Change controller here (if you need)
  79. 79. and initialise data
  80. 80. e.g. parameters conversion happens now
  81. 81. Resolve Arguments flickr.com/joiseyshowaa/2720195951
  82. 82. interface  ControllerResolverInterface   {          public  function  getController(                                                  Request  $request                                          );          public  function  getArguments(                                                  Request  $request,                                                                    $controller                                          );   }
  83. 83. Arguments come from $request->attributes ParameterBag
  84. 84. Controller Call flickr.com/taspicsvns/11768808836
  85. 85. Time for your application logic
  86. 86. Return Response object
  87. 87. Optional: The kernel.view event flickr.com/drakegoodman/11006558364
  88. 88. Transform non-Response into Response
  89. 89. e.g. @Template annotation
  90. 90. e.g. transform arrays into JSON Responses
  91. 91. The kernel.response Event flickr.com/drakegoodman/14482752231
  92. 92. Manipulate Response
  93. 93. e.g. WebDebugToolbar
  94. 94. Send Response flickr.com/stuckincustoms/5727003126
  95. 95. The kernel.terminate Event flickr.com/drakegoodman/12203395206
  96. 96. Do the heavy stuff now
  97. 97. e.g. Send Emails
  98. 98. HTTP Cache flickr.com/soldiersmediacenter/403524071
  99. 99. Cache-Control Expires
  100. 100. Cache-Control Expires
  101. 101. $response  =  new  Response();   $response-­‐>setPublic();   $response-­‐>setMaxAge(600);   $response-­‐>setSharedMaxAge(600);
  102. 102. Validation
  103. 103. public  function  indexAction(Request  $request,                                                            $name)   {          $response  =  new  Response("Hello  $name");          $response-­‐>setETag(md5($response-­‐>getContent()));          $response-­‐>setPublic();          $response-­‐>isNotModified($request);          return  $response;   }
  104. 104. ESI flickr.com/nasamarshall/6950477589
  105. 105. “The ESI specification describes tags you can embed in your pages to communicate with the gateway cache.” Symfony.com
  106. 106. <!DOCTYPE  html>   <html>          <body>          <!-­‐-­‐  ...  content  -­‐-­‐>          <!-­‐-­‐  Embed  the  content  of  another  page  -­‐-­‐>          <esi:include  src="http://..."/>          <!-­‐-­‐  ...  content  -­‐-­‐>          </body>   </html>
  107. 107. But I don’t have Varnish!
  108. 108. Symfony2 Reverse Proxy flickr.com/zacharyz/3950845049
  109. 109. $kernel  =  new  AppKernel('prod',  false);   $kernel-­‐>loadClassCache();   $kernel  =  new  AppCache($kernel);   $request  =  Request::createFromGlobals();   $response  =  $kernel-­‐>handle($request);   $response-­‐>send();   $kernel-­‐>terminate($request,  $response);
  110. 110. $kernel  =  new  AppKernel('prod',  false);   $kernel-­‐>loadClassCache();   $kernel  =  new  AppCache($kernel);   $request  =  Request::createFromGlobals();   $response  =  $kernel-­‐>handle($request);   $response-­‐>send();   $kernel-­‐>terminate($request,  $response);
  111. 111. OK, but are those things actually used outside of Symfony?
  112. 112. YES!
  113. 113. Drupal 8 phpBB SilexeZ Publish Laravel
  114. 114. Kacper Gunia Software Engineer Symfony Certified Developer PHPers Silesia Thanks!

×