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

DrupalCon 2015: Routes, controllers and responses: The Basic Lifecycle of a D8 Request

DrupalCon 2015: Routes, controllers and responses: The Basic Lifecycle of a D8 Request

Whether your viewing a node on the frontend, consuming a JSON endpoint or using the admin interface, every request in D8 follows the same workflow: routing, a controller and a response. Woh!

In this talk, we'll uncover the basic lifecycle of a D8 request, by creating a custom page using routes, a controller and a response. And you'll see just how simple life is. Once we're there, we'll dive deeper to see how Drupal uses this *exact* same stuff to fuel node pages, the admin interface and everything else. If you want to be able to create custom pages or open up the hood and really "get" D8, this is your first step.

weaverryan

May 13, 2015
Tweet

More Decks by weaverryan

Other Decks in Technology

Transcript

  1. > Husband of the much more talented @leannapelham knplabs.com twitter.com/weaverryan

    Hallo! > Lead contributor to the Symfony documentation
 > KnpLabs US - Symfony consulting, training & kumbaya > Writer for KnpUniversity.com awesome amazing PHP Tutorials!!!
  2. @weaverryan <?php
 
 namespace Drupal\dino_roar\Controller;
 
 use Symfony\Component\HttpFoundation\Response;
 
 class

    RoarController
 {
 public function roar()
 {
 return new Response('ROOOOAR');
 }
 }
  3. Request -> Response Framework Response: ROOOAR! Routing: Determine a function

    that can create this page (the controller) Request: GET /the/dino/says The Controller: Our code: constructs the page @weaverryan
  4. @weaverryan class RoarController
 {
 public function roar($count)
 {
 $roar =

    'R'.str_repeat('O', $count).'AR';
 return new Response($roar);
 }
 }
  5. @weaverryan parameters:
 factory.keyvalue:
 default: keyvalue.database
 services:
 state:
 class: Drupal\Core\State\State
 arguments:

    ['@keyvalue']
 keyvalue:
 class: Drupal\Core\KeyValueStore\KeyValueFactory
 arguments: ['@service_container', '%factory.keyvalue%']
  6. Request -> Response Framework The Controller: Our code: constructs the

    page Response: Hello Drupal! Container (with services) Routing: Determine a function that can create this page (the controller) Request: GET /hello/Drupal! @weaverryan
  7. EVENTS kernel.view kernel.response Request -> Response Framework The Controller: Our

    code: constructs the page Container (with services) EVENT kernel.controller Response: Hello Drupal! Routing: Determine a function that can create this page (the controller) EVENT kernel.request @weaverryan Request: GET /hello/Drupal!
  8. @weaverryan class RoarController
 {
 public function roar($count)
 {
 $roar =

    'R'.str_repeat('O', $count).'AR';
 return new Response($roar);
 }
 }
  9. @weaverryan class RoarController
 {
 public function roar($_route, $_access_result)
 {
 $roar

    = 'R'.str_repeat('O', $count).'AR';
 return new Response($roar);
 }
 }
  10. @weaverryan use Symfony\Component\HttpFoundation\Request;
 
 class RoarController
 {
 public function roar(Request

    $request)
 {
 $count = $request->attributes->get('count'); 
 $roar = 'R'.str_repeat('O', $count).'AR';
 return new Response($roar);
 }
 }
  11. EVENTS kernel.view kernel.response Request -> Response Framework The Controller: Our

    code: constructs the page Container (with services) EVENT kernel.controller Response: Hello Drupal! Routing: Determine a function that can create this page (the controller) EVENT kernel.request @weaverryan Arguments $request->attributes Request: GET /hello/Drupal!
  12. @weaverryan interface ParamConverterInterface {
 
 public function convert($value, $definition, $name,

    array $defaults);
 
 public function applies($definition, $name, Route $route);
 
 }
  13. @weaverryan interface ParamConverterInterface {
 
 public function convert($value, $definition, $name,

    array $defaults);
 
 public function applies($definition, $name, Route $route);
 
 } alternate_node_view:
 path: /the/dino/{node}
 defaults:
 _controller: Drupal\dino_roar\Controller\RoarController::node
 requirements:
 _permission: 'access content'
 options:
 parameters:
 node:
 type: entity:node
  14. EVENTS kernel.view kernel.response Request -> Response Framework The Controller: Our

    code: constructs the page Container (with services) EVENT kernel.controller Response: Hello Drupal! Routing: Determine a function that can create this page (the controller) EVENT kernel.request @weaverryan Arguments $request->attributes paramconverters Request: GET /hello/Drupal!
  15. EVENTS kernel.view kernel.response Request -> Response Framework The Controller: Our

    code: constructs the page Container (with services) EVENT kernel.controller Response: Hello Drupal! Routing: Determine a function that can create this page (the controller) Request: GET /hello/Drupal! EVENT kernel.request @weaverryan Arguments $request->attributes paramconverters
  16. class HtmlRenderer implements MainContentRendererInterface { public function renderResponse(array $main_content, Reques

    // ...
 $this->buildPageTopAndBottom($html);
 
 // ...
 $content = $this->renderer->render($html);
 
 $response = new CacheableResponse($content, 200,[
 'Content-Type' => 'text/html; charset=UTF-8',
 ]);
 
 return $response;
 }
 }
  17. EVENTS kernel.view kernel.response Request -> Response Framework The Controller: Our

    code: constructs the page Container (with services) EVENT kernel.controller Response: Hello Drupal! Routing: Determine a function that can create this page (the controller) EVENT kernel.request @weaverryan Arguments $request->attributes paramconverters “content renderers” Request: GET /hello/Drupal!
  18. @weaverryan class ContentControllerSubscriber implements EventSubscr public function onRequestDeriveFormWrapper(GetResponse $request =

    $event->getRequest();
 
 if ($request->attributes->has('_form')) {
 $request->attributes->set(
 '_controller',
 'controller.form:getContentResult'
 );
 }
 }
 } $ Oh, it’s in this listener
  19. @weaverryan parameters:
 factory.keyvalue:
 default: keyvalue.database
 services:
 state:
 class: Drupal\Core\State\State
 arguments:

    ['@keyvalue']
 keyvalue:
 class: Drupal\Core\KeyValueStore\KeyValueFactory
 arguments: ['@service_container', '%factory.keyvalue%']
  20. EVENTS kernel.view kernel.response Request -> Response Framework The Controller: Our

    code: constructs the page Container (with services) EVENT kernel.controller Response: Hello Drupal! Routing: Determine a function that can create this page (the controller) EVENT kernel.request @weaverryan Arguments $request->attributes paramconverters “content renderers” Request: GET /hello/Drupal!