127
Symfony2 Fabien Potencier

Symfony2 - WebExpo 2010

Embed Size (px)

Citation preview

Page 1: Symfony2 - WebExpo 2010

Symfony2 Fabien Potencier

Page 2: Symfony2 - WebExpo 2010

How many of you have already used symfony1?

Page 3: Symfony2 - WebExpo 2010

How many of you have already played with Symfony2?

Page 4: Symfony2 - WebExpo 2010

What is Symfony2?

Page 5: Symfony2 - WebExpo 2010

A set of decoupled and cohesive components

Page 6: Symfony2 - WebExpo 2010

DependencyInjection EventDispatcher HttpFoundation OutputEscaper

DomCrawler CssSelector Templating HttpKernel BrowserKit Validator Routing Console Process Finder Form Yaml

Page 7: Symfony2 - WebExpo 2010

git clone git://github.com/symfony/symfony.git

Page 8: Symfony2 - WebExpo 2010

A set of decoupled and cohesive components

Autoloading

Page 9: Symfony2 - WebExpo 2010

PEAR_Log > PEAR/Log.php Zend_Log > Zend/Log.php

Swift_Mime_Message > Swift/Mime/Message.php Twig_Node_For > Twig/Node/For.php

Page 10: Symfony2 - WebExpo 2010

Symfony\Foundation\Kernel Symfony/Foundation/Kernel.php

Doctrine\DBAL\Driver Doctrine/DBAL/Driver.php

pdepend\reflection\ReflectionSession pdepend/reflection/ReflectionSession.php

http://groups.google.com/group/php-standards/web/psr-0-final-proposal  

Page 11: Symfony2 - WebExpo 2010

require_once '.../Symfony/Framework/UniversalClassLoader.php';

use Symfony\Framework\UniversalClassLoader;

$loader = new UniversalClassLoader(); $loader->register();

Page 12: Symfony2 - WebExpo 2010

PHP 5.3 technical interoperability standards

$loader->registerNamespaces(array( 'Symfony' => '/path/to/symfony/src', 'Doctrine' => '/path/to/doctrine/lib', 'pdepend' => '/path/to/reflection/source', ));

Page 13: Symfony2 - WebExpo 2010

$loader->registerPrefixes(array( 'Swift_' => '/path/to/swiftmailer/lib/classes', 'Zend_' => '/path/to/vendor/zend/library', ));

PEAR style

Page 14: Symfony2 - WebExpo 2010

A set of decoupled and cohesive components

Process

Page 15: Symfony2 - WebExpo 2010

use Symfony\Component\Process\Process;

$cmd = 'ssh 1.2.3.4 "ps waux"';

$process = new Process($cmd); $process->run();

if (!$process->isSuccessful()) { throw new \RuntimeException( $process->getErrorOutput()); }

echo $process->getOutput();

Page 16: Symfony2 - WebExpo 2010

$cmd = 'ssh 1.2.3.4 "tail -f /some/log"';

$process = new Process($cmd);

$process->run(function ($type, $buffer) { echo $buffer; });

Page 17: Symfony2 - WebExpo 2010

use Symfony\Component\Process\PhpProcess;

$process = new PhpProcess( '<?php echo "hello"; ?>'); $process->run();

if (!$process->isSuccessful()) { throw new \RuntimeException( $process->getErrorOutput()); }

echo $process->getOutput();

Page 18: Symfony2 - WebExpo 2010

A set of decoupled and cohesive components

CssSelector

Page 19: Symfony2 - WebExpo 2010

use Symfony\Component\CssSelector\Parser;

Parser::cssToXpath('h4 > a:contains("foo")');

Page 20: Symfony2 - WebExpo 2010

use Symfony\Component\CssSelector\Parser;

$document = new \DOMDocument(); $document->loadHTMLFile('...'); $xpath = new \DOMXPath($document);

$expr = Parser::cssToXpath('a.smart'); $nodes = $xpath->query($expr);

foreach ($nodes as $node) { printf("%s (%s)\n", $node->nodeValue, $node->getAttribute('href')); }

Page 21: Symfony2 - WebExpo 2010

A set of decoupled and cohesive components

Finder

Page 22: Symfony2 - WebExpo 2010

use Symfony\Component\Finder\Finder;

$finder = new Finder(); $finder ->files() ->in(__DIR__) ->...() ->sortByName() ;

Page 23: Symfony2 - WebExpo 2010

$finder ->name('*.php') ->depth('<= 1') ->date('>= yesterday') ->size('<= 1K') ->filter(function (\SplFileInfo $file) { return strlen($file->getBasename()) < 9; }) ;

Page 24: Symfony2 - WebExpo 2010

foreach ($finder as $file) { print $file->getRealpath()."\n"; }

$files = iterator_to_array($finder);

$count = iterator_count($finder);

Page 25: Symfony2 - WebExpo 2010

use Symfony\Component\Finder\Finder;

$s3 = new \Zend_Service_Amazon_S3($key, $sct); $s3->registerStreamWrapper("s3");

$finder = new Finder(); $finder ->name('photos*') ->size('< 100K') ->date('since 1 hour ago') ->in('s3://bucket-name') ;

Page 26: Symfony2 - WebExpo 2010

A set of decoupled and cohesive components

Routing

Page 27: Symfony2 - WebExpo 2010

/blog.php?section=symfony&article_id=18475

Page 28: Symfony2 - WebExpo 2010

web/ index.php

Page 29: Symfony2 - WebExpo 2010

/index.php/blog/2010/09/18/Symfony2-in-India

Page 30: Symfony2 - WebExpo 2010

/blog/2010/09/18/Symfony2-in-India

Page 31: Symfony2 - WebExpo 2010

/blog/:year/:month/:day/:slug

Page 32: Symfony2 - WebExpo 2010

post: pattern: /blog/:year/:month/:day/:slug defaults: { _controller: BlogBundle:Post:show }

Page 33: Symfony2 - WebExpo 2010

<routes> <route id="post" pattern="/blog/:year/:month/:day/:slug"> <default key="_controller"> BlogBundle:Post:show </default> </route> </routes>

Page 34: Symfony2 - WebExpo 2010

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route;

$collection = new RouteCollection();

$route = new Route( '/blog/:year/:month/:day/:slug', array('_controller' => 'BlogBundle:Post:show'));

$collection->addRoute('post', $route);

return $collection;

Page 35: Symfony2 - WebExpo 2010

$router ->match('/blog/2010/09/18/Symfony2-in-India')

$router ->generate('post', array('slug' => '...'))

Page 36: Symfony2 - WebExpo 2010

post: pattern: /post/:slug defaults: { _controller: BlogBundle:Post:show }

Page 37: Symfony2 - WebExpo 2010

$router ->generate('post', array('slug' => '...'))

Page 38: Symfony2 - WebExpo 2010

An Object-Oriented abstraction on top of PHP

Page 39: Symfony2 - WebExpo 2010

An Object-Oriented abstraction on top of PHP

Request

Page 40: Symfony2 - WebExpo 2010

use Symfony\Component\HttpFoundation\Request;

$request = new Request();

// get a $_GET parameter $request->query->get('page');

// get a $_POST parameter $request->request->get('page');

// get a $_COOKIE parameter $request->cookies->get('name');

$request->getPreferredLanguage(array('en', 'fr')); $request->isXmlHttpRequest();

Page 41: Symfony2 - WebExpo 2010

// get a $_FILE parameter $f = $request->files->get('image');

// $f is an instance of // Symfony\Component\HttpFoundation\File\UploadedFile

// guess extension, based on the mime type $n = '/path/to/file'.$file->getDefaultExtension(); $f->move($n);

Page 42: Symfony2 - WebExpo 2010

new Request();

new Request( $_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER );

Request::create('/hello/Fabien', 'GET');

Page 43: Symfony2 - WebExpo 2010

An Object-Oriented abstraction on top of PHP

Session

Page 44: Symfony2 - WebExpo 2010

$session = $request->getSession();

$session->set('foo', 'bar'); $session->get('foo');

$session->setFlash('notice', 'Congratulations!');

Page 45: Symfony2 - WebExpo 2010

An Object-Oriented abstraction on top of PHP

Response

Page 46: Symfony2 - WebExpo 2010

use Symfony\Component\HttpFoundation\Response;

$response = new Response('Hello World', 200, array('Content-Type' => 'text/plain')); $response->send();

$response->setHeader('Content-Type', 'text/plain'); $response->setCookie('foo', 'bar'); $response->setContent('Hello World'); $response->setStatusCode(200);

Page 47: Symfony2 - WebExpo 2010

An Object-Oriented abstraction of the HTTP dialog

Page 48: Symfony2 - WebExpo 2010

A MVC Web Framework

Page 49: Symfony2 - WebExpo 2010

The Symfony2 MVC Philosophy

Page 50: Symfony2 - WebExpo 2010

Be as easy as possible for newcomers and as flexible as possible for advanced users

Page 51: Symfony2 - WebExpo 2010

MVC

Page 52: Symfony2 - WebExpo 2010

http://symfony-reloaded.org/

http://symfony-reloaded.org/downloads/sandbox_2_0_PR3.zip

Page 53: Symfony2 - WebExpo 2010

post: pattern: /hello/:name defaults: { _controller: HelloBundle:Hello:index }

namespace Application\HelloBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller;

class HelloController extends Controller { public function indexAction($name) { return new Response('Hello '.$name); } }

Page 54: Symfony2 - WebExpo 2010

namespace Application\HelloBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller;

class HelloController extends Controller { public function indexAction($name) { // Get things from the Model

return $this->render( 'HelloBundle:Hello:index', array('name' => $name) ); } }

Page 55: Symfony2 - WebExpo 2010

Hello <?php echo $name ?>!

Page 56: Symfony2 - WebExpo 2010

<?php $view->extend('HelloBundle::layout') ?>

Hello <?php echo $name ?>!

Page 57: Symfony2 - WebExpo 2010

<html> <head> <title> <?php $view['slots']->output('title') ?> </title> </head> <body> <?php $view['slots']->output('_content') ?> </body> </html>

Page 58: Symfony2 - WebExpo 2010

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus,  in  pulvinar  lectus  rutrum  sit  amet.  Duis  gravida,  metus  in  dictum  eleifend,  dolor  risus  ;ncidunt  ligula,  non  volutpat  nulla  sapien  in  elit.  Nulla  rutrum  erat  id  neque  suscipit  eu  ultricies  odio  sollicitudin.  Aliquam  a  mi  vel  eros  placerat  hendrerit.  Phasellus  por6tor,  augue  sit  amet  vulputate  venena;s,  dui  leo  commodo  odio,  a  euismod  turpis  ligula  in  elit.    

_content

title

layout

slot

slot

Page 59: Symfony2 - WebExpo 2010

{% extends "HelloBundle::layout" %}

{% block content %} Hello {{ name }}! {% endblock %}

Page 60: Symfony2 - WebExpo 2010

<html> <head> <title> {% block title %}{% endblock %} </title> </head> <body> {% block body %}{% endblock %} </body> </html>

Page 61: Symfony2 - WebExpo 2010

~ PAC / HMVC

http://en.wikipedia.org/wiki/Presentation-abstraction-control

Page 62: Symfony2 - WebExpo 2010

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus.  

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus,  in  pulvinar  lectus  rutrum  sit  amet.  Duis  gravida,  metus  in  dictum  eleifend,  dolor  risus  ;ncidunt  ligula,  non  volutpat  nulla  sapien  in  elit.  Nulla  rutrum  erat  id  neque  suscipit  eu  ultricies  odio  sollicitudin.  Aliquam  a  mi  vel  eros  placerat  hendrerit.  Phasellus  por6tor,  augue  sit  amet  vulputate  venena;s,  dui  leo  commodo  odio,  a  euismod  turpis  ligula  in  elit.    

main controller (_content slot)

embedded MVC controller

layout

Page 63: Symfony2 - WebExpo 2010

public function indexAction($name) { $embedded = $this['controller_resolver'] ->render('HelloBundle:Hello:foo', array('name' => $name));

return $this->render( 'HelloBundle:Hello:index', array( 'name' => $name, 'embedded' => $embedded, ) ); }

Page 64: Symfony2 - WebExpo 2010

<?php $view->extend('...:layout') ?>

Lorem ipsum...

<?php echo $view['actions'] ->render('HelloBundle:Hello:foo', array('name' => $name)) ?>

Lorem ipsum...

Page 65: Symfony2 - WebExpo 2010

Bundles

Page 66: Symfony2 - WebExpo 2010

.../ SomeBundle/ Controller/ Entity/ Resources/ config/ views/ SomeBundle.php Tests/

Page 67: Symfony2 - WebExpo 2010

public function registerBundleDirs() { return array( 'Application' => __DIR__.'/../src/Application', 'Bundle' => __DIR__.'/../src/Bundle', 'Symfony\Bundle' => __DIR__.'/../src/vendor/symfony/src/Symfony/Bundle', ); }

Page 68: Symfony2 - WebExpo 2010

$this->render('SomeBundle:Hello:index', $params)

Page 69: Symfony2 - WebExpo 2010

hello: pattern: /hello/:name defaults: { _controller: SomeBundle:Hello:index }

Page 70: Symfony2 - WebExpo 2010

SomeBundle can be any of

Application\SomeBundle Bundle\SomeBundle Symfony\Bundle\SomeBundle

Page 71: Symfony2 - WebExpo 2010

Environments

Page 72: Symfony2 - WebExpo 2010

Developers Customer End Users

Development Environment

Staging Environment

Production Environment

Page 73: Symfony2 - WebExpo 2010

cache cache cache

debug   debug   debug  

logs   logs   logs  

stats stats stats

Development Environment

Staging Environment

Production Environment

Page 74: Symfony2 - WebExpo 2010

# config/config.yml doctrine.dbal: dbname: mydbname user: root password: %doctrine.dbal_password%

swift.mailer: transport: smtp host: localhost

Page 75: Symfony2 - WebExpo 2010

# config/config_dev.yml imports: - { resource: config.yml }

doctrine.dbal: password: null

swift.mailer: transport: gmail username: xxxxxxxx password: xxxxxxxx

Page 76: Symfony2 - WebExpo 2010

# Doctrine Configuration doctrine.dbal: dbname: xxxxxxxx user: xxxxxxxx password: ~

# Swiftmailer Configuration swift.mailer: transport: smtp encryption: ssl auth_mode: login host: smtp.gmail.com username: xxxxxxxx password: xxxxxxxx

Page 77: Symfony2 - WebExpo 2010

<!-- Doctrine Configuration --> <doctrine:dbal dbname="xxxxxxxx" user="xxxxxxxx" password="" />

<!-- Swiftmailer Configuration --> <swift:mailer transport="smtp" encryption="ssl" auth_mode="login" host="smtp.gmail.com" username="xxxxxxxx" password="xxxxxxxx" />

Page 78: Symfony2 - WebExpo 2010

// Doctrine Configuration $container->loadFromExtension('doctrine', 'dbal', array( 'dbname' => 'xxxxxxxx', 'user' => 'xxxxxxxx', 'password' => '', ));

// Swiftmailer Configuration $container->loadFromExtension('swift', 'mailer', array( 'transport' => "smtp", 'encryption' => "ssl", 'auth_mode' => "login", 'host' => "smtp.gmail.com", 'username' => "xxxxxxxx", 'password' => "xxxxxxxx", ));

Page 79: Symfony2 - WebExpo 2010

Dependency Injection Container

Page 80: Symfony2 - WebExpo 2010

Third-party libraries integration Unified Configuration

Page 81: Symfony2 - WebExpo 2010

# Twig Configuration twig.config: auto_reload: true

# Zend Logger Configuration zend.logger: priority: debug path: %kernel.root_dir%/logs/%kernel.environment%.log

Page 82: Symfony2 - WebExpo 2010

Configuration formats XML, YAML, PHP, INI, or Annotations

Parameters management Fast (cached) Inheritance

Sensitive data security …

Page 83: Symfony2 - WebExpo 2010

<doctrine:dbal dbname="sfweb" username="root" password="SuperSecretPasswordThatAnyoneCanSee" />

Page 84: Symfony2 - WebExpo 2010

SetEnv SYMFONY__DOCTRINE__DBAL__PASSWORD "foobar"

in a .htaccess or httpd.conf file

%doctrine.dbal.password%

Page 85: Symfony2 - WebExpo 2010

<doctrine:dbal dbname="sfweb" username="root" password="%doctrine.dbal.password%" />

Page 86: Symfony2 - WebExpo 2010

Developer Tools

Page 87: Symfony2 - WebExpo 2010

INFO: Matched route "blog_home" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'index', '_route' => 'blog_home',))

INFO: Using controller "Bundle\BlogBundle\Controller\PostController::indexAction"

INFO: SELECT s0_.id AS id0, s0_.title AS title1, s0_.html_body AS html_body2, s0_.excerpt AS excerpt3, s0_.published_at AS published_at4 FROM sf_weblog_post s0_ ORDER BY s0_.published_at DESC LIMIT 10 (array ())

Page 88: Symfony2 - WebExpo 2010

INFO: Matched route "blog_post" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'show', '_format' => 'html', 'id' => '3456', '_route' => 'blog_post',))

INFO: Using controller "Bundle\BlogBundle\Controller\PostController::showAction »

INFO: SELECT s0_.id AS id0, s0_.title AS title1, s0_.html_body AS html_body2, s0_.excerpt AS excerpt3, s0_.published_at AS published_at4 FROM sf_weblog_post s0_ WHERE s0_.id = ? (array ( 0 => '3456',)) ERR: Post "3456" not found! (No result was found for query although at least one row was expected.) (uncaught Symfony\Components\RequestHandler\Exception\NotFoundHttpException exception)

INFO: Using controller "Symfony\Framework\WebBundle\Controller\ExceptionController::exceptionAction"

Page 89: Symfony2 - WebExpo 2010

DEBUG: Notifying (until) event "core.request" to listener "(Symfony\Framework\WebBundle\Listener\RequestParser, resolve)" INFO: Matched route "blog_post" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'show', '_format' => 'html', 'id' => '3456', '_route' => 'blog_post',)) DEBUG: Notifying (until) event "core.load_controller" to listener "(Symfony\Framework\WebBundle\Listener\ControllerLoader, resolve)" INFO: Using controller "Bundle\BlogBundle\Controller\PostController::showAction" DEBUG: Listener "(Symfony\Framework\WebBundle\Listener\ControllerLoader, resolve)" processed the event "core.load_controller" INFO: Trying to get post "3456" from database INFO: SELECT s0_.id AS id0, s0_.title AS title1, s0_.html_body AS html_body2, s0_.excerpt AS excerpt3, s0_.published_at AS published_at4 FROM sf_weblog_post s0_ WHERE s0_.id = ? (array ( 0 => '3456',)) DEBUG: Notifying (until) event "core.exception" to listener "(Symfony\Framework\WebBundle\Listener\ExceptionHandler, handle)" ERR: Post "3456" not found! (No result was found for query although at least one row was expected.) (uncaught Symfony\Components\RequestHandler\Exception\NotFoundHttpException exception) DEBUG: Notifying (until) event "core.request" to listener "(Symfony\Framework\WebBundle\Listener\RequestParser, resolve)" DEBUG: Notifying (until) event "core.load_controller" to listener "(Symfony\Framework\WebBundle\Listener\ControllerLoader, resolve)" INFO: Using controller "Symfony\Framework\WebBundle\Controller\ExceptionController::exceptionAction" DEBUG: Listener "(Symfony\Framework\WebBundle\Listener\ControllerLoader, resolve)" processed the event "core.load_controller" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Listener\ResponseFilter, filter)" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Debug\DataCollector\DataCollectorManager, handle)" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Debug\WebDebugToolbar, handle)" DEBUG: Listener "(Symfony\Framework\WebBundle\Listener\ExceptionHandler, handle)" processed the event "core.exception" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Listener\ResponseFilter, filter)" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Debug\DataCollector\DataCollectorManager, handle)" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Debug\WebDebugToolbar, handle)"

Page 90: Symfony2 - WebExpo 2010
Page 91: Symfony2 - WebExpo 2010
Page 92: Symfony2 - WebExpo 2010
Page 93: Symfony2 - WebExpo 2010
Page 94: Symfony2 - WebExpo 2010
Page 95: Symfony2 - WebExpo 2010
Page 96: Symfony2 - WebExpo 2010
Page 97: Symfony2 - WebExpo 2010
Page 98: Symfony2 - WebExpo 2010

Security

XSS / CSRF / SQL Injection

Page 99: Symfony2 - WebExpo 2010

Functional Tests

Page 100: Symfony2 - WebExpo 2010

$client = $this->createClient();

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

$this->assertTrue($crawler->filter( 'html:contains("Hello Fabien")')->count());

Page 101: Symfony2 - WebExpo 2010

$this->assertEquals( 10, $crawler->filter('div.hentry')->count());

$this->assertTrue( $client->getResponse()->isSuccessful());

Page 102: Symfony2 - WebExpo 2010

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

Page 103: Symfony2 - WebExpo 2010

$link = $crawler->selectLink("Greet Lucas");

$client->click($link);

Page 104: Symfony2 - WebExpo 2010

$form = $crawler->selectButton('submit');

$client->submit($form, array( 'name' => 'Lucas', 'country' => 'France', 'like_symfony' => true, 'photo' => '/path/to/lucas.jpg', ));

Page 105: Symfony2 - WebExpo 2010

$harry = $this->createClient(); $sally = $this->createClient();

$harry->request('POST', '/say/sally/Hello'); $sally->request('GET', '/messages');

$this->assertEquals(201, $harry->getResponse()->getStatusCode());

$this->assertRegExp('/Hello/', $sally->getResponse()->getContent());

Page 106: Symfony2 - WebExpo 2010

$harry = $this->createClient(); $sally = $this->createClient();

$harry->insulate(); $sally->insulate();

$harry->request('POST', '/say/sally/Hello'); $sally->request('GET', '/messages');

$this->assertEquals(201, $harry->getResponse()->getStatusCode()); $this->assertRegExp('/Hello/', $sally->getResponse()->getContent());

Page 107: Symfony2 - WebExpo 2010

Caching

Page 108: Symfony2 - WebExpo 2010

HTTP Expiration / HTTP Validation

Page 109: Symfony2 - WebExpo 2010

$response->setSharedMaxAge(...); $response->setTtl(...); $response->setMaxAge(...); $response->setClientTtl(...); $response->setExpires(...);

$response->setETag(...); $response->setLastModified(...);

Page 110: Symfony2 - WebExpo 2010

Cache-Control: s-maxage=10

Page 111: Symfony2 - WebExpo 2010

public function showAction() { // ...

$response = $this->render('...', $vars);

$response->setSharedMaxAge(10);

return $response; }

Page 112: Symfony2 - WebExpo 2010

Symfony 2 comes built-in with an HTTP accelerator

Page 113: Symfony2 - WebExpo 2010

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus.  

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus,  in  pulvinar  lectus  rutrum  sit  amet.  Duis  gravida,  metus  in  dictum  eleifend,  dolor  risus  ;ncidunt  ligula,  non  volutpat  nulla  sapien  in  elit.  Nulla  rutrum  erat  id  neque  suscipit  eu  ultricies  odio  sollicitudin.  Aliquam  a  mi  vel  eros  placerat  hendrerit.  Phasellus  por6tor,  augue  sit  amet  vulputate  venena;s,  dui  leo  commodo  odio,  a  euismod  turpis  ligula  in  elit.    

cacheable for 10 seconds cacheable for 5 seconds

main controller

embedded controller

layout

Page 114: Symfony2 - WebExpo 2010

<?php $view->extend('...:layout') ?>

<?php $view['slots']->start('sidebar') ?>

<?php echo $view['actions']->render('...:foo') ?>

<?php $view['slots']->stop() ?>

cacheable for 10 seconds

cacheable for 5 seconds

Page 115: Symfony2 - WebExpo 2010

$view['actions']->render('HelloBundle:Hello:foo', array('name' => $name), array('standalone' => true) )

Page 116: Symfony2 - WebExpo 2010

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus.  

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus,  in  pulvinar  lectus  rutrum  sit  amet.  Duis  gravida,  metus  in  dictum  eleifend,  dolor  risus  ;ncidunt  ligula,  non  volutpat  nulla  sapien  in  elit.  Nulla  rutrum  erat  id  neque  suscipit  eu  ultricies  odio  sollicitudin.  Aliquam  a  mi  vel  eros  placerat  hendrerit.  Phasellus  por6tor,  augue  sit  amet  vulputate  venena;s,  dui  leo  commodo  odio,  a  euismod  turpis  ligula  in  elit.    

Page 117: Symfony2 - WebExpo 2010

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus,  in  pulvinar  lectus  rutrum  sit  amet.  Duis  gravida,  metus  in  dictum  eleifend,  dolor  risus  ;ncidunt  ligula,  non  volutpat  nulla  sapien  in  elit.  Nulla  rutrum  erat  id  neque  suscipit  eu  ultricies  odio  sollicitudin.  Aliquam  a  mi  vel  eros  placerat  hendrerit.  Phasellus  por6tor,  augue  sit  amet  vulputate  venena;s,  dui  leo  commodo  odio,  a  euismod  turpis  ligula  in  elit.    

<esi:include src="..." />

Page 118: Symfony2 - WebExpo 2010

ESI… or Edge Side Includes

Page 119: Symfony2 - WebExpo 2010

Symf

ony2

Appli

catio

n

Reve

rse Pr

oxy

Clien

t Lorem  ipsum  dolor  sit  amet,    

Lorem  ipsum  dolor  

Lorem  ipsum  dolor  sit  amet,    

Lorem  ipsum  dolor  

1

2

3

4

Page 120: Symfony2 - WebExpo 2010

Symfony2 app

Web Server

Requests

Response

Page 121: Symfony2 - WebExpo 2010

Symfony2 app

Symfony2 HTTP proxy

Web Server

Requests

Response

Page 122: Symfony2 - WebExpo 2010

Symfony2 app

Web Server

Reverse proxy

Requests

Response

Page 123: Symfony2 - WebExpo 2010

Extensibility

Page 124: Symfony2 - WebExpo 2010

Request

Response

core.controller

core.response

core.view

core.request

getController()

getArguments()

Page 125: Symfony2 - WebExpo 2010

Request

Response

core.controller

core.response

core.view

core.request

getController()

getArguments()

core.exception

Page 126: Symfony2 - WebExpo 2010

HttpFoundation

HttpKernel

FrameworkBundle

Routing

Console

SwiftmailerBundle

TwigBundle

DependencyInjection

...

...

Components

Bundles

Event Dispatcher

Templating

DoctrineBundle

ZendBundle

Page 127: Symfony2 - WebExpo 2010

Questions?