phpBB4 meets Symfony2
      Fabien Potencier
symfony 1 vs Symfony2
MVC
namespace ApplicationHelloBundleController;
use SymfonyBundleFrameworkBundleController;

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

        return $this->render(
           'HelloBundle:Hello:index',
           array('name' => $name)
        );
    }
}
<?php $view->extend('HelloBundle::layout') ?>

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

         Lorem	
  ipsum	
  dolor	
  sit	
  amet,	
  consectetur	
  adipiscing	
  elit.	
  In	
  vel	
  
                                                                                                  _content
         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	
  
layout   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.	
  	
  


                                                                                                                    slot
{% extends "HelloBundle::layout" %}

{% block content %}
    Hello {{ name }}!
{% endblock %}
<html>
    <head>
        <title>
           {% block title %}{% endblock %}
        </title>
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>
Routing
/blog.php?section=symfony&article_id=18475
web/
  index.php
/index.php/blog/2010/08/21/symfony2-meets-phpBB4
/blog/2010/08/21/symfony2-meets-phpBB4
/blog/:year/:month/:day/:slug
post:
    pattern: /blog/:year/:month/:day/:slug
    defaults:
      { _controller: BlogBundle:Post:show }
<routes>
    <route
      id="post"
      pattern="/blog/:year/:month/:day/:slug">
      <default key="_controller">
         BlogBundle:Post:show
      </default>
    </route>
</routes>
use SymfonyComponentRoutingRouteCollection;
use SymfonyComponentRoutingRoute;

$collection = new RouteCollection();

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

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

return $collection;
$router
  ->match('/blog/2010/08/21/sf2-meets-phpBB4')



$router
  ->generate('post', array('slug' => '...'))
post:
    pattern: /post/:slug
    defaults:
      { _controller: BlogBundle:Post:show }
$router
  ->generate('post', array('slug' => '...'))
Bundles
.../
  SomeBundle/
     Controller/
     Entity/
     Resources/
       config/
       views/
     SomeBundle.php
     Tests/
public function registerBundleDirs()
{
  return array(
     'Application'    => __DIR__.'/../src/Application',
     'Bundle'         => __DIR__.'/../src/Bundle',
     'SymfonyBundle' => __DIR__.'/../src/vendor/symfony/
src/Symfony/Bundle',
  );
}
$this->render('SomeBundle:Hello:index', $params)
hello:
  pattern: /hello/:name
  defaults: { _controller: SomeBundle:... }
SomeBundle can be any of


ApplicationSomeBundle
BundleSomeBundle
SymfonyBundleSomeBundle
Environments
Developers     Customer     End Users




Development     Staging      Production
Environment   Environment   Environment
cache         cache          cache

  debug	
       debug	
        debug	
  

   logs	
        logs	
         logs	
  

    stats        stats          stats



Development     Staging      Production
Environment   Environment   Environment
# config/config.yml
doctrine.dbal:
    dbname:    mydbname
    user:      root
    password: %doctrine.dbal_password%

swift.mailer:
    transport:   smtp
    host:        localhost
# config/config_dev.yml
imports:
    - { resource: config.yml }

zend.logger:
    priority: debug
    path:     %kernel.root_dir%/logs/%kernel.environment%.log


doctrine.dbal:
    password: ~

swift.mailer:
    transport:      gmail
    username:       xxxxxxxx
    password:       xxxxxxxx
# 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
<!-- Doctrine Configuration -->
<doctrine:dbal dbname="xxxxxxxx" user="xxxxxxxx"
password="" />
<doctrine:orm />

<!-- Swiftmailer Configuration -->
<swift:mailer
    transport="smtp"
    encryption="ssl"
    auth_mode="login"
    host="smtp.gmail.com"
    username="xxxxxxxx"
    password="xxxxxxxx" />
// Doctrine Configuration
$container->loadFromExtension('doctrine', 'dbal', array(
    'dbname'   => 'xxxxxxxx',
    'user'     => 'xxxxxxxx',
    'password' => '',
));
$container->loadFromExtension('doctrine', 'orm');

// Swiftmailer Configuration
$container->loadFromExtension('swift', 'mailer', array(
    'transport' => "smtp",
    'encryption' => "ssl",
    'auth_mode' => "login",
    'host'       => "smtp.gmail.com",
    'username'   => "xxxxxxxx",
    'password'   => "xxxxxxxx",
));
Developer Tools
INFO: Matched route "blog_home" (parameters: array ( '_bundle' =>
'BlogBundle', '_controller' => 'Post', '_action' => 'index', '_route' =>
'blog_home',))

INFO: Using controller "BundleBlogBundleController
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 ())
INFO: Matched route "blog_post" (parameters: array ( '_bundle' =>
'BlogBundle', '_controller' => 'Post', '_action' => 'show', '_format' =>
'html', 'id' => '3456', '_route' => 'blog_post',))

INFO: Using controller "BundleBlogBundleController
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 SymfonyComponentsRequestHandlerException
NotFoundHttpException exception)

INFO: Using controller "SymfonyFrameworkWebBundleController
ExceptionController::exceptionAction"
DEBUG: Notifying (until) event "core.request" to listener "(SymfonyFrameworkWebBundleListenerRequestParser, 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 "(SymfonyFrameworkWebBundleListenerControllerLoader,
resolve)"
INFO: Using controller "BundleBlogBundleControllerPostController::showAction"
DEBUG: Listener "(SymfonyFrameworkWebBundleListenerControllerLoader, 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 "(SymfonyFrameworkWebBundleListenerExceptionHandler, handle)"
ERR: Post "3456" not found! (No result was found for query although at least one row was expected.) (uncaught SymfonyComponents
RequestHandlerExceptionNotFoundHttpException exception)
DEBUG: Notifying (until) event "core.request" to listener "(SymfonyFrameworkWebBundleListenerRequestParser, resolve)"
DEBUG: Notifying (until) event "core.load_controller" to listener "(SymfonyFrameworkWebBundleListenerControllerLoader,
resolve)"
INFO: Using controller "SymfonyFrameworkWebBundleControllerExceptionController::exceptionAction"
DEBUG: Listener "(SymfonyFrameworkWebBundleListenerControllerLoader, resolve)" processed the event "core.load_controller"
DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleListenerResponseFilter, filter)"
DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugDataCollector
DataCollectorManager, handle)"
DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugWebDebugToolbar, handle)"
DEBUG: Listener "(SymfonyFrameworkWebBundleListenerExceptionHandler, handle)" processed the event "core.exception"
DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleListenerResponseFilter, filter)"
DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugDataCollector
DataCollectorManager, handle)"
DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugWebDebugToolbar, handle)"
Security
XSS / CSRF / SQL Injection
<doctrine:dbal
   dbname="sfweb"
   username="root"
   password="SuperSecretPasswordThatAnyoneCanSee"
/>
in a .htaccess or httpd.conf file
SetEnv SYMFONY__DOCTRINE__DBAL__PASSWORD "foobar"
                        %doctrine.dbal.password%
<doctrine:dbal
   dbname="sfweb"
   username="root"
   password="%doctrine.dbal.password%"
/>
Functional Tests
$client = $this->createClient();

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

$this->assertTrue($crawler->filter(
  'html:contains("Hello Fabien")')->count());
$this->assertEquals(
  10,
  $crawler->filter('div.hentry')->count());

$this->assertTrue(
  $client->getResponse()->isSuccessful());
$crawler = $client->request(
   'GET', 'hello/Lucas'
);
$link = $crawler->selectLink("Greet Lucas");

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

$client->submit($form, array(
    'name'         => 'Lucas',
    'country'      => 'France',
    'like_symfony' => true,
    'photo'        => '/path/to/lucas.jpg',
));
$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());
$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());
Caching
cacheable for 10 seconds
                                                                            cacheable for 5 seconds
         Lorem	
  ipsum	
  dolor	
  sit	
  amet,	
  consectetur	
           Lorem	
  ipsum	
  dolor	
  sit	
  
layout   adipiscing	
  elit.	
  In	
  vel	
  nulla	
  arcu,	
  vitae	
      amet,	
  consectetur	
  
         cursus	
  nunc.	
  Integer	
  semper	
  turpis	
  et	
  enim	
     adipiscing	
  elit.	
  In	
  vel	
  nulla	
  
         por6tor	
  iaculis.	
  Nulla	
  facilisi.	
  Lorem	
  ipsum	
      arcu,	
  vitae	
  cursus	
  nunc.	
  
         dolor	
  sit	
  amet,	
  consectetur	
  adipiscing	
  elit.	
      Integer	
  semper	
  turpis	
  et	
  
         Mauris	
  vehicula	
  ves;bulum	
  dictum.	
                       enim	
  por6tor	
  iaculis.	
  
         Aenean	
  non	
  velit	
  tortor.	
  Nullam	
  adipiscing	
        Nulla	
  facilisi.	
  Lorem	
  ipsum	
  
         malesuada	
  aliquam.	
  Mauris	
  dignissim,	
  urna	
            dolor	
  sit	
  amet,	
  
         quis	
  iaculis	
  tempus,	
  justo	
  libero	
  por6tor	
         consectetur	
  adipiscing	
  elit.	
  
         est,	
  nec	
  eleifend	
  est	
  elit	
  vitae	
  ante.	
         Mauris	
  vehicula	
  
         Curabitur	
  interdum	
  luctus	
  metus,	
  in	
                  ves;bulum	
  dictum.	
  
         pulvinar	
  lectus	
  rutrum	
  sit	
  amet.	
  Duis	
             Aenean	
  non	
  velit	
  tortor.	
  
         gravida,	
  metus	
  in	
  dictum	
  eleifend,	
  dolor	
          Nullam	
  adipiscing	
  
         risus	
  ;ncidunt	
  ligula,	
  non	
  volutpat	
  nulla	
         malesuada	
  aliquam.	
  
         sapien	
  main Nulla	
  rutrum	
  erat	
  id	
  neque	
  
                     in	
  elit.	
                                          Mauris	
  embeddedurna	
  
                                                                                       dignissim,	
  
         suscipit	
  eu	
  ultricies	
  odio	
  sollicitudin.	
  
                 controller                                                 quis	
  iaculis	
  tempus,	
  justo	
  
                                                                                        controller
         Aliquam	
  a	
  mi	
  vel	
  eros	
  placerat	
  hendrerit.	
      libero	
  por6tor	
  est,	
  nec	
  
         Phasellus	
  por6tor,	
  augue	
  sit	
  amet	
                    eleifend	
  est	
  elit	
  vitae	
  ante.	
  
         vulputate	
  venena;s,	
  dui	
  leo	
  commodo	
                  Curabitur	
  interdum	
  luctus	
  
         odio,	
  a	
  euismod	
  turpis	
  ligula	
  in	
  elit.	
  	
     metus.	
  
cacheable for 10 seconds

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

<?php $view['slots']->start('sidebar') ?> 5 seconds
                                 cacheable for
<?php echo $view['actions']->render('...:list') ?>

<?php $view['slots']->stop() ?>
$view['actions']->render('...:list', array(
   'standalone' => true,
))
Lorem	
  ipsum	
  dolor	
  sit	
  amet,	
  consectetur	
              Lorem	
  ipsum	
  dolor	
  sit	
  
adipiscing	
  elit.	
  In	
  vel	
  nulla	
  arcu,	
  vitae	
         amet,	
  consectetur	
  
cursus	
  nunc.	
  Integer	
  semper	
  turpis	
  et	
  enim	
        adipiscing	
  elit.	
  In	
  vel	
  nulla	
  
por6tor	
  iaculis.	
  Nulla	
  facilisi.	
  Lorem	
  ipsum	
         arcu,	
  vitae	
  cursus	
  nunc.	
  
dolor	
  sit	
  amet,	
  consectetur	
  adipiscing	
  elit.	
         Integer	
  semper	
  turpis	
  et	
  
Mauris	
  vehicula	
  ves;bulum	
  dictum.	
                          enim	
  por6tor	
  iaculis.	
  
Aenean	
  non	
  velit	
  tortor.	
  Nullam	
  adipiscing	
           Nulla	
  facilisi.	
  Lorem	
  ipsum	
  
malesuada	
  aliquam.	
  Mauris	
  dignissim,	
  urna	
               dolor	
  sit	
  amet,	
  
quis	
  iaculis	
  tempus,	
  justo	
  libero	
  por6tor	
            consectetur	
  adipiscing	
  elit.	
  
est,	
  nec	
  eleifend	
  est	
  elit	
  vitae	
  ante.	
            Mauris	
  vehicula	
  
Curabitur	
  interdum	
  luctus	
  metus,	
  in	
                     ves;bulum	
  dictum.	
  
pulvinar	
  lectus	
  rutrum	
  sit	
  amet.	
  Duis	
                Aenean	
  non	
  velit	
  tortor.	
  
gravida,	
  metus	
  in	
  dictum	
  eleifend,	
  dolor	
             Nullam	
  adipiscing	
  
risus	
  ;ncidunt	
  ligula,	
  non	
  volutpat	
  nulla	
            malesuada	
  aliquam.	
  
sapien	
  in	
  elit.	
  Nulla	
  rutrum	
  erat	
  id	
  neque	
     Mauris	
  dignissim,	
  urna	
  
suscipit	
  eu	
  ultricies	
  odio	
  sollicitudin.	
                quis	
  iaculis	
  tempus,	
  justo	
  
Aliquam	
  a	
  mi	
  vel	
  eros	
  placerat	
  hendrerit.	
         libero	
  por6tor	
  est,	
  nec	
  
Phasellus	
  por6tor,	
  augue	
  sit	
  amet	
                       eleifend	
  est	
  elit	
  vitae	
  ante.	
  
vulputate	
  venena;s,	
  dui	
  leo	
  commodo	
                     Curabitur	
  interdum	
  luctus	
  
odio,	
  a	
  euismod	
  turpis	
  ligula	
  in	
  elit.	
  	
        metus.	
  
<esi:include src="..." />
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… or Edge Side Includes
Lorem	
  ipsum	
  
                                                                      dolor	
  sit	
  
                                                                      amet,	
  	
  

         1
                                                                  2




                                                                                                       Symfony2 Application
                                                                                           Lorem	
  
                                                                                           ipsum	
  




                                                  Reverse Proxy
                                                                                           dolor	
  
Client




                                                                  3


             Lorem	
  ipsum	
     Lorem	
  
             dolor	
  sit	
       ipsum	
  
             amet,	
  	
          dolor	
  



                                              4
Web Server




                      Symfony2
                        app
Requests




           Response
Web Server

               Symfony2 HTTP proxy


                      Symfony2
                        app
Requests




           Response
Reverse proxy

                      Web Server




                      Symfony2
                        app
Requests




           Response
HttpKernel: The framework construction kit
namespace SymfonyComponentHttpKernel;
interface HttpKernelInterface
{
  const MASTER_REQUEST = 1;
  const SUB_REQUEST = 2;

    public function handle(
      Request $request = null,
      $type = self::MASTER_REQUEST,
      $raw = false);
}
Request


      core.request


           getController()


      core.controller


           getArguments()


      core.view


      core.response



Response
Request


      core.request


           getController()


      core.controller


           getArguments()


      core.view


      core.response



Response
Request


      core.request


           getController()


      core.controller
                             core.exception

           getArguments()


      core.view


      core.response



Response
SwiftmailerBundle     DoctrineBundle


                                 ZendBundle               ...


             FrameworkBundle     TwigBundle

Bundles

               Framework



Components
               HttpKernel      DependencyInjection      Console


                                    Routing           Templating


             HttpFoundation    Event Dispatcher           ...
MOD author
Theme author
Core Developer
End Users
Everybody
Questions?

PhpBB meets Symfony2

  • 1.
    phpBB4 meets Symfony2 Fabien Potencier
  • 2.
    symfony 1 vsSymfony2
  • 3.
  • 4.
    namespace ApplicationHelloBundleController; use SymfonyBundleFrameworkBundleController; classHelloController extends Controller { public function indexAction($name) { // Get things from the Model return $this->render( 'HelloBundle:Hello:index', array('name' => $name) ); } }
  • 5.
  • 6.
    <html> <head> <title> <?php $view['slots']->output('title') ?> </title> </head> <body> <?php $view['slots']->output('_content') ?> </body> </html>
  • 7.
    title Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel   _content 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   layout 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.     slot
  • 8.
    {% extends "HelloBundle::layout"%} {% block content %} Hello {{ name }}! {% endblock %}
  • 9.
    <html> <head> <title> {% block title %}{% endblock %} </title> </head> <body> {% block body %}{% endblock %} </body> </html>
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
    post: pattern: /blog/:year/:month/:day/:slug defaults: { _controller: BlogBundle:Post:show }
  • 17.
    <routes> <route id="post" pattern="/blog/:year/:month/:day/:slug"> <default key="_controller"> BlogBundle:Post:show </default> </route> </routes>
  • 18.
    use SymfonyComponentRoutingRouteCollection; use SymfonyComponentRoutingRoute; $collection= new RouteCollection(); $route = new Route( '/blog/:year/:month/:day/:slug', array('_controller' => 'BlogBundle:Post:show')); $collection->addRoute('post', $route); return $collection;
  • 19.
    $router ->match('/blog/2010/08/21/sf2-meets-phpBB4') $router ->generate('post', array('slug' => '...'))
  • 20.
    post: pattern: /post/:slug defaults: { _controller: BlogBundle:Post:show }
  • 21.
    $router ->generate('post',array('slug' => '...'))
  • 22.
  • 23.
    .../ SomeBundle/ Controller/ Entity/ Resources/ config/ views/ SomeBundle.php Tests/
  • 24.
    public function registerBundleDirs() { return array( 'Application' => __DIR__.'/../src/Application', 'Bundle' => __DIR__.'/../src/Bundle', 'SymfonyBundle' => __DIR__.'/../src/vendor/symfony/ src/Symfony/Bundle', ); }
  • 25.
  • 26.
    hello: pattern:/hello/:name defaults: { _controller: SomeBundle:... }
  • 27.
    SomeBundle can beany of ApplicationSomeBundle BundleSomeBundle SymfonyBundleSomeBundle
  • 28.
  • 29.
    Developers Customer End Users Development Staging Production Environment Environment Environment
  • 30.
    cache cache cache debug   debug   debug   logs   logs   logs   stats stats stats Development Staging Production Environment Environment Environment
  • 31.
    # config/config.yml doctrine.dbal: dbname: mydbname user: root password: %doctrine.dbal_password% swift.mailer: transport: smtp host: localhost
  • 32.
    # config/config_dev.yml imports: - { resource: config.yml } zend.logger: priority: debug path: %kernel.root_dir%/logs/%kernel.environment%.log doctrine.dbal: password: ~ swift.mailer: transport: gmail username: xxxxxxxx password: xxxxxxxx
  • 33.
    # 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
  • 34.
    <!-- Doctrine Configuration--> <doctrine:dbal dbname="xxxxxxxx" user="xxxxxxxx" password="" /> <doctrine:orm /> <!-- Swiftmailer Configuration --> <swift:mailer transport="smtp" encryption="ssl" auth_mode="login" host="smtp.gmail.com" username="xxxxxxxx" password="xxxxxxxx" />
  • 35.
    // Doctrine Configuration $container->loadFromExtension('doctrine','dbal', array( 'dbname' => 'xxxxxxxx', 'user' => 'xxxxxxxx', 'password' => '', )); $container->loadFromExtension('doctrine', 'orm'); // Swiftmailer Configuration $container->loadFromExtension('swift', 'mailer', array( 'transport' => "smtp", 'encryption' => "ssl", 'auth_mode' => "login", 'host' => "smtp.gmail.com", 'username' => "xxxxxxxx", 'password' => "xxxxxxxx", ));
  • 36.
  • 37.
    INFO: Matched route"blog_home" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'index', '_route' => 'blog_home',)) INFO: Using controller "BundleBlogBundleController 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 ())
  • 38.
    INFO: Matched route"blog_post" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'show', '_format' => 'html', 'id' => '3456', '_route' => 'blog_post',)) INFO: Using controller "BundleBlogBundleController 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 SymfonyComponentsRequestHandlerException NotFoundHttpException exception) INFO: Using controller "SymfonyFrameworkWebBundleController ExceptionController::exceptionAction"
  • 39.
    DEBUG: Notifying (until)event "core.request" to listener "(SymfonyFrameworkWebBundleListenerRequestParser, 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 "(SymfonyFrameworkWebBundleListenerControllerLoader, resolve)" INFO: Using controller "BundleBlogBundleControllerPostController::showAction" DEBUG: Listener "(SymfonyFrameworkWebBundleListenerControllerLoader, 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 "(SymfonyFrameworkWebBundleListenerExceptionHandler, handle)" ERR: Post "3456" not found! (No result was found for query although at least one row was expected.) (uncaught SymfonyComponents RequestHandlerExceptionNotFoundHttpException exception) DEBUG: Notifying (until) event "core.request" to listener "(SymfonyFrameworkWebBundleListenerRequestParser, resolve)" DEBUG: Notifying (until) event "core.load_controller" to listener "(SymfonyFrameworkWebBundleListenerControllerLoader, resolve)" INFO: Using controller "SymfonyFrameworkWebBundleControllerExceptionController::exceptionAction" DEBUG: Listener "(SymfonyFrameworkWebBundleListenerControllerLoader, resolve)" processed the event "core.load_controller" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleListenerResponseFilter, filter)" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugDataCollector DataCollectorManager, handle)" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugWebDebugToolbar, handle)" DEBUG: Listener "(SymfonyFrameworkWebBundleListenerExceptionHandler, handle)" processed the event "core.exception" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleListenerResponseFilter, filter)" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugDataCollector DataCollectorManager, handle)" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugWebDebugToolbar, handle)"
  • 42.
  • 43.
    XSS / CSRF/ SQL Injection
  • 44.
    <doctrine:dbal dbname="sfweb" username="root" password="SuperSecretPasswordThatAnyoneCanSee" />
  • 45.
    in a .htaccessor httpd.conf file SetEnv SYMFONY__DOCTRINE__DBAL__PASSWORD "foobar" %doctrine.dbal.password%
  • 46.
    <doctrine:dbal dbname="sfweb" username="root" password="%doctrine.dbal.password%" />
  • 47.
  • 48.
    $client = $this->createClient(); $crawler= $client->request( 'GET', '/hello/Fabien'); $this->assertTrue($crawler->filter( 'html:contains("Hello Fabien")')->count());
  • 49.
    $this->assertEquals( 10, $crawler->filter('div.hentry')->count()); $this->assertTrue( $client->getResponse()->isSuccessful());
  • 50.
    $crawler = $client->request( 'GET', 'hello/Lucas' );
  • 51.
    $link = $crawler->selectLink("GreetLucas"); $client->click($link);
  • 52.
    $form = $crawler->selectButton('submit'); $client->submit($form,array( 'name' => 'Lucas', 'country' => 'France', 'like_symfony' => true, 'photo' => '/path/to/lucas.jpg', ));
  • 53.
    $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());
  • 54.
    $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());
  • 55.
  • 56.
    cacheable for 10seconds cacheable for 5 seconds Lorem  ipsum  dolor  sit  amet,  consectetur   Lorem  ipsum  dolor  sit   layout adipiscing  elit.  In  vel  nulla  arcu,  vitae   amet,  consectetur   cursus  nunc.  Integer  semper  turpis  et  enim   adipiscing  elit.  In  vel  nulla   por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum   arcu,  vitae  cursus  nunc.   dolor  sit  amet,  consectetur  adipiscing  elit.   Integer  semper  turpis  et   Mauris  vehicula  ves;bulum  dictum.   enim  por6tor  iaculis.   Aenean  non  velit  tortor.  Nullam  adipiscing   Nulla  facilisi.  Lorem  ipsum   malesuada  aliquam.  Mauris  dignissim,  urna   dolor  sit  amet,   quis  iaculis  tempus,  justo  libero  por6tor   consectetur  adipiscing  elit.   est,  nec  eleifend  est  elit  vitae  ante.   Mauris  vehicula   Curabitur  interdum  luctus  metus,  in   ves;bulum  dictum.   pulvinar  lectus  rutrum  sit  amet.  Duis   Aenean  non  velit  tortor.   gravida,  metus  in  dictum  eleifend,  dolor   Nullam  adipiscing   risus  ;ncidunt  ligula,  non  volutpat  nulla   malesuada  aliquam.   sapien  main Nulla  rutrum  erat  id  neque   in  elit.   Mauris  embeddedurna   dignissim,   suscipit  eu  ultricies  odio  sollicitudin.   controller quis  iaculis  tempus,  justo   controller Aliquam  a  mi  vel  eros  placerat  hendrerit.   libero  por6tor  est,  nec   Phasellus  por6tor,  augue  sit  amet   eleifend  est  elit  vitae  ante.   vulputate  venena;s,  dui  leo  commodo   Curabitur  interdum  luctus   odio,  a  euismod  turpis  ligula  in  elit.     metus.  
  • 57.
    cacheable for 10seconds <?php $view->extend('...:layout') ?> <?php $view['slots']->start('sidebar') ?> 5 seconds cacheable for <?php echo $view['actions']->render('...:list') ?> <?php $view['slots']->stop() ?>
  • 58.
  • 59.
    Lorem  ipsum  dolor  sit  amet,  consectetur   Lorem  ipsum  dolor  sit   adipiscing  elit.  In  vel  nulla  arcu,  vitae   amet,  consectetur   cursus  nunc.  Integer  semper  turpis  et  enim   adipiscing  elit.  In  vel  nulla   por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum   arcu,  vitae  cursus  nunc.   dolor  sit  amet,  consectetur  adipiscing  elit.   Integer  semper  turpis  et   Mauris  vehicula  ves;bulum  dictum.   enim  por6tor  iaculis.   Aenean  non  velit  tortor.  Nullam  adipiscing   Nulla  facilisi.  Lorem  ipsum   malesuada  aliquam.  Mauris  dignissim,  urna   dolor  sit  amet,   quis  iaculis  tempus,  justo  libero  por6tor   consectetur  adipiscing  elit.   est,  nec  eleifend  est  elit  vitae  ante.   Mauris  vehicula   Curabitur  interdum  luctus  metus,  in   ves;bulum  dictum.   pulvinar  lectus  rutrum  sit  amet.  Duis   Aenean  non  velit  tortor.   gravida,  metus  in  dictum  eleifend,  dolor   Nullam  adipiscing   risus  ;ncidunt  ligula,  non  volutpat  nulla   malesuada  aliquam.   sapien  in  elit.  Nulla  rutrum  erat  id  neque   Mauris  dignissim,  urna   suscipit  eu  ultricies  odio  sollicitudin.   quis  iaculis  tempus,  justo   Aliquam  a  mi  vel  eros  placerat  hendrerit.   libero  por6tor  est,  nec   Phasellus  por6tor,  augue  sit  amet   eleifend  est  elit  vitae  ante.   vulputate  venena;s,  dui  leo  commodo   Curabitur  interdum  luctus   odio,  a  euismod  turpis  ligula  in  elit.     metus.  
  • 60.
    <esi:include src="..." /> 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.    
  • 61.
    ESI… or EdgeSide Includes
  • 62.
    Lorem  ipsum   dolor  sit   amet,     1 2 Symfony2 Application Lorem   ipsum   Reverse Proxy dolor   Client 3 Lorem  ipsum   Lorem   dolor  sit   ipsum   amet,     dolor   4
  • 63.
    Web Server Symfony2 app Requests Response
  • 64.
    Web Server Symfony2 HTTP proxy Symfony2 app Requests Response
  • 65.
    Reverse proxy Web Server Symfony2 app Requests Response
  • 66.
    HttpKernel: The frameworkconstruction kit
  • 67.
    namespace SymfonyComponentHttpKernel; interface HttpKernelInterface { const MASTER_REQUEST = 1; const SUB_REQUEST = 2; public function handle( Request $request = null, $type = self::MASTER_REQUEST, $raw = false); }
  • 68.
    Request core.request getController() core.controller getArguments() core.view core.response Response
  • 69.
    Request core.request getController() core.controller getArguments() core.view core.response Response
  • 70.
    Request core.request getController() core.controller core.exception getArguments() core.view core.response Response
  • 71.
    SwiftmailerBundle DoctrineBundle ZendBundle ... FrameworkBundle TwigBundle Bundles Framework Components HttpKernel DependencyInjection Console Routing Templating HttpFoundation Event Dispatcher ...
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.