symfony2 meets drupal

Upload: chimericdream

Post on 05-Apr-2018

225 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/31/2019 Symfony2 Meets Drupal

    1/131

    meets

    http://www.flickr.com/photos/nimport_nawak/3404931191

    http://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://www.flickr.com/photos/nimport_nawak/3404931191http://www.flickr.com/photos/nimport_nawak/3404931191http://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svghttp://localhost/Users/fabien/Downloads/symfony_black_02.svg
  • 7/31/2019 Symfony2 Meets Drupal

    2/131

    Drupal 8 meets Symfony

    Fabien Potencier@fabpot

    [email protected]

    Founder of

    Lead developer of Open-Source librariesTwig, Swiftmailer, Silex, Pirum, Sismo, Pimple, Goutte, ...

    Symfony founder and lead developer

    mailto:[email protected]:[email protected]:[email protected]
  • 7/31/2019 Symfony2 Meets Drupal

    3/131

    Drupal 8 meets Symfony

    Lukas Kahwe Smith@lsmith

    [email protected]

    Works for in Switzerland

    PHP 5.3 Release Manager

    Co-lead of PHPCRSymfony2 core contributor

    mailto:[email protected]:[email protected]:[email protected]
  • 7/31/2019 Symfony2 Meets Drupal

    4/131

    http://www.flickr.com/photos/dunechaser/160405823

    Drupal 8 meets Symfony

    How many of you are

    PHP developers?

    http://www.flickr.com/photos/davemorris/3431970729http://www.flickr.com/photos/davemorris/3431970729
  • 7/31/2019 Symfony2 Meets Drupal

    5/131

    Drupal 8 meets Symfony

    http://www.flickr.com/photos/dunechaser/142079357

    How many of you are

    Symfony aware?

    http://www.flickr.com/photos/davemorris/3431970729http://www.flickr.com/photos/davemorris/3431970729
  • 7/31/2019 Symfony2 Meets Drupal

    6/131

    Drupal 8 meets Symfony

    We are both outsiders

    We are both quite experiencedPHP developers

    We have a rough understandingof the hook paradigm aka the Drupal way

    http://www.flickr.com/photos/pictureperfectpose/76138988

    http://www.flickr.com/photos/pictureperfectpose/76138988http://www.flickr.com/photos/pictureperfectpose/76138988
  • 7/31/2019 Symfony2 Meets Drupal

    7/131Drupal 8 meets Symfony

    A sad realization

    It would take a long time for usto be productive in Drupallet alone work on the core

    And everything we learn along the waywould only help us with Drupal

  • 7/31/2019 Symfony2 Meets Drupal

    8/131Drupal 8 meets Symfony

    What others do

    Building on top of long establishedOO design patterns

    Leverage new PHP language features

    and performance improvementsShare code!

  • 7/31/2019 Symfony2 Meets Drupal

    9/131

    Drupal 8 meets Symfony

    So Drupal is wrong?

    No, the question is justif the benefits of doing things differently

    outweigh the disadvantages

  • 7/31/2019 Symfony2 Meets Drupal

    10/131

    Drupal 8 meets Symfony

    Core brain drain

    The complexity of the custom code thats used

    and the non-standard architecturecombines to create a barrier to entry

    for developers new to Drupal(both experienced and novice developers alike).

    buytaert.net

    http://buytaert.net/the-future-is-a-restful-drupalhttp://buytaert.net/the-future-is-a-restful-drupalhttp://buytaert.net/the-future-is-a-restful-drupal
  • 7/31/2019 Symfony2 Meets Drupal

    11/131

    Drupal 8 meets Symfony

    What could be gained

    Facilitate the refactoringtowards a framework core

    Focus Drupal dev resources on the CMS

    Easier integration with other applications

    Ensure that the Drupal developer poolcontinues to grow

  • 7/31/2019 Symfony2 Meets Drupal

    12/131

    Drupal 8 meets Symfony

    A decision was made

    While these changes may seem large, and some of them are,

    we believe that they will achieve the right balancebetween empowering Drupal's design and architecture,and moving toward more modern, standard,

    well-tested code and techniques

    to empower a new generation of developers.

    buytaert.net

    http://buytaert.net/the-future-is-a-restful-drupalhttp://buytaert.net/the-future-is-a-restful-drupalhttp://buytaert.net/the-future-is-a-restful-drupal
  • 7/31/2019 Symfony2 Meets Drupal

    13/131

    Drupal 8 meets Symfony

    How to collaborate?

    Symfony2 is MIT licensedwhich is GPL compatible

    Symfony2 development isvery transparently managed on github.com

    We want to ensure Symfony2works for Drupal, phpBB, etc.

    https://github.com/symfony/symfony/pullshttps://github.com/symfony/symfony/pullshttps://github.com/symfony/symfony/pulls
  • 7/31/2019 Symfony2 Meets Drupal

    14/131

    Drupal 8 meets Symfony

    For example ...

    Symfony2.0 provides a conceptcalled flash messages to pass messages

    to the very next request

    drupal_set_message() could be replacedby this if we make it a bit more flexible

    Drak, lead of the Zikula CMS, created a PRto address exactly these concerns

    https://github.com/symfony/symfony/pull/3267https://github.com/symfony/symfony/pull/3267https://github.com/symfony/symfony/pull/3267
  • 7/31/2019 Symfony2 Meets Drupal

    15/131

    Drupal 8 meets Symfony

    What isSymfony?

    http://www.flickr.com/photos/apranihita/141159146/

    http://www.flickr.com/photos/apranihita/141159146/http://www.flickr.com/photos/apranihita/141159146/
  • 7/31/2019 Symfony2 Meets Drupal

    16/131

    Drupal 8 meets Symfony

    http://www.flickr.com/photos/bigpinkcookie/22716359

    http://www.flickr.com/photos/bigpinkcookie/22716359http://www.flickr.com/photos/bigpinkcookie/22716359
  • 7/31/2019 Symfony2 Meets Drupal

    17/131

    Drupal 8 meets Symfony

    is...

    ... a reusable set ofstandalone, decoupled, and cohesivePHP components that solve

    common web development problems

    http://www.flickr.com/photos/krislitman/493626935

    http://www.flickr.com/photos/krislitman/493626935http://www.flickr.com/photos/krislitman/493626935
  • 7/31/2019 Symfony2 Meets Drupal

    18/131

    Drupal 8 meets Symfony

    is...

    ... an Object-Oriented set of classes

    ... compatible with PHP 5.3 and later

    http://www.flickr.com/photos/krislitman/493626935

    http://www.flickr.com/photos/krislitman/493626935http://www.flickr.com/photos/krislitman/493626935
  • 7/31/2019 Symfony2 Meets Drupal

    19/131

    Drupal 8 meets Symfony

    DependencyInjectionEventDispatcher

    HttpFoundation

    DomCrawler

    ClassLoader

    CssSelector

    HttpKernel

    BrowserKitTemplating

    Translation

    Filesystem

    Serializer

    ValidatorSecurity

    Routing

    ConsoleProcessConfig

    Finder

    Locale

    Yaml

    Form

  • 7/31/2019 Symfony2 Meets Drupal

    20/131

    Drupal 8 meets Symfony

    is...

    ... a full-stack web framework

    http://www.flickr.com/photos/krislitman/493626935

    http://www.flickr.com/photos/krislitman/493626935http://www.flickr.com/photos/krislitman/493626935
  • 7/31/2019 Symfony2 Meets Drupal

    21/131

    Drupal 8 meets Symfony

    Official websitehttp://symfony.com/

    Official repositoryhttps://github.com/symfony/symfony

    http://www.flickr.com/photos/28634332@N05/5654415647

    http://www.flickr.com/photos/28634332@N05/5654415647http://www.flickr.com/photos/28634332@N05/5654415647https://github.com/symfony/symfonyhttps://github.com/symfony/symfony
  • 7/31/2019 Symfony2 Meets Drupal

    22/131

    Drupal 8 meets Symfony

    Official websitehttp://symfony.com/components

    Official repositorieshttps://github.com/symfony/XXXX

    Components

    http://www.flickr.com/photos/28634332@N05/5654415647

    http://www.flickr.com/photos/28634332@N05/5654415647http://www.flickr.com/photos/28634332@N05/5654415647https://github.com/symfony/symfonyhttps://github.com/symfony/symfonyhttp://symfony.com/componentshttp://symfony.com/components
  • 7/31/2019 Symfony2 Meets Drupal

    23/131

    Drupal 8 meets Symfony

    Mailing-listhttps://groups.google.com/group/symfony2

    IRC channelirc://irc.freenode.net/symfony

    http://www.flickr.com/photos/28634332@N05/5654415647

    http://www.flickr.com/photos/28634332@N05/5654415647http://www.flickr.com/photos/28634332@N05/5654415647
  • 7/31/2019 Symfony2 Meets Drupal

    24/131

    Drupal 8 meets Symfony

    Which Open-Source projects

    are already using theSymfony Components?

    http://www.flickr.com/photos/maistora/3014414972

    http://www.flickr.com/photos/maistora/3014414972http://www.flickr.com/photos/maistora/3014414972
  • 7/31/2019 Symfony2 Meets Drupal

    25/131

    Drupal 8 meets Symfony

    Behat - a BDD frameworkConsole, DependencyInjection, EventDispatcher, Finder, Yaml, Config, Translation

    Doctrine - an object relational mapper

    Console, Yaml

    Propel - an object relational mapperConsole, ClassLoader, Yaml

    PHPUnit - a PHP unit testing frameworkYaml, (Finder soon?)

    Jackalope - a content repository (JCR 170/283)ClassLoader, Console

    Developer Tools

    http://www.flickr.com/photos/c_r_i_s/77763712

    http://www.flickr.com/photos/c_r_i_s/77763712http://www.flickr.com/photos/c_r_i_s/77763712
  • 7/31/2019 Symfony2 Meets Drupal

    26/131

    Drupal 8 meets Symfony

    Silex - a micro-frameworkBrowerKit, CssSelector, DomCrawler, EventDispatcher,

    HttpFoundation, HttpKernel, Routing, Form, Translation, Validator

    PPI 2 - a frameworkClassLoader, HttpFoundation, Routing, Templating

    Frameworks

    http://www.flickr.com/photos/c_r_i_s/77763712

    P d

    http://www.flickr.com/photos/c_r_i_s/77763712http://www.flickr.com/photos/c_r_i_s/77763712
  • 7/31/2019 Symfony2 Meets Drupal

    27/131

    Drupal 8 meets Symfony

    easybook - a book publishing platformClassLoader, Console, EventDispatcher, Filesystem, Finder, Yaml

    Midgard CMS - a content management frameworkuses the full-stack framework

    Zikula - ex PostNuke - an application frameworkHttpFoundation, HttpKernel, EventDispatcher,

    ClassLoader, DependencyInjection

    phpBB - a bulletin board softwareEventDispatcher, and most of them for version 4?

    Products

    http://www.flickr.com/photos/c_r_i_s/77763712

    http://www.flickr.com/photos/c_r_i_s/77763712http://www.flickr.com/photos/c_r_i_s/77763712
  • 7/31/2019 Symfony2 Meets Drupal

    28/131

    Drupal 8 meets Symfony

    What aboutDrupal 8?

    http://www.flickr.com/photos/aloshbennett/619307160

    http://www.flickr.com/photos/aloshbennett/619307160http://www.flickr.com/photos/aloshbennett/619307160http://www.flickr.com/photos/aloshbennett/619307160
  • 7/31/2019 Symfony2 Meets Drupal

    29/131

    Drupal 8 meets Symfony

    DependencyInjectionEventDispatcher

    HttpFoundation

    DomCrawler

    ClassLoader

    CssSelector

    HttpKernel

    BrowserKitTemplating

    Translation

    Filesystem

    Serializer

    ValidatorSecurity

    Routing

    ConsoleProcessConfig

    Finder

    Locale

    Yaml

    Form

  • 7/31/2019 Symfony2 Meets Drupal

    30/131

    Drupal 8 meets Symfony

    DependencyInjectionEventDispatcher

    HttpFoundation

    DomCrawler

    ClassLoader

    CssSelector

    HttpKernel

    BrowserKitTemplating

    Translation

    Filesystem

    Serializer

    ValidatorSecurity

    Routing

    ConsoleProcessConfig

    Finder

    Locale

    Yaml

    Form

  • 7/31/2019 Symfony2 Meets Drupal

    31/131

    Drupal 8 meets Symfony

    Using the

    SymfonyComponents

    http://www.flickr.com/photos/35168673@N03/6086229920

    Git

    http://www.flickr.com/photos/35168673@N03/6086229920http://www.flickr.com/photos/35168673@N03/6086229920
  • 7/31/2019 Symfony2 Meets Drupal

    32/131

    Drupal 8 meets Symfony

    $ git clone https://github.com/symfony/Console.git

    $ git co v2.0.9

    $ git co 2.0

    $ git co master

    Git

    A hi

    https://github.com/symfony/Console.githttps://github.com/symfony/Console.git
  • 7/31/2019 Symfony2 Meets Drupal

    33/131

    Drupal 8 meets Symfony

    $ curl -O https://github.com/symfony/Console/zipball/v2.0.9

    $ curl -O https://github.com/symfony/Console/zipball/2.0

    $ curl -O https://github.com/symfony/Console/zipball/master

    Archives

    PEAR

    https://github.com/symfony/Console.githttps://github.com/symfony/Console.githttps://github.com/symfony/Console.githttps://github.com/symfony/Console.githttps://github.com/symfony/Console.githttps://github.com/symfony/Console.git
  • 7/31/2019 Symfony2 Meets Drupal

    34/131

    Drupal 8 meets Symfony

    $ pear channel-discover pear.symfony.com

    $ pear install symfony2/Console-2.0.9

    PEAR

    C

  • 7/31/2019 Symfony2 Meets Drupal

    35/131

    Drupal 8 meets Symfony

    composer.json

    {"require": {

    "symfony/console": "2.1.*",

    "symfony/http-foundation": "v2.0.9"

    }

    }

    curl -s http://getcomposer.org/installer | php

    php composer.phar install

    Composer

    http://getcomposer.org/installerhttp://getcomposer.org/installerhttp://getcomposer.org/installer
  • 7/31/2019 Symfony2 Meets Drupal

    36/131

    Drupal 8 meets Symfony

    Symfony Componentscomes with Drupal 8

  • 7/31/2019 Symfony2 Meets Drupal

    37/131

    Drupal 8 meets Symfony

    ClassLoader

  • 7/31/2019 Symfony2 Meets Drupal

    38/131

    Drupal 8 meets Symfony

    http://symfony.com/PSR0

    http://symfony.com/PSR0http://symfony.com/PSR0http://symfony.com/PSR0
  • 7/31/2019 Symfony2 Meets Drupal

    39/131

    Drupal 8 meets Symfony

    require_once__DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';

    use Symfony\Component\ClassLoader\UniversalClassLoader;

    $loader=newUniversalClassLoader();$loader->registerNamespaces(array( 'Symfony'=>__DIR__.'/vendor/symfony/src',));

    $loader->register();

  • 7/31/2019 Symfony2 Meets Drupal

    40/131

    $loader->registerPrefixes(array(

    'Twig_'=>__DIR__.'/vendor/twig/lib',));

    Drupal 8 meets Symfony

  • 7/31/2019 Symfony2 Meets Drupal

    41/131

    Drupal 8 meets Symfony

    The Symfony ClassLoader Componentloads your project classes automatically

    if they follow some standard conventions

    http://www.flickr.com/photos/ynaffitx/4667769355

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355
  • 7/31/2019 Symfony2 Meets Drupal

    42/131

    Drupal 8 meets Symfony

    HttpFoundation

  • 7/31/2019 Symfony2 Meets Drupal

    43/131

    Drupal 8 meets Symfony

    http://www.flickr.com/photos/deniscollette/6741424757

    HTTPHTTP/1.1RFC 2616

    http://www.ietf.org/rfc/rfc2616.txt

    http://tools.ietf.org/wg/httpbis/

    http://www.flickr.com/photos/deniscollette/6741424757http://tools.ietf.org/wg/httpbis/http://tools.ietf.org/wg/httpbis/http://www.ietf.org/rfc/rfc2616.txthttp://www.ietf.org/rfc/rfc2616.txthttp://www.flickr.com/photos/deniscollette/6741424757http://www.flickr.com/photos/deniscollette/6741424757
  • 7/31/2019 Symfony2 Meets Drupal

    44/131

    Drupal 8 meets Symfony

    The Web in action

    The User asks for a Resource in a Browser

    http://example.com/foo.html

    http://example.com/foo.htmlhttp://example.com/foo.htmlhttp://example.com/foo.htmlhttp://example.com/foo.htmlhttp://example.com/foo.htmlhttp://example.com/foo.html
  • 7/31/2019 Symfony2 Meets Drupal

    45/131

    Drupal 8 meets Symfony

    The Web in action

    The User asks for a Resource in a Browser

    The Browser sends a Request to the Server

    GET /foo.html HTTP/1.1Host: example.com

  • 7/31/2019 Symfony2 Meets Drupal

    46/131

    Drupal 8 meets Symfony

    The Web in action

    The User asks for a Resource in a Browser

    The Browser sends a Request to the Server

    The Server sends back a Response to the Browser

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMT

    Content-Length: 14Content-Type: text/html

    Hello World!

  • 7/31/2019 Symfony2 Meets Drupal

    47/131

    Drupal 8 meets Symfony

    The Web in action

    The User asks for a Resource in a Browser

    The Browser sends a Request to the Server

    The Server sends back a Response to the BrowserThe Browser displays the Resource to the User

  • 7/31/2019 Symfony2 Meets Drupal

    48/131

    Drupal 8 meets Symfony

    The Client sendsa Request to the Server

    The Server sends backa Response to the Client

    Request

    GET /foo.html HTTP/1.1Host: example.com

    Response

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMTContent-Length: 14Content-Type: text/html

    Hello World!

  • 7/31/2019 Symfony2 Meets Drupal

    49/131

    Drupal 8 meets Symfony

    Request

    GET /foo.html HTTP/1.1

    Host: example.com

    http://www.flickr.com/photos/splorp/64027565

    Request

    http://www.flickr.com/photos/splorp/64027565http://www.flickr.com/photos/splorp/64027565
  • 7/31/2019 Symfony2 Meets Drupal

    50/131

    session_start();

    $name=$_GET['name'];// $_POST, $_FILE, $_COOKIE, ...

    echo $_SESSION['name'];

    $method=$_SERVER['REQUEST_METHOD'];

    Drupal 8 meets Symfony

    Request

    GET /foo.html HTTP/1.1Host: example.com

    Request

  • 7/31/2019 Symfony2 Meets Drupal

    51/131

    Drupal 8 meets Symfony

    $clientIp=$_SERVER['REMOTE_ADDR'];

    Request

    GET /foo.html HTTP/1.1Host: example.com

    Request

  • 7/31/2019 Symfony2 Meets Drupal

    52/131

    Drupal 8 meets Symfony

    if (isset($_SERVER['HTTP_CLIENT_IP'])) {return$_SERVER['HTTP_CLIENT_IP'];

    }

    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ips=explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2);

    returnisset($ips[0]) ? trim($ips[0]) : '';}

    return$_SERVER['REMOTE_ADDR'];

    Request

    GET /foo.html HTTP/1.1Host: example.com

    Request

  • 7/31/2019 Symfony2 Meets Drupal

    53/131

    Drupal 8 meets Symfony

    if ($trustProxy) {if (isset($_SERVER['HTTP_CLIENT_IP'])) {

    return$_SERVER['HTTP_CLIENT_IP'];}

    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ips=explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2);

    returnisset($ips[0]) ? trim($ips[0]) : '';}

    }

    return$_SERVER['REMOTE_ADDR'];

    Request

    GET /foo.html HTTP/1.1Host: example.com

    Request

  • 7/31/2019 Symfony2 Meets Drupal

    54/131

    Drupal 8 meets Symfony

    http://www.flickr.com/photos/viamoi/3338093351

    Not Object-Oriented

    Low-level abstraction only

    Singleton like

    Not Object-Oriented

    Request

    GET /foo.html HTTP/1.1Host: example.com

    Request

    http://www.flickr.com/photos/viamoi/3338093351http://www.flickr.com/photos/viamoi/3338093351
  • 7/31/2019 Symfony2 Meets Drupal

    55/131

    Drupal 8 meets Symfony

    use Symfony\Component\HttpFoundation\Request;

    $request=Request::createFromGlobals();

    $request=Request::create('/hello.html', 'GET');

    $request->overrideGlobals();

    Request

    GET /foo.html HTTP/1.1Host: example.com

    Request

  • 7/31/2019 Symfony2 Meets Drupal

    56/131

    Drupal 8 meets Symfony

    $request->query->get('name', 'Default');

    $request->getSession()->get('name');

    $request->getPathInfo();

    $request->getClientIp();

    Request::trustProxyData();

    Request

    GET /foo.html HTTP/1.1Host: example.com

    Response

  • 7/31/2019 Symfony2 Meets Drupal

    57/131

    Drupal 8 meets Symfony

    Response

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMTContent-Length: 14Content-Type: text/html

    Hello World!

    http://www.flickr.com/photos/splorp/64027565

    Response

    http://www.flickr.com/photos/splorp/64027565http://www.flickr.com/photos/splorp/64027565
  • 7/31/2019 Symfony2 Meets Drupal

    58/131

    Drupal 8 meets Symfony

    p

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMTContent-Length: 14Content-Type: text/html

    Hello World!

    header('HTTP/1.0 404 Not Found');

    header('Content-Type: text/html; charset=UTF-8');

    setcookie('name', $name);

    $_SESSION['name'] ='Fabien';echo'Hello '.$name;

    Response

  • 7/31/2019 Symfony2 Meets Drupal

    59/131

    Drupal 8 meets Symfony

    http://www.flickr.com/photos/viamoi/3338093351

    Low-level abstraction only

    Singleton like

    Does not play well with the CLI

    Not Object-Oriented

    p

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMTContent-Length: 14Content-Type: text/html

    Hello World!

    Response

    http://www.flickr.com/photos/viamoi/3338093351http://www.flickr.com/photos/viamoi/3338093351
  • 7/31/2019 Symfony2 Meets Drupal

    60/131

    Drupal 8 meets Symfony

    use Symfony\Component\HttpFoundation\Response;

    $response=newResponse('Not Found', 404, array('Content-Type'=>'text/plain'));$response=newResponse();

    $response->setContent('Hello World');

    $response->send();

    p

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMTContent-Length: 14Content-Type: text/html

    Hello World!

    Response

  • 7/31/2019 Symfony2 Meets Drupal

    61/131

    Drupal 8 meets Symfony

    use Symfony\Component\HttpFoundation\StreamedResponse;

    $response=newStreamedResponse(function () { echo'foo'; flush();

    echo'bar';});$response->send();

    p

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMTContent-Length: 14Content-Type: text/html

    Hello World!

    Response

  • 7/31/2019 Symfony2 Meets Drupal

    62/131

    Drupal 8 meets Symfony

    $headers=$response->headers;

    $headers->set( 'Content-Disposition', $headers->makeDisposition(

    ResponseHeaderBag::DISPOSITION_ATTACHMENT, 'foo.pdf'));

    p

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMTContent-Length: 14Content-Type: text/html

    Hello World!

    Response

  • 7/31/2019 Symfony2 Meets Drupal

    63/131

    Drupal 8 meets Symfony

    $response->prepare($request);

    p

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMTContent-Length: 14Content-Type: text/html

    Hello World!

  • 7/31/2019 Symfony2 Meets Drupal

    64/131

    Drupal 8 meets Symfony

    SessionManagement

    http://www.flickr.com/photos/tomvu/5371659662

    http://www.flickr.com/photos/tomvu/5371659662http://www.flickr.com/photos/tomvu/5371659662
  • 7/31/2019 Symfony2 Meets Drupal

    65/131

    Drupal 8 meets Symfony

    The Symfony HttpFoundation Componentdefines a feature-full object-oriented layer

    for the HTTP messages

    http://www.flickr.com/photos/ynaffitx/4667769355

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355
  • 7/31/2019 Symfony2 Meets Drupal

    66/131

    Drupal 8 meets Symfony

    It replaces PHP native global variables and functionsto allow writing better, more secure, and more testable code

    http://www.flickr.com/photos/ynaffitx/4667769355

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355
  • 7/31/2019 Symfony2 Meets Drupal

    67/131

    Drupal 8 meets Symfony

    Routing

  • 7/31/2019 Symfony2 Meets Drupal

    68/131

    Drupal 8 meets Symfony

    use Symfony\Component\Routing\Route;

    $route=newRoute('/node/{id}', array( '_controller'=>'SomeClass::someMethod'));

    use Symfony\Component\Routing\RouteCollection;

    $routes=newRouteCollection();

    $routes->add('node', $route);

    f \ \ i \

  • 7/31/2019 Symfony2 Meets Drupal

    69/131

    Drupal 8 meets Symfony

    use Symfony\Component\Routing\RequestContext;use Symfony\Component\Routing\Matcher\UrlMatcher;

    $matcher=newUrlMatcher($routes, newRequestContext());

    $attributes=$matcher->match('/node/12');$attributes=$matcher->match($request->getPathInfo());

    print_r($attributes);

    array( '_route' =>'node',

    'id' =>12, '_controller'=>'SomeClass::someMethod',);

  • 7/31/2019 Symfony2 Meets Drupal

    70/131

    Drupal 8 meets Symfony

    use Symfony\Component\Routing\Generator\UrlGenerator;

    $generator=newUrlGenerator($routes, $context);

    echo$generator->generate('node', array('id'=>12));

  • 7/31/2019 Symfony2 Meets Drupal

    71/131

    Drupal 8 meets Symfony

    The Symfony Routing Componentdecouples the look of URLs

    from the code that handle them

    http://www.flickr.com/photos/ynaffitx/4667769355

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355
  • 7/31/2019 Symfony2 Meets Drupal

    72/131

    Drupal 8 meets Symfony

    EventDispatcher

  • 7/31/2019 Symfony2 Meets Drupal

    73/131

    Drupal 8 meets Symfony

    use Symfony\Component\EventDispatcher\EventDispatcher;

    $dispatcher=newEventDispatcher();

    $callable=function (Event$event) { // do something

    };$dispatcher->addListener('event_name', $callable);

    $dispatcher->dispatch('event_name', newEvent());

  • 7/31/2019 Symfony2 Meets Drupal

    74/131

    Drupal 8 meets Symfony

    The Symfony EventDispatcher Componentimplements a lightweight version

    of the Observer design pattern

    http://www.flickr.com/photos/ynaffitx/4667769355

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355
  • 7/31/2019 Symfony2 Meets Drupal

    75/131

    Drupal 8 meets Symfony

    HttpKernel

  • 7/31/2019 Symfony2 Meets Drupal

    76/131

    Drupal 8 meets Symfony

    Request Response

    HTTP/1.1 200 OKDate: Wed, 15 Oct 2005 07:07:07 GMTContent-Length: 14Content-Type: text/html

    Hello World!

    GET /foo.html HTTP/1.1Host: example.com

    http://www.flickr.com/photos/-bast-/349497988

    The web in action

    http://www.flickr.com/photos/-bast-/349497988http://www.flickr.com/photos/-bast-/349497988http://www.flickr.com/photos/-bast-/349497988
  • 7/31/2019 Symfony2 Meets Drupal

    77/131

    Drupal 8 meets Symfony

    The web in action

    The User asks for a Resource in a BrowserThe Browser sends a Request to the Server

    Symfony gives the Developer a Request Object

    The Developerconverts the Request Object to a Response Object

    The Server sends back a Response to the Browser

    The Browser displays the Resource to the User

  • 7/31/2019 Symfony2 Meets Drupal

    78/131

    Drupal 8 meets Symfony

    namespace Symfony\Component\HttpKernel;

    interface HttpKernelInterface{ /**

    * @return Response A Response instance*/

    functionhandle(Request$request, $type=self::MASTER_REQUEST, $catch=true);}

  • 7/31/2019 Symfony2 Meets Drupal

    79/131

    Drupal 8 meets Symfony

    Request ResponseWorkflow

  • 7/31/2019 Symfony2 Meets Drupal

    80/131

    Drupal 8 meets Symfony

    Request request

  • 7/31/2019 Symfony2 Meets Drupal

    81/131

    Drupal 8 meets Symfony

    Request Responseresponse

    response?

    request

  • 7/31/2019 Symfony2 Meets Drupal

    82/131

    Drupal 8 meets Symfony

    Request resolvecontrollerrequest

  • 7/31/2019 Symfony2 Meets Drupal

    83/131

    Drupal 8 meets Symfony

    namespace Symfony\Component\HttpKernel\Controller;

    interface ControllerResolverInterface{

    functiongetController(Request$request);

    functiongetArguments(Request$request, $controller);}

  • 7/31/2019 Symfony2 Meets Drupal

    84/131

    Drupal 8 meets Symfony

    Request controllerresolvecontrollerrequest

  • 7/31/2019 Symfony2 Meets Drupal

    85/131

    Drupal 8 meets Symfony

    Request controllerresolvecontrollerresolve

    argumentsrequest

  • 7/31/2019 Symfony2 Meets Drupal

    86/131

    Drupal 8 meets Symfony

    RequestCall

    Controllercontrollerresolve

    controllerresolve

    argumentsrequest

  • 7/31/2019 Symfony2 Meets Drupal

    87/131

    Drupal 8 meets Symfony

    Request ResponseresponseCall

    Controllercontrollerresolve

    controllerresolve

    argumentsrequest

  • 7/31/2019 Symfony2 Meets Drupal

    88/131

    Drupal 8 meets Symfony

    Request ResponseresponseCall

    Controllercontroller

    view

    resolvecontroller

    resolveargumentsrequest

  • 7/31/2019 Symfony2 Meets Drupal

    89/131

    Drupal 8 meets Symfony

    Request Responseresponse

    expection

    exception

  • 7/31/2019 Symfony2 Meets Drupal

    90/131

    Drupal 8 meets Symfony

    Request Response

    terminate

  • 7/31/2019 Symfony2 Meets Drupal

    91/131

    Drupal 8 meets Symfony

    CallController

    Sub-Request

    request

    sub-response content

  • 7/31/2019 Symfony2 Meets Drupal

    92/131

    Drupal 8 meets Symfony

    Request ResponseresponseCall

    Controller

    response?

    expectionSub-Request

    terminate

    controller

    view

    resolvecontroller

    resolveargumentsrequest

    exceptionsub-response content

    $ t R t C ll ti ()

  • 7/31/2019 Symfony2 Meets Drupal

    93/131

    Drupal 8 meets Symfony

    $routes=newRouteCollection();$routes->add('hello', newRoute('/hello', array('_controller'=> function (Request$request) {

    returnnewResponse(sprintf("Hello %s", $request->get('name')));})));

    $request=Request::createFromGlobals();

    $matcher=newUrlMatcher($routes, newRequestContext());

    $dispatcher=newEventDispatcher();$dispatcher->addSubscriber(newRouterListener($matcher));

    $resolver=newControllerResolver();$kernel=newHttpKernel($dispatcher, $resolver);$kernel->handle($request)->send();

  • 7/31/2019 Symfony2 Meets Drupal

    94/131

    Drupal 8 meets Symfony

    Symfonybuilt-inlisteners

    http://www.flickr.com/photos/c_r_i_s/67306260

    http://www.flickr.com/photos/c_r_i_s/67306260http://www.flickr.com/photos/c_r_i_s/67306260
  • 7/31/2019 Symfony2 Meets Drupal

    95/131

    Drupal 8 meets Symfony

    $handler=function ($exception) {returnnewResponse($exception->getMessage(), 500);

    });

    $dispatcher->addSubscriber(newExceptionListener($handler));

  • 7/31/2019 Symfony2 Meets Drupal

    96/131

    Drupal 8 meets Symfony

    $handler=function ($exception) { $handler=newExceptionHandler();

    return$handler->createResponse($exception);

    });

    $dispatcher->addSubscriber(newExceptionListener($handler));

  • 7/31/2019 Symfony2 Meets Drupal

    97/131

    Drupal 8 meets Symfony

  • 7/31/2019 Symfony2 Meets Drupal

    98/131

    Drupal 8 meets Symfony

    The default HttpKernel implementationmakes Drupal interoperable with

    any other software using the same

    http://www.flickr.com/photos/ynaffitx/4667769355

    HTTP

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355
  • 7/31/2019 Symfony2 Meets Drupal

    99/131

    Drupal 8 meets Symfony

    http://www.flickr.com/photos/cmogle/2947179118

    HTTP

    Testing

    http://www.flickr.com/photos/cmogle/2947179118http://www.flickr.com/photos/cmogle/2947179118
  • 7/31/2019 Symfony2 Meets Drupal

    100/131

    Drupal 8 meets Symfony

    use Symfony\Component\HttpKernel\Client;

    $client=newClient($kernel);

    $client->request('GET', '/hello/Fabien');

    $response=$client->getResponse();

    $this->assertEquals(200, $response->getStatusCode());

  • 7/31/2019 Symfony2 Meets Drupal

    101/131

    Drupal 8 meets Symfony

    use Symfony\Component\HttpKernel\Client;

    $client=newClient($kernel);

    $crawler=$client->request('GET', '/hello/Fabien');

    $nodes=$crawler->filter('h1:contains("Fabien")');

    $this->assertCount(1, $nodes);

    HTTP

  • 7/31/2019 Symfony2 Meets Drupal

    102/131

    http://www.flickr.com/photos/laserstars/908946494 Drupal 8 meets Symfony

    Caching

    Expiration

  • 7/31/2019 Symfony2 Meets Drupal

    103/131

    Expiration

    Cache-Control

    Expires

    Validation

  • 7/31/2019 Symfony2 Meets Drupal

    104/131

    Validation

    Last-ModifiedIf-Modified-Since

    ETagIf-None-Match

  • 7/31/2019 Symfony2 Meets Drupal

    105/131

    Drupal 8 meets Symfony

    $response->setTtl(10);$response->setClientTtl(10);

    // get the last modified date as fast as you can

  • 7/31/2019 Symfony2 Meets Drupal

    106/131

    Drupal 8 meets Symfony

    // get the last modified date as fast as you can$lastModified=...;

    $response=newResponse();$response->setLastModified($lastModified);

    if ($response->isNotModified($request)) {

    return$response;}

    // do the expensive work$response->setContent(...);

    return$response;

  • 7/31/2019 Symfony2 Meets Drupal

    107/131

    Drupal 8 meets Symfony

    Expiration

    wins overValidation

    http://www.flickr.com/photos/hoyvinmayvin/4672922637

    http://www.flickr.com/photos/hoyvinmayvin/4672922637http://www.flickr.com/photos/hoyvinmayvin/4672922637
  • 7/31/2019 Symfony2 Meets Drupal

    108/131

    Drupal 8 meets Symfony

    $kernel=newHttpKernel($dispatcher, $resolver);

    $kernel=newHttpCache($kernel, newStore($cacheDir));

    Varnish

  • 7/31/2019 Symfony2 Meets Drupal

    109/131

    Drupal 8 meets Symfony

    Varnish

    The HTTPaccelerator

    http://www.flickr.com/photos/stuckincustoms/3232133635

    http://www.flickr.com/photos/stuckincustoms/3232133635http://www.flickr.com/photos/stuckincustoms/3232133635
  • 7/31/2019 Symfony2 Meets Drupal

    110/131

    Drupal 8 meets Symfony

    Using the default HttpKernelallows Drupal to benefit from

    the many built-in features

    http://www.flickr.com/photos/ynaffitx/4667769355

    Edge

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355
  • 7/31/2019 Symfony2 Meets Drupal

    111/131

    Drupal 8 meets Symfony

    g

    SideIncludes

    ESI

    http://www.w3.org/TR/esi-lang

    h"p://www.flickr.com/photos/bored-now/2264811719

    http://www.flickr.com/photos/bored-now/2264811719http://www.flickr.com/photos/bored-now/2264811719http://www.w3.org/TR/esi-langhttp://www.w3.org/TR/esi-lang
  • 7/31/2019 Symfony2 Meets Drupal

    112/131

    Drupal 8 meets Symfony

  • 7/31/2019 Symfony2 Meets Drupal

    113/131

    Drupal 8 meets Symfony

    HTTP Validation

  • 7/31/2019 Symfony2 Meets Drupal

    114/131

    Drupal 8 meets Symfony

    HTTP Expiration

    HTTP Validation

  • 7/31/2019 Symfony2 Meets Drupal

    115/131

    Drupal 8 meets Symfony

    HTTP Expiration

  • 7/31/2019 Symfony2 Meets Drupal

    116/131

    Drupal 8 meets Symfony

  • 7/31/2019 Symfony2 Meets Drupal

    117/131

    Drupal 8 meets Symfony

    CallController

    Sub-Request

    request

    sub-response content

    HTTP Expiration

  • 7/31/2019 Symfony2 Meets Drupal

    118/131

    Drupal 8 meets Symfony

    GET /foo HTTP/1.1Host: foo.org

    GET /foo HTTP/1.1Host: foo.org

  • 7/31/2019 Symfony2 Meets Drupal

    119/131

    GET /bar HTTP/1.1Host: foo.org

    Lorem

    ipsum

    dolor

    HTTP/1.1 200 OKC-C: s-maxage=600

    Loremipsum

    dolor

    HTTP/1.1 200 OKC-C: s-maxage=5

    Loremipsum

    dolorsitamet,

    Lorem

    ipsum

    dolor

    HTTP/1.1 200 OK

    GET /fooC-C: s-maxage=600

    Lor

    GET /barC-C: s-maxage=5

    Lorem

    GET /foo HTTP/1.1Host: foo.org

  • 7/31/2019 Symfony2 Meets Drupal

    120/131

    Loremipsum

    dolorsitamet,

    Lorem

    ipsum

    dolor

    HTTP/1.1 200 OK

    GET /fooC-C: s-maxage=600

    Lor

    GET /barC-C: s-maxage=5

    Lorem

    GET /foo HTTP/1.1Host: foo.org

  • 7/31/2019 Symfony2 Meets Drupal

    121/131

    GET /bar HTTP/1.1Host: foo.org

    Loremipsum

    dolor

    HTTP/1.1 200 OKC-C: s-maxage=5

    Loremipsum

    dolorsitamet,

    Lorem

    ipsum

    dolor

    HTTP/1.1 200 OK

    GET /fooC-C: s-maxage=600

    Lor

    GET /barC-C: s-maxage=5

    Lorem

  • 7/31/2019 Symfony2 Meets Drupal

    122/131

    Drupal 8 meets Symfony

    $kernel=newHttpCache( $kernel, newStore($cacheDir),

    newEsi());

    Varnish

  • 7/31/2019 Symfony2 Meets Drupal

    123/131

    Drupal 8 meets Symfony

    http://www.flickr.com/photos/stuckincustoms/3232133635

    Varnish

    The HTTPaccelerator

    http://www.flickr.com/photos/stuckincustoms/3232133635http://www.flickr.com/photos/stuckincustoms/3232133635
  • 7/31/2019 Symfony2 Meets Drupal

    124/131

    Drupal 8 meets Symfony

    The Symfony HttpKernel Componentprovides the building blocks

    to create flexible, extensible, and scalable

    HTTP-based frameworks

    http://www.flickr.com/photos/ynaffitx/4667769355

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355
  • 7/31/2019 Symfony2 Meets Drupal

    125/131

    Drupal 8 meets Symfony

    The Symfony HttpKernel Componentleverages the HTTP specification

    to make integration between projects easy

    http://www.flickr.com/photos/ynaffitx/4667769355

    http://symfony.com/components

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355http://symfony.com/componentshttp://symfony.com/components
  • 7/31/2019 Symfony2 Meets Drupal

    126/131

    Drupal 8 meets Symfony

    DependencyInjectionEventDispatcher

    HttpFoundation

    DomCrawler

    ClassLoader

    CssSelector

    HttpKernel

    BrowserKit TemplatingTranslation

    Filesystem

    Serializer

    ValidatorSecurity

    Routing

    ConsoleProcess

    Config

    Finder

    Locale

    Yaml

    Formhttp://www.flickr.com/photos/ecstaticist/3860865429

    Silex

    http://www.flickr.com/photos/ecstaticist/3860865429http://www.flickr.com/photos/ecstaticist/3860865429
  • 7/31/2019 Symfony2 Meets Drupal

    127/131

    Drupal 8 meets Symfony

    Silex

    https://github.com/fabpot/Silexhttp://silex.sensiolabs.org/http://www.flickr.com/photos/linhngan/2715287035

    Build your own

    http://www.flickr.com/photos/linhngan/2715287035http://www.flickr.com/photos/linhngan/2715287035https://github.com/fabpot/Silexhttps://github.com/fabpot/Silex
  • 7/31/2019 Symfony2 Meets Drupal

    128/131

    Drupal 8 meets Symfony

    http://fabien.potencier.org/build-a-framework

    y

    framework

    http://www.flickr.com/photos/linhngan/2715287035

    http://www.flickr.com/photos/linhngan/2715287035http://www.flickr.com/photos/linhngan/2715287035http://fabien.potencier.org/build-a-frameworkhttp://fabien.potencier.org/build-a-framework
  • 7/31/2019 Symfony2 Meets Drupal

    129/131

    Drupal 8 meets Symfony

    http://live.symfony.com/

    http://live.symfony.com/http://live.symfony.com/
  • 7/31/2019 Symfony2 Meets Drupal

    130/131

    Drupal 8 meets Symfony

    The Symfony Components provides the low-levelbuilding blocks that you need to build a web product

    so that YOU can focus on what matters most for Drupal

    http://www.flickr.com/photos/ynaffitx/4667769355

    @fabpot@l ith

    http://www.flickr.com/photos/ynaffitx/4667769355http://www.flickr.com/photos/ynaffitx/4667769355
  • 7/31/2019 Symfony2 Meets Drupal

    131/131

    @lsmith