Beruflich Dokumente
Kultur Dokumente
http://www.flickr.com/photos/nimport_nawak/3404931191
Fabien Potencier
@fabpot fabien@symfony.com
Works for in Switzerland PHP 5.3 Release Manager Co-lead of PHPCR Symfony2 core contributor
PHP developers?
http://www.flickr.com/photos/dunechaser/160405823
Symfony aware?
http://www.flickr.com/photos/dunechaser/142079357
We have a rough understanding of the hook paradigm aka the Drupal way
http://www.flickr.com/photos/pictureperfectpose/76138988
A sad realization
It would take a long time for us to be productive in Drupal let alone work on the core And everything we learn along the way would only help us with Drupal
What others do
Building on top of long established OO design patterns Leverage new PHP language features and performance improvements Share code!
So Drupal is wrong?
No, the question is just if the benefits of doing things differently outweigh the disadvantages
How to collaborate?
Symfony2 is MIT licensed which is GPL compatible Symfony2 development is very transparently managed on github.com We want to ensure Symfony2 works for Drupal, phpBB, etc.
Drupal 8 meets Symfony
Symfony?
What is
http://www.flickr.com/photos/apranihita/141159146/
http://www.flickr.com/photos/bigpinkcookie/22716359
is... ... a reusable set of standalone, decoupled, and cohesive PHP components that solve common web development problems
http://www.flickr.com/photos/krislitman/493626935
is... ... an Object-Oriented set of classes ... compatible with PHP 5.3 and later
http://www.flickr.com/photos/krislitman/493626935
Config
ClassLoader
Finder
Process
Console
Filesystem
EventDispatcher
BrowserKit CssSelector DomCrawler
DependencyInjection
Translation Form
http://www.flickr.com/photos/krislitman/493626935
Components
http://www.flickr.com/photos/maistora/3014414972
PPI 2 - a framework
ClassLoader, HttpFoundation, Routing, Templating
http://www.flickr.com/photos/c_r_i_s/77763712
What about
Drupal 8?
http://www.flickr.com/photos/aloshbennett/619307160
Config
ClassLoader
Finder
Process
Console
Filesystem
EventDispatcher
BrowserKit CssSelector DomCrawler
DependencyInjection
Translation Form
Config
ClassLoader
Finder
Process
Console
Filesystem
EventDispatcher
BrowserKit CssSelector DomCrawler
DependencyInjection
Translation Form
Using the
Symfony
Components
http://www.flickr.com/photos/35168673@N03/6086229920
Git
$ $ $ $
Archives
PEAR
Composer
composer.json { "require": { "symfony/console": "2.1.*", "symfony/http-foundation": "v2.0.9" } } curl -s http://getcomposer.org/installer | php php composer.phar install
Symfony Components
ClassLoader
http://symfony.com/PSR0
require_once __DIR__.'/src/Symfony/Component/ ClassLoader/UniversalClassLoader.php'; use Symfony\Component\ClassLoader\UniversalClassLoader; $loader = new UniversalClassLoader(); $loader->registerNamespaces(array( 'Symfony' => __DIR__.'/vendor/symfony/src', )); $loader->register();
The Symfony ClassLoader Component loads your project classes automatically if they follow some standard conventions
http://www.flickr.com/photos/ynaffitx/4667769355
HttpFoundation
HTTP
HTTP/1.1 RFC 2616
http://www.ietf.org/rfc/rfc2616.txt http://tools.ietf.org/wg/httpbis/
http://www.flickr.com/photos/deniscollette/6741424757
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.1 Host: example.com
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 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-Type: text/html Hello World!
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 The Browser displays the Resource to the User
Client
Request
GET /foo.html HTTP/1.1 Host: example.com
HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-Type: text/html Hello World!
Request
http://www.flickr.com/photos/splorp/64027565
Request
GET /foo.html HTTP/1.1 Host: example.com
session_start(); $name = $_GET['name']; // $_POST, $_FILE, $_COOKIE, ... echo $_SESSION['name']; $method = $_SERVER['REQUEST_METHOD'];
Request
GET /foo.html HTTP/1.1 Host: example.com
$clientIp = $_SERVER['REMOTE_ADDR'];
Request
GET /foo.html HTTP/1.1 Host: example.com
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); return isset($ips[0]) ? trim($ips[0]) : ''; } return $_SERVER['REMOTE_ADDR'];
Request
GET /foo.html HTTP/1.1 Host: example.com
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); return isset($ips[0]) ? trim($ips[0]) : ''; } } return $_SERVER['REMOTE_ADDR'];
Drupal 8 meets Symfony
Request
http://www.flickr.com/photos/viamoi/3338093351
Request
GET /foo.html HTTP/1.1 Host: example.com
Request
GET /foo.html HTTP/1.1 Host: example.com
Response
HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-Type: text/html Hello World!
http://www.flickr.com/photos/splorp/64027565
Response
HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-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
HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-Type: text/html
Singleton like Low-level abstraction only Does not play well with the CLI Not Object-Oriented
Hello World!
http://www.flickr.com/photos/viamoi/3338093351
Response
HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-Type: text/html Hello World!
use Symfony\Component\HttpFoundation\Response; $response = new Response('Not Found', 404, array('Content-Type' => 'text/plain')); $response = new Response(); $response->setContent('Hello World'); $response->send();
Response
HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-Type: text/html Hello World!
use Symfony\Component\HttpFoundation\StreamedResponse; $response = new StreamedResponse(function () { echo 'foo'; flush(); echo 'bar'; }); $response->send();
Response
HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-Type: text/html Hello World!
Response
HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-Type: text/html Hello World!
$response->prepare($request);
Session Management
http://www.flickr.com/photos/tomvu/5371659662
The Symfony HttpFoundation Component defines a feature-full object-oriented layer for the HTTP messages
http://www.flickr.com/photos/ynaffitx/4667769355
It replaces PHP native global variables and functions to allow writing better, more secure, and more testable code
http://www.flickr.com/photos/ynaffitx/4667769355
Routing
use Symfony\Component\Routing\Route; $route = new Route('/node/{id}', array( '_controller' => 'SomeClass::someMethod' )); use Symfony\Component\Routing\RouteCollection; $routes = new RouteCollection(); $routes->add('node', $route);
use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Matcher\UrlMatcher; $matcher = new UrlMatcher($routes, new RequestContext()); $attributes = $matcher->match('/node/12'); $attributes = $matcher->match($request->getPathInfo()); print_r($attributes); array( '_route' => 'node', 'id' => 12, '_controller' => 'SomeClass::someMethod', );
Drupal 8 meets Symfony
use Symfony\Component\Routing\Generator\UrlGenerator; $generator = new UrlGenerator($routes, $context); echo $generator->generate('node', array('id' => 12));
The Symfony Routing Component decouples the look of URLs from the code that handle them
http://www.flickr.com/photos/ynaffitx/4667769355
EventDispatcher
use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $callable = function (Event $event) { // do something }; $dispatcher->addListener('event_name', $callable);
The Symfony EventDispatcher Component implements a lightweight version of the Observer design pattern
http://www.flickr.com/photos/ynaffitx/4667769355
HttpKernel
Request
GET /foo.html HTTP/1.1 Host: example.com
Response
HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Content-Length: 14 Content-Type: text/html Hello World!
http://www.flickr.com/photos/-bast-/349497988
Symfony gives the Developer a Request Object The Developer converts the Request Object to a Response Object
The Server sends back a Response to the Browser The Browser displays the Resource to the User
namespace Symfony\Component\HttpKernel; interface HttpKernelInterface { /** * @return Response A Response instance */ function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true); }
Request
request
resolve controller
controller
Workflow
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
namespace Symfony\Component\HttpKernel\Controller; interface ControllerResolverInterface { function getController(Request $request); function getArguments(Request $request, $controller); }
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
$routes = new RouteCollection(); $routes->add('hello', new Route('/hello', array('_controller' => function (Request $request) { return new Response(sprintf("Hello %s", $request->get('name'))); } ))); $request = Request::createFromGlobals(); $matcher = new UrlMatcher($routes, new RequestContext()); $dispatcher = new EventDispatcher(); $dispatcher->addSubscriber(new RouterListener($matcher)); $resolver = new ControllerResolver(); $kernel = new HttpKernel($dispatcher, $resolver); $kernel->handle($request)->send();
Symfony
built-in
listeners
http://www.flickr.com/photos/c_r_i_s/67306260
$handler = function ($exception) { return new Response($exception->getMessage(), 500); }); $dispatcher->addSubscriber(new ExceptionListener($handler));
$handler = function ($exception) { $handler = new ExceptionHandler(); return $handler->createResponse($exception); }); $dispatcher->addSubscriber(new ExceptionListener($handler));
The default HttpKernel implementation makes Drupal interoperable with any other software using the same
http://www.flickr.com/photos/ynaffitx/4667769355
HTTP
Testing
http://www.flickr.com/photos/cmogle/2947179118
use Symfony\Component\HttpKernel\Client; $client = new Client($kernel); $client->request('GET', '/hello/Fabien'); $response = $client->getResponse(); $this->assertEquals(200, $response->getStatusCode());
use Symfony\Component\HttpKernel\Client; $client = new Client($kernel); $crawler = $client->request('GET', '/hello/Fabien'); $nodes = $crawler->filter('h1:contains("Fabien")'); $this->assertCount(1, $nodes);
Caching
HTTP
http://www.flickr.com/photos/laserstars/908946494
Expiration
Cache-Control Expires
Validation
Last-Modified If-Modified-Since ETag If-None-Match
$response->setTtl(10); $response->setClientTtl(10);
// get the last modified date as fast as you can $lastModified = ...; $response = new Response(); $response->setLastModified($lastModified); if ($response->isNotModified($request)) { return $response; } // do the expensive work $response->setContent(...); return $response;
http://www.flickr.com/photos/hoyvinmayvin/4672922637
Varnish
accelerator
The HTTP
http://www.flickr.com/photos/stuckincustoms/3232133635
Using the default HttpKernel allows Drupal to benefit from the many built-in features
http://www.flickr.com/photos/ynaffitx/4667769355
Edge
Side
Includes
http://www.w3.org/TR/esi-lang
ESI
h"p://www.ickr.com/photos/bored-now/2264811719
HTTP Validation
Request
request
resolve controller
controller
resolve arguments
Call Controller
response
Response
view
terminate
response?
HTTP Expiration
Browser
HTTP/1.1 200 OK
Lorem
ipsum
Lorem
dolor
sit
amet,
ipsum
dolor
GET /bar C-C: s-maxage=5 Lorem GET /foo C-C: s-maxage=600 Lor <esi:include />
HTTP/1.1 200 OK
Lorem
ipsum
Lorem
dolor
sit
amet,
ipsum
dolor
GET /bar C-C: s-maxage=5 Lorem GET /foo C-C: s-maxage=600 Lor <esi:include />
before exp.
Browser
Browser
HTTP/1.1 200 OK
Lorem
ipsum
Lorem
dolor
sit
amet,
ipsum
dolor
GET /bar C-C: s-maxage=5 Lorem GET /foo C-C: s-maxage=600 Lor <esi:include />
after exp.
Varnish
accelerator
The HTTP
http://www.flickr.com/photos/stuckincustoms/3232133635
The Symfony HttpKernel Component provides the building blocks to create flexible, extensible, and scalable HTTP-based frameworks
http://www.flickr.com/photos/ynaffitx/4667769355
The Symfony HttpKernel Component leverages the HTTP specification to make integration between projects easy
http://www.flickr.com/photos/ynaffitx/4667769355
http://symfony.com/components
Config
ClassLoader
Finder
Process
Console
Filesystem
EventDispatcher
BrowserKit CssSelector DomCrawler
DependencyInjection
Translation Form
http://www.flickr.com/photos/ecstaticist/3860865429
Silex
https://github.com/fabpot/Silex http://silex.sensiolabs.org/
http://www.flickr.com/photos/linhngan/2715287035
framework
http://fabien.potencier.org/build-a-framework
http://www.flickr.com/photos/linhngan/2715287035
http://live.symfony.com/
The Symfony Components provides the low-level building 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 @lsmith
http://www.flickr.com/photos/stevendepolo/4582437563