The Symfony Framework YOUR FREE NEW TOOLKIT Hallo! > Lead - - PowerPoint PPT Presentation

the symfony framework
SMART_READER_LITE
LIVE PREVIEW

The Symfony Framework YOUR FREE NEW TOOLKIT Hallo! > Lead - - PowerPoint PPT Presentation

The Symfony Framework YOUR FREE NEW TOOLKIT Hallo! > Lead contributor to the Symfony documentation > KnpLabs US - Symfony consulting, training & kumbaya > Writer for KnpUniversity.com awesome amazing PHP Tutorials!!! >


slide-1
SLIDE 1

The Symfony Framework

YOUR FREE NEW TOOLKIT

slide-2
SLIDE 2

> 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!!!

slide-3
SLIDE 3

Act 1 Dancing on your own?

@weaverryan
slide-4
SLIDE 4

Drupal 7

/** Implements hook_menu() */
 function dinosaur_menu() {
 $items['hello'] = array(
 'title' => 'ROOOOOOAR!',
 'page callback' => 'favorite_dinosaur',
 );
 
 return $items;
 }
 
 function favorite_dinosaur() {
 return 'Triceratops';
 }

slide-5
SLIDE 5

Symfony, Silex, etc routes & controllers requests & responses service container

@weaverryan
slide-6
SLIDE 6

And now Symfony, Silex, D8

@weaverryan
slide-7
SLIDE 7

@weaverryan require_once __DIR__.'/vendor/autoload.php';
 
 $app = new Silex\Application();
 
 $app->get('/hello/{name}', function($name) use($app) {
 return 'Hello '.$app->escape($name);
 });
 
 $app->run();


slide-8
SLIDE 8

require_once __DIR__.'/vendor/autoload.php';
 
 $app = new Silex\Application();
 
 $app->get('/hello/{name}', function($name) use($app) {
 return 'Hello '.$app->escape($name);
 });
 
 $app->run();


An entire application that says hallo!

@weaverryan

slide-9
SLIDE 9

Configure your web server

slide-10
SLIDE 10

Or use the built-in PHP web server \o/

php -S localhost:8000

@weaverryan

slide-11
SLIDE 11

* The built-in PHP web server can be used with Drupal too!

@weaverryan
slide-12
SLIDE 12

Request -> Response Framework

Response: Hello Drupal! Routing:

Determine a function that can create this page (the controller)

Request: GET /hello/Drupal! The Controller:

Our code: constructs the page

@weaverryan

slide-13
SLIDE 13

require_once __DIR__.'/vendor/autoload.php';
 
 $app = new Silex\Application();
 
 $app->get('/hello/{name}', function($name) use($app) {
 return 'Hello '.$app->escape($name);
 });
 
 $app->run();


The route is matched when the URI is /hello/*

@weaverryan

slide-14
SLIDE 14

require_once __DIR__.'/vendor/autoload.php';
 
 $app = new Silex\Application();
 
 $app->get('/hello/{name}', function($name) use($app) {
 return 'Hello '.$app->escape($name);
 });
 
 $app->run();


If the URI matches the route, Silex executes this function (the controller)

@weaverryan

slide-15
SLIDE 15

require_once __DIR__.'/vendor/autoload.php';
 
 $app = new Silex\Application();
 
 $app->get('/hello/{name}', function($name) use($app) {
 return 'Hello '.$app->escape($name);
 });
 
 $app->run();


The value of {name} is passed as an argument to the controller

@weaverryan

slide-16
SLIDE 16

require_once __DIR__.'/vendor/autoload.php';
 
 $app = new Silex\Application();
 
 $app->get('/hello/{name}', function($name) use($app) {
 return 'Hello '.$app->escape($name);
 });
 
 $app->run();


We construct the page and celebrate!

@weaverryan

(or non-alcoholic beverage of your choice)
slide-17
SLIDE 17

Request -> Response Framework

Response: Hello Drupal! Routing:

Determine a function that can create this page (the controller)

Request: GET /hello/Drupal! The Controller:

Our code: constructs the page

@weaverryan

slide-18
SLIDE 18

Act 2 Hello Symfony

@weaverryan
slide-19
SLIDE 19

@weaverryan

downloads the installer

slide-20
SLIDE 20 @weaverryan my_dir_name
slide-21
SLIDE 21

Symfony Project Structure

configuration, templates PHP Classes 3rd Party Code

@weaverryan

slide-22
SLIDE 22 @weaverryan
slide-23
SLIDE 23

@weaverryan

slide-24
SLIDE 24

Hi, I’m the Symfony PacMan ghost! Look, things are working, you just don’t have any pages yet. Get to it!

@weaverryan

slide-25
SLIDE 25

Install Build a page!

@weaverryan
slide-26
SLIDE 26

hello_world:
 path: /hello/{name}
 defaults:
 _controller: AppBundle\…sayHelloAction


AppBundle\Controller\PoliteController::sayHelloAction

@weaverryan
slide-27
SLIDE 27

namespace AppBundle\Controller;
 
 use Symfony\Component\HttpFoundation\Response;
 
 class PoliteController
 {
 public function sayHelloAction($name)
 {
 return new Response('Hello '.$name);
 }
 }


@weaverryan
slide-28
SLIDE 28

@weaverryan

slide-29
SLIDE 29

Request -> Response Framework

The Controller:

Our code: constructs the page

Response: Hello Drupal! Routing:

Determine a function that can create this page (the controller)

Request: GET /hello/Drupal!

@weaverryan

slide-30
SLIDE 30

Debugging?

@weaverryan
slide-31
SLIDE 31
slide-32
SLIDE 32

@weaverryan

slide-33
SLIDE 33

@weaverryan

slide-34
SLIDE 34

@weaverryan

slide-35
SLIDE 35
slide-36
SLIDE 36
slide-37
SLIDE 37

Can we do even less work?

@weaverryan
slide-38
SLIDE 38

// ...
 
 class PoliteController
 {
 /**
 * @Route("/hello/{name}", name="hello_world")
 */
 public function sayHelloAction($name)
 {
 return new Response('Hello '.$name);
 }
 }


@weaverryan
slide-39
SLIDE 39

Act 3 Services and the “container”

@weaverryan
slide-40
SLIDE 40

Services == Useful Objects

@weaverryan

slide-41
SLIDE 41

The container == the object that contains all the services

@weaverryan

slide-42
SLIDE 42

In Silex, Symfony & Drupal 8 there is a “container”. If you have it, you can use any service (useful object)

@weaverryan
slide-43
SLIDE 43

In Symfony and Drupal 8 The container is pre-loaded with many useful services (objects)

slide-44
SLIDE 44

That’s 224 built-in services

@weaverryan
slide-45
SLIDE 45 @weaverryan
slide-46
SLIDE 46

How do I get access to the container inside a controller?

@weaverryan
slide-47
SLIDE 47

/**
 * @Route("/hello/{name}", name="hello_world")
 */
 public function sayHelloAction($name)
 {
 $html = $this->container->get('templating')->render(
 'polite/sayHello.html.twig',
 ['myName' => $name]
 );
 
 return new Response($html);
 }


@weaverryan
slide-48
SLIDE 48

{% extends 'base.html.twig' %}
 
 {% block body %}
 Hello {{ myName }}!
 {% endblock %}


@weaverryan
slide-49
SLIDE 49

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

slide-50
SLIDE 50

What else does Symfony do?

@weaverryan
slide-51
SLIDE 51

Doctrine ORM

$em = $this->container

  • >get('doctrine.orm.entity_manager');


 $post = $em->getRepository('AppBundle:Post')


  • >findOneBySlug($slug);



 // ...
 
 $em->persist($post);
 $em->flush();


@weaverryan
slide-52
SLIDE 52
  • r just use the DBAL or PDO

$conn = $this->container

  • >get('database_connection');


 $sql = 'SELECT id, name FROM post';
 $posts = $conn->fetchAll($sql);

@weaverryan
slide-53
SLIDE 53

Forms

$form = $this->container->get('form.factory')
  • >createBuilder()

  • >add('email', 'email')

  • >add('username', 'text')

  • >add('gender', 'choice', [

'choices' => ['f' => 'Female', 'm' => 'Male']
 ])

  • >getForm();


 $form->handleRequest($request);
 if ($form->isValid()) {
 $data = $form->getData();
 // do some stuff
 }
 
 $html = $this->container->get('templating')->render(
 'user/register.html.twig',
 ['form' => $form->createView()]
 );
 
 return new Response($html);
slide-54
SLIDE 54

Forms

{{ form_start(form) }}
 {{ form_row(form.email) }}
 {{ form_row(form.username) }}
 {{ form_row(form.gender) }}
 
 <button type="submit">Do it!</button>
 {{ form_end(form) }}

@weaverryan
slide-55
SLIDE 55
  • r just do it yourself

$email = $request->request->get('email');
 $username = $request->request->get('username');
 $gender = $request->request->get('gender');

@weaverryan
slide-56
SLIDE 56

… and infinitely more with community bundles

@weaverryan
slide-57
SLIDE 57

Act 4 Creating your own Services

@weaverryan
slide-58
SLIDE 58

Now we want to select a random greeting each time

@weaverryan
slide-59
SLIDE 59

Put this logic in our controller? How about a flat function somewhere?

@weaverryan
slide-60
SLIDE 60 namespace AppBundle\Greet;
 
 class RandomGreeter
 {
 private static $greetings = [
 'Hello %s',
 'Hola %s!',
 'git blame. Ah, I knew it was %s!'
 ];
 
 public function randomlyGreet($name)
 {
 $key = array_rand(self::$greetings);
 $greeting = self::$greetings[$key];
 
 return sprintf($greeting, $name);
 }
 }
slide-61
SLIDE 61

public function sayHelloAction($name)
 {
 $greeter = new RandomGreeter();
 $greeting = $greeter->randomlyGreet($name);
 
 $html = $this->container->get('templating')->render(
 'polite/sayHello.html.twig',
 ['theGreeting' => $greeting]
 );
 
 return new Response($html);
 }

@weaverryan
slide-62
SLIDE 62

Could we log which greeting was chosen?

@weaverryan
slide-63
SLIDE 63 @weaverryan
slide-64
SLIDE 64

public function sayHelloAction($name)
 {
 $greeter = new RandomGreeter();
 $greeting = $greeter->randomlyGreet($name);
 
 $this->container->get('logger')


  • >info('Created greeting: '.$greeting);



 // ...
 }


@weaverryan
slide-65
SLIDE 65

Could we log from inside RandomGreeter?

@weaverryan
slide-66
SLIDE 66

class RandomGreeter
 {
 public function randomlyGreet($name)
 {
 $key = array_rand(self::$greetings);
 $greeting = self::$greetings[$key];
 
 $this->container->get('logger')


  • >info('Created greeting: '.$greeting);



 return sprintf($greeting, $name);
 }
 } There’s no container property! That’s

magic only the controller has

slide-67
SLIDE 67
  • mg

DEPENDENCY INJECTION

@weaverryan
slide-68
SLIDE 68

class RandomGreeter
 {
 private $logger;
 
 public function __construct($logger)
 {
 $this->logger = $logger;
 }
 
 // ...
 }


@weaverryan
slide-69
SLIDE 69

class RandomGreeter
 {
 private $logger;
 
 public function __construct(LoggerInterface $logger)
 {
 $this->logger = $logger;
 }
 
 // ...
 }


@weaverryan

If you’re feeling fancy and/or awesome

slide-70
SLIDE 70

class RandomGreeter
 {
 private $logger;
 
 // ...
 
 public function randomlyGreet($name)
 {
 $key = array_rand(self::$greetings);
 $greeting = self::$greetings[$key];
 
 $this->logger

  • >info('Created greeting: '.$greeting);



 return sprintf($greeting, $name);
 }
 }


slide-71
SLIDE 71

public function sayHelloAction($name)
 {
 $greeter = new RandomGreeter( $this->container->get('logger') );
 $greeting = $greeter->randomlyGreet($name);
 
 // ...
 }

@weaverryan
slide-72
SLIDE 72

Act 5 Teach Symfony how to instantiate your services

@weaverryan
slide-73
SLIDE 73

services:
 my_random_greeter:
 class: AppBundle\Greet\RandomGreeter
 arguments:


  • "@logger"

@weaverryan
slide-74
SLIDE 74

services:
 my_random_greeter:
 class: AppBundle\Greet\RandomGreeter
 arguments:


  • "@logger"

slide-75
SLIDE 75

public function sayHelloAction($name)
 {
 /* $greeter = new RandomGreeter(
 $this->container->get('logger')
 ); */
 
 $greeter = $this->container

  • >get('my_random_greeter');


$greeting = $greeter->randomlyGreet($name);
 
 // ...
 }


@weaverryan
slide-76
SLIDE 76

Act 6 Events

(extra credit)

@weaverryan
slide-77
SLIDE 77

Just like Drupal “hooks”, Silex has events

@weaverryan
slide-78
SLIDE 78

“Hi! When event XXXXX happens, execute this

  • function. kthxbai”

YOU CAN TELL SILEX

@weaverryan
slide-79
SLIDE 79 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
slide-80
SLIDE 80

What if we didn’t return a Response from the controller?

slide-81
SLIDE 81

public function sayHelloAction($name)
 {
 $greeter = $this->container

  • >get('my_random_greeter');


$greeting = $greeter->randomlyGreet($name);
 
 return [
 'template' => 'polite/sayHello.html.twig',
 'variables' => ['theGreeting' => $greeting]
 ];
 }

@weaverryan
slide-82
SLIDE 82

@weaverryan

I’m so angry right now!!!!!

slide-83
SLIDE 83 class RenderArrayViewSubscriber implements EventSubscriberInterface
 {
 private $templating;
 
 public function __construct(EngineInterface $templating)
 {
 $this->templating = $templating;
 }
 
 public function onView()
 {
 // call me if the controller does not
 // return a Response
 }
 
 public static function getSubscribedEvents()
 {
 return ['kernel.view' => 'onView'];
 }
 }

slide-84
SLIDE 84 services:
 # ...
 
 listener.render_array_view_listener:
 class: AppBundle\EventListener\RenderArrayViewSubscriber
 arguments:

  • "@templating"

tags:

  • { name: kernel.event_subscriber }

@weaverryan
slide-85
SLIDE 85 public function onView(GetResponseForControllerResultEvent $event)
 {
 $controllerResult = $event->getControllerResult();
 
 if (!is_array($controllerResult)) {
 return;
 }
 if (!isset($controllerResult['template'])) {
 return;
 }
 
 $template = $controllerResult['template'];
 $variables = $controllerResult['variables'];
 $html = $this->templating->render($template, $variables);
 
 $response = new Response($html);
 $event->setResponse($response);
 }
slide-86
SLIDE 86

Act 7

Build something amazing

@weaverryan
slide-87
SLIDE 87

It’d be nice to learn by looking at a real, fully- feature application

@weaverryan

slide-88
SLIDE 88 @weaverryan
slide-89
SLIDE 89
slide-90
SLIDE 90 @weaverryan

Use

+ the Symfony plugin

http://bit.ly/phpstorm-symfony

slide-91
SLIDE 91

http://symfony.com/doc

slide-92
SLIDE 92 @weaverryan

KnpUniversity.com Screencasts

slide-93
SLIDE 93

@weaverryan require_once __DIR__.'/vendor/autoload.php';
 
 $app = new Silex\Application();
 
 $app->get('/hello/{name}', function($name) use($app) {
 return 'Hello '.$app->escape($name);
 });
 
 $app->run();


Use Silex!

slide-94
SLIDE 94

Use D8

@weaverryan
slide-95
SLIDE 95

Act 8 , &

@weaverryan

slide-96
SLIDE 96

PRINCIPAL THEMES

  • Request/Response
  • Routing/Controller
  • PHP Namespaces/Autoloading
  • Services/Container

  • Events/Listeners

  • Profiler

All are the same in Silex, Drupal & Symfony

@weaverryan

slide-97
SLIDE 97

You can use Silex to learn Drupal!

@weaverryan
slide-98
SLIDE 98

You can use Silex to learn Symfony!

@weaverryan
slide-99
SLIDE 99

You can use Symfony to learn Drupal!

@weaverryan
slide-100
SLIDE 100 https://www.flickr.com/photos/zzpza/326978423

Finally, We have more tools to solve problems

slide-101
SLIDE 101

Ryan Weaver @weaverryan

THANK YOU!