Symfony2 - OSIDays 2010

126
Symfony2 Fabien Potencier

description

 

Transcript of Symfony2 - OSIDays 2010

Page 1: Symfony2 - OSIDays 2010

Symfony2 Fabien Potencier

Page 2: Symfony2 - OSIDays 2010

Serial entrepreneur Developer by passion Founder of Sensio Creator and lead developer of Symfony @fabpot http://www.github.com/fabpot http://fabien.potencier.org/

Page 3: Symfony2 - OSIDays 2010

What is Symfony2?

Page 4: Symfony2 - OSIDays 2010

A set of decoupled and cohesive components

Page 5: Symfony2 - OSIDays 2010

DependencyInjection EventDispatcher HttpFoundation OutputEscaper

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

Page 6: Symfony2 - OSIDays 2010

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

Page 7: Symfony2 - OSIDays 2010

A set of decoupled and cohesive components

Autoloading

Page 8: Symfony2 - OSIDays 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 9: Symfony2 - OSIDays 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 10: Symfony2 - OSIDays 2010

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

use Symfony\Framework\UniversalClassLoader;

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

Page 11: Symfony2 - OSIDays 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 12: Symfony2 - OSIDays 2010

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

PEAR style

Page 13: Symfony2 - OSIDays 2010

A set of decoupled and cohesive components

Process

Page 14: Symfony2 - OSIDays 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 15: Symfony2 - OSIDays 2010

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

$process = new Process($cmd);

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

Page 16: Symfony2 - OSIDays 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 17: Symfony2 - OSIDays 2010

A set of decoupled and cohesive components

CssSelector

Page 18: Symfony2 - OSIDays 2010

use Symfony\Component\CssSelector\Parser;

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

Page 19: Symfony2 - OSIDays 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 20: Symfony2 - OSIDays 2010

A set of decoupled and cohesive components

Finder

Page 21: Symfony2 - OSIDays 2010

use Symfony\Component\Finder\Finder;

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

Page 22: Symfony2 - OSIDays 2010

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

Page 23: Symfony2 - OSIDays 2010

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

$files = iterator_to_array($finder);

$count = iterator_count($finder);

Page 24: Symfony2 - OSIDays 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 25: Symfony2 - OSIDays 2010

A set of decoupled and cohesive components

Routing

Page 26: Symfony2 - OSIDays 2010

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

Page 27: Symfony2 - OSIDays 2010

web/ index.php

Page 28: Symfony2 - OSIDays 2010

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

Page 29: Symfony2 - OSIDays 2010

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

Page 30: Symfony2 - OSIDays 2010

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

Page 31: Symfony2 - OSIDays 2010

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

Page 32: Symfony2 - OSIDays 2010

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

Page 33: Symfony2 - OSIDays 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 34: Symfony2 - OSIDays 2010

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

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

Page 35: Symfony2 - OSIDays 2010

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

Page 36: Symfony2 - OSIDays 2010

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

Page 37: Symfony2 - OSIDays 2010

An Object-Oriented abstraction on top of PHP

Page 38: Symfony2 - OSIDays 2010

An Object-Oriented abstraction on top of PHP

Request

Page 39: Symfony2 - OSIDays 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 40: Symfony2 - OSIDays 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 41: Symfony2 - OSIDays 2010

new Request();

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

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

Page 42: Symfony2 - OSIDays 2010

An Object-Oriented abstraction on top of PHP

Session

Page 43: Symfony2 - OSIDays 2010

$session = $request->getSession();

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

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

Page 44: Symfony2 - OSIDays 2010

An Object-Oriented abstraction on top of PHP

Response

Page 45: Symfony2 - OSIDays 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 46: Symfony2 - OSIDays 2010

An Object-Oriented abstraction of the HTTP dialog

Page 47: Symfony2 - OSIDays 2010

A MVC Web Framework

Page 48: Symfony2 - OSIDays 2010

The Symfony2 MVC Philosophy

Page 49: Symfony2 - OSIDays 2010

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

Page 50: Symfony2 - OSIDays 2010

MVC

Page 51: Symfony2 - OSIDays 2010

http://symfony-reloaded.org/

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

Page 52: Symfony2 - OSIDays 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 53: Symfony2 - OSIDays 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 54: Symfony2 - OSIDays 2010

Hello <?php echo $name ?>!

Page 55: Symfony2 - OSIDays 2010

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

Hello <?php echo $name ?>!

Page 56: Symfony2 - OSIDays 2010

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

Page 57: Symfony2 - OSIDays 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 58: Symfony2 - OSIDays 2010

{% extends "HelloBundle::layout" %}

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

Page 59: Symfony2 - OSIDays 2010

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

Page 60: Symfony2 - OSIDays 2010

PAC / HMVC

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

Page 61: Symfony2 - OSIDays 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 62: Symfony2 - OSIDays 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 63: Symfony2 - OSIDays 2010

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

Lorem ipsum...

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

Lorem ipsum...

Page 64: Symfony2 - OSIDays 2010

Bundles

Page 65: Symfony2 - OSIDays 2010

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

Page 66: Symfony2 - OSIDays 2010

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

Page 67: Symfony2 - OSIDays 2010

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

Page 68: Symfony2 - OSIDays 2010

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

Page 69: Symfony2 - OSIDays 2010

SomeBundle can be any of

Application\SomeBundle Bundle\SomeBundle Symfony\Bundle\SomeBundle

Page 70: Symfony2 - OSIDays 2010

Environments

Page 71: Symfony2 - OSIDays 2010

Developers Customer End Users

Development Environment

Staging Environment

Production Environment

Page 72: Symfony2 - OSIDays 2010

cache cache cache

debug   debug   debug  

logs   logs   logs  

stats stats stats

Development Environment

Staging Environment

Production Environment

Page 73: Symfony2 - OSIDays 2010

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

swift.mailer: transport: smtp host: localhost

Page 74: Symfony2 - OSIDays 2010

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

doctrine.dbal: password: null

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

Page 75: Symfony2 - OSIDays 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 76: Symfony2 - OSIDays 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 - OSIDays 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 78: Symfony2 - OSIDays 2010

Dependency Injection Container

Page 79: Symfony2 - OSIDays 2010

Third-party libraries integration Unified Configuration

Page 80: Symfony2 - OSIDays 2010

# Twig Configuration twig.config: auto_reload: true

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

Page 81: Symfony2 - OSIDays 2010

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

Parameters management Fast (cached) Inheritance

Sensitive data security …

Page 82: Symfony2 - OSIDays 2010

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

Page 83: Symfony2 - OSIDays 2010

SetEnv SYMFONY__DOCTRINE__DBAL__PASSWORD "foobar"

in a .htaccess or httpd.conf file

%doctrine.dbal.password%

Page 84: Symfony2 - OSIDays 2010

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

Page 85: Symfony2 - OSIDays 2010

Developer Tools

Page 86: Symfony2 - OSIDays 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 87: Symfony2 - OSIDays 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 88: Symfony2 - OSIDays 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 89: Symfony2 - OSIDays 2010
Page 90: Symfony2 - OSIDays 2010
Page 91: Symfony2 - OSIDays 2010
Page 92: Symfony2 - OSIDays 2010
Page 93: Symfony2 - OSIDays 2010
Page 94: Symfony2 - OSIDays 2010
Page 95: Symfony2 - OSIDays 2010
Page 96: Symfony2 - OSIDays 2010
Page 97: Symfony2 - OSIDays 2010

Security

XSS / CSRF / SQL Injection

Page 98: Symfony2 - OSIDays 2010

Functional Tests

Page 99: Symfony2 - OSIDays 2010

$client = $this->createClient();

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

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

Page 100: Symfony2 - OSIDays 2010

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

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

Page 101: Symfony2 - OSIDays 2010

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

Page 102: Symfony2 - OSIDays 2010

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

$client->click($link);

Page 103: Symfony2 - OSIDays 2010

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

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

Page 104: Symfony2 - OSIDays 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 105: Symfony2 - OSIDays 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 106: Symfony2 - OSIDays 2010

Caching

Page 107: Symfony2 - OSIDays 2010

HTTP Expiration / HTTP Validation

Page 108: Symfony2 - OSIDays 2010

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

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

Page 109: Symfony2 - OSIDays 2010

Cache-Control: s-maxage=10

Page 110: Symfony2 - OSIDays 2010

public function showAction() { // ...

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

$response->setSharedMaxAge(10);

return $response; }

Page 111: Symfony2 - OSIDays 2010

Symfony 2 comes built-in with an HTTP accelerator

Page 112: Symfony2 - OSIDays 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 113: Symfony2 - OSIDays 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 114: Symfony2 - OSIDays 2010

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

Page 115: Symfony2 - OSIDays 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 116: Symfony2 - OSIDays 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 117: Symfony2 - OSIDays 2010

ESI… or Edge Side Includes

Page 118: Symfony2 - OSIDays 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 119: Symfony2 - OSIDays 2010

Symfony2 app

Web Server

Requests

Response

Page 120: Symfony2 - OSIDays 2010

Symfony2 app

Symfony2 HTTP proxy

Web Server

Requests

Response

Page 121: Symfony2 - OSIDays 2010

Symfony2 app

Web Server

Reverse proxy

Requests

Response

Page 122: Symfony2 - OSIDays 2010

Extensibility

Page 123: Symfony2 - OSIDays 2010

Request

Response

core.controller

core.response

core.view

core.request

getController()

getArguments()

Page 124: Symfony2 - OSIDays 2010

Request

Response

core.controller

core.response

core.view

core.request

getController()

getArguments()

core.exception

Page 125: Symfony2 - OSIDays 2010

HttpFoundation

HttpKernel

FrameworkBundle

Routing

Console

SwiftmailerBundle

TwigBundle

DependencyInjection

...

...

Components

Bundles

Event Dispatcher

Templating

DoctrineBundle

ZendBundle

Page 126: Symfony2 - OSIDays 2010

Questions?