Drupal 8 Module Dev – The Crash Course – The web in a nutshell



Drupal 8 Module Dev – The Crash Course – The web in a nutshell

1 1


slides-d8-mod-dev


On Github palantirnet / slides-d8-mod-dev

Drupal 8 Module Dev

The Crash Course

Presented by Larry Garfield / Ken Rickard

Goals

Students will be able to...

  • Trace the path of a Drupal request and response
  • Create routes and controllers for requests
  • Create blocks
  • Store default module settings
  • Create forms and pages
  • Store and manage application state
  • Create and leverage application services
  • Unit test portions of a module

The web in a nutshell

PHP 4 architecture

HTTP Architecture

Symfony/HttpKernel architecture

interface HttpKernelInterface {
  const MASTER_REQUEST = 1;
  const SUB_REQUEST = 2;

  /**
   * Handles a Request to convert it to a Response.
   *
   * @param Request $request A Request instance
   * @param integer $type    The type of the request
   * @param Boolean $catch Whether to catch exceptions or not
   *
   * @return Response A Response instance
   */
  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
}

HttpKernel pipeline

Controllers

(The concept formerly known as page callbacks and now represented by a PHP callable...)

use Symfony\Component\HttpFoundation\Response;

class MyControllers {

  public function hello() {
    return new Response('<html><body>Hello World</body></html>');
  }
}
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;

class MyControllers {

  public function hello() {
    return new Response('<html><body>Hello World</body></html>');
  }

  public function helloJson() {
    $data['Hello'] = 'World';
    return new JsonResponse($data);
  }
}
use Symfony\Component\HttpFoundation\StreamedResponse;

class MyControllers {

  public function helloStream() {
    $response = new StreamedResponse();
    $response->setCallback(function () {
      echo 'Hello World';
      flush();
      sleep(2);
      echo 'Hello Universe';
      flush();
    });

    return $response;
  }
}
Segue: The most common example is just returning a file off disk...
use Symfony\Component\HttpFoundation\StreamedResponse;

class MyControllers {

  public function helloCsv() {
    $lots_of_data = get_lots_of_data();

    $response = new StreamedResponse();
    $response->headers->set('Content-Type', 'text/csv');

    $response->setCallback(function() use ($lots_of_data) {
      foreach ($lots_of_data as $record) {
        print implode(', ', $record) . PHP_EOL;
      }
    });

    return $response;
  }
}
  • Tip: Could we combine this with a StreamedResponse to send records on the fly? How?
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

class MyControllers {

  public function helloFile() {
    $response = new BinaryFileResponse('hello_world.png');

    // Do this in settings.php if you know you're on nginx or
    // have the Apache module enabled.
    Response::trustXSendfileTypeHeader();

    return $response;
  }
}
Drupalers wrote that. :-)
use Symfony\Component\HttpFoundation\Response;

class MyControllers {

  public function helloEmpty() {
    $this->doSomething();

    $response = new Response();
    $response->setStatusCode(204);
    return $response;
  }
}
class MyControllers {

  public function helloString() {
    return "The view event will turn this into a response.";
  }
}
class MyControllers {

  public function helloDrupal() {
    return array(
      '#theme' => 'a_drupal_render_array',
      '#description' => 'Those still exist.',
    );
  }
}
/hello/world/{from}/{to}
class MyControllers {

  public function helloDrupal($to, $from, Request $request) {
    return array(
      '#theme' => 'love_letter',
      '#from' => $from,
      '#to' => $to,
    );
  }
}

module.routing.yml

hello.world:
  path: '/hello/world/{from}/{to}'
  defaults:
    _content: '\Drupal\mymodule\Controller\HelloController::helloWorld'
  requirements:
    _permission: 'access content'
    from: \s+
    to: \s+

The task

As a college campus
I want to show a blast message on my site
So that I can keep the campus notified in an emergency
  • Emergency admin != block admin
  • Also trigger by low-temperature warning

The parts

  • Emergency block
  • Config form
  • Status page
  • Emergency status data
  • Weather config form
  • Weather detection

The tools

  • Block plugins
  • Page controller
  • Forms
  • State API
  • Configuration API
  • Services
  • Twig

The watch word

Loose coupling

Live demo!

Please pardon the dust

Follow along at home:https://github.com/palantirnet/emergency_block

Your mission

Make a block that shows "Happy $day" Only show the block between 9-5 Make a page that shows the open/close time Make a config form for the message to show when open/closed Make a config form to set open/close time; use it in the page and block

For reference:https://github.com/palantirnet/emergency_block

Palantir.net

Larry Garfield, Senior Architect

Ken Rickard, Director of Development

Making the Web a Better Place

Keep tabs on our work at @Palantir

Want to hear about what we're doing?