SlideShare a Scribd company logo
Symfony 2

 Fabien Potencier
Who am I?
•  Founder of Sensio
   –  Web Agency
   –  Since 1998
   –  70 people
   –  Open-Source Specialists
   –  Big corporate customers


•  Creator and lead developer of symfony
How many of you have used symfony?
         1.0? 1.1? 1.2?
symfony 1.0
•  Started as a glue between existing Open-Source libraries:
   – Mojavi (heavily modified), Propel, Prado i18n, …

•  Borrowed concepts from other languages and frameworks:
   – Routing, CLI, functional tests, YAML, Rails helpers…

•  Added new concepts to the mix
   – Web Debug Toolbar, admin generator, configuration cascade, …
symfony 1.2

•  Decoupled but cohesive components: the symfony platform

   –  Forms, Routing, Cache, YAML, ORMs, …

•  Controller still based on Mojavi

   –  View, Filter Chain, …

•  Could have been named 2.0 ;)
symfony platform                                 >= 1.1
                                                                                  2.0


    sfRequest    sfRouting     sfLogger   sfI18N    sfUser      sfResponse




sfYAML   sfDatabase   sfForm    sfEventDispatcher   sfStorage     sfCache    sfOutputEscaper



             sfValidator     sfWidget                            sfCoreAutoload
                                                                                   platform
symfony platform



require_once '/path/to/sfCoreAutoload.class.php';
sfCoreAutoload::register();
$config = sfYaml::load(<<<EOF
config:
   key: value
   foo: [bar, foobar]
   bar: { bar: foo }
EOF
);

print_r($config);
echo sfYaml::dump($config);
$cache = new sfSQLiteCache(array(
  'database' => dirname(__FILE__).'/cache.db'
));
$cache->set('foo', 'bar');
echo $cache->get('foo');
Symfony 2 is an evolution of symfony 1


•  Same symfony platform

•  Different controller implementation

•  Oh! Symfony now takes a capital S!!!
Symfony 2 main goals


   Flexibility
       Fast
     Smart
Symfony 2: New components


Dependency Injection Container
   Templating Framework
     Controller Handling
Symfony 2
•  Not yet available as a full-stack MVC framework
•  Some components have already been merged into Symfony 1
   –  Event Dispatcher
   –  Form Framework
•  Other new components will soon be released as standalone
   components:
   –  Controller Handling
   –  Templating Framework
   –  Dependency Injection Container
symfony 1: Not fast enough?
symfony 1 is
  one of the slowest framework
     when you test it against
a simple Hello World application
1644&

1544&          !"#$%&!'!&

1344&

1144&

1444&

 ;44&

 :44&
                                                                      x 19.5
 944&

 844&


        Hello World
 744&

 644&

 544&    Benchmark
 344&
                                     ()"#*&
 144&                                                                  x 2.3
                                                           +,&           -./0)%.&123&
   4&
               based on numbers from http://paul-m-jones.com/?p=315
Conclusion?
Don’t use symfony
for your next « Hello World » website

            Use PHP ;)
By the way,

      the fastest implemention
of a Hello World application with PHP:

  die('Hello World');
But symfony 1 is probably fast enough
        for your next website
… anyway, it is fast enough for Yahoo!

Yahoo! Bookmarks      sf-to.org/bookmarks

Yahoo! Answers        sf-to.org/answers

delicious.com         sf-to.org/delicious
… and recently
dailymotion.com announced
  its migration to Symfony

 sf-to.org/dailymotion
Secondmost popular video sharing website
 One of the top 50 websites in the world
     42 million unique users in December
…and of course
many other smaller websites…
Symfony 2: Faster?
Symfony 2 core is so light and flexible
   that you can easily customize it
  to have outstanding performance
     for a Hello World application
Symfony 2 core is so light and flexible
      that its raw performance
            is outstanding
require_once dirname(__FILE__).'/sf20/autoload2/sfCore2Autoload.class.php';
sfCore2Autoload::register();

$app = new HelloApplication();
$app->run()->send();

class HelloApplication
{
  public function __construct()
  {
    $this->dispatcher = new sfEventDispatcher();
    $this->dispatcher->connect('application.load_controller', array($this, 'loadController'));
  }

    public function run()


                                                                                               Hello World
    {
      $request = new sfWebRequest($this->dispatcher);


                                                                                                  Symfony 2.0
      $handler = new sfRequestHandler($this->dispatcher);

                                                                                             with
      $response = $handler->handle($request);

        return $response;
    }

    public function loadController(sfEvent $event)
    {
      $event->setReturnValue(array(array($this, 'hello'), array($this->dispatcher, $event['request'])));

        return true;
    }

    public function hello($dispatcher, $request)
    {
      $response = new sfWebResponse($dispatcher);
      $response->setContent('Hello World');

        return $response;
    }
}
7922&

7822&   !"#$%&!'!&
                                                                        Hello World
                      ()$*+&
7022&
                                                                         Benchmark
7722&

7222&

 >22&

 =22&

 <22&

 ;22&

 :22&
                                        ,-./+%-&012&
 922&
                                                         x 3                  x 7
 822&

 022&
                                                         3+"#4&
 722&                                                                   56&         ,-./+%-&710&
   2&
                 based on numbers from http://paul-m-jones.com/?p=315
Twitto ?!
Twitto: The PHP framework that fits in a tweet
•  The fastest framework around?
•  Uses some PHP 5.3 new features
•  It also fits in a slide…

require __DIR__.'/c.php';
if (!is_callable($c = @$_GET['c'] ?:
function() { echo 'Woah!'; }))
  throw new Exception('Error');
$c();                            twitt o.org
Don’t use Twitto for your next website
            It is a joke ;)
7 times faster ?!



You won’t have such a difference for real applications
       as most of the time, the limiting factor
             is not the framework itself
7 times faster ?!
•  But raw speed matters because
   – It demonstrates that the core « kernel » is very light
   – It allows you to use several Symfony frameworks within a single
     application with the same behavior but different optimizations:

      •  One full-stack framework optimized for ease of use (think symfony 1)

      •  One light framework optimized for speed (think Rails Metal ;))
symfony platform                                            2.0



sfRequestHandler       sfRequest    sfRouting   sfLogger   sfI18N   sfUser    sfTemplate   sfResponse




sfValidator   sfForm     sfWidget    sfCache    sfDatabase    sfStorage      sfYAML   sfOutputEscaper



                           sfServiceContainer      sfEventDispatcher      sfCoreAutoload
                                                                                            platform
Symfony 2 kernel:

The Request Handler
Symfony 2 secret weapon:

  The Request Handler
The Request Handler
•  The backbone of Symfony 2 controller implementation
•  Class to build web frameworks, not only MVC ones
•  Based on a simple assumption:
   –  The input is a request object
   –  The output is a response object
•  The request object can be anything you want
•  The response object must implement a send() method

        Web Request                                  Web Response
                                  Request Handler
The Request Handler


$handler = new sfRequestHandler($dispatcher);

$request = new sfWebRequest($dispatcher);
$response = $handler->handle($request);

$response->send();
The Request Handler
•  The sfRequestHandler does several things:
   –  Notify events

   –  Execute a callable (the controller)

   –  Ensure that the Request is converted to a Response object

•  The framework is responsible for choosing the controller
•  The controller is responsible for the conversion of the Request to a
   Response
class sfRequestHandler
{
  protected $dispatcher = null;

    public function __construct(sfEventDispatcher $dispatcher)
    {
      $this->dispatcher = $dispatcher;
    }




                                                                                                                                                                                           sfRequestHandler
    public function handle($request)
    {
      try
      {
        return $this->handleRaw($request);




                                                                                                                                                                                            s less than 100
      }
      catch (Exception $e)



                                                                                                                                                                                           i
      {
        $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'application.exception', array('request' => $request, 'exception' => $e)));
        if ($event->isProcessed())
        {




                                                                                                                                                                                             lines of PHP
          return $this->filterResponse($event->getReturnValue(), 'An "application.exception" listener returned a non response object.');
        }

            throw $e;
        }
    }




                                                                                                                                                                                                 code!
    public function handleRaw($request)
    {
      $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'application.request', array('request' => $request)));
      if ($event->isProcessed())
      {
        return $this->filterResponse($event->getReturnValue(), 'An "application.request" listener returned a non response object.');
      }

        $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'application.load_controller', array('request' => $request)));
        if (!$event->isProcessed())
        {
          throw new Exception('Unable to load the controller.');
        }

        list($controller, $arguments) = $event->getReturnValue();

        if (!is_callable($controller))
        {
          throw new Exception(sprintf('The controller must be a callable (%s).', var_export($controller, true)));
        }

        $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'application.controller', array('request' => $request, 'controller' => &$controller, 'arguments' => &$arguments)));
        if ($event->isProcessed())
        {
          try
          {
             return $this->filterResponse($event->getReturnValue(), 'An "application.controller" listener returned a non response object.');
          }
          catch (Exception $e)
          {
            $retval = $event->getReturnValue();
          }
        }
        else
        {
          $retval = call_user_func_array($controller, $arguments);
        }

        $event = $this->dispatcher->filter(new sfEvent($this, 'application.view'), $retval);

        return $this->filterResponse($event->getReturnValue(), sprintf('The controller must return a response (instead of %s).', is_object($event->getReturnValue()) ? 'an object of class '.get_class($event->getReturnValue()) : (string) $event->getReturnValue()));
    }

    protected function filterResponse($response, $message)
    {
      if (!is_object($response) || !method_exists($response, 'send'))
      {
        throw new RuntimeException($message);
      }

        $event = $this->dispatcher->filter(new sfEvent($this, 'application.response'), $response);
        $response = $event->getReturnValue();

        if (!is_object($response) || !method_exists($response, 'send'))
        {
          throw new RuntimeException('An "application.response" listener returned a non response object.');
        }

        return $response;
    }
}
Request Handler Events
application.request

application.load_controller

application.controller

application.view

application.response

application.exception
application.response




As the very last event notified, a listener can modify the
   Response object just before it is returned to the user
application.request



•  The very first event notified

•  It can act as a short-circuit event

•  If one listener returns a Response object, it stops the processing
application.load_controller



•  Only event for which at least one listener must be connected to

•  A listener must return
   –  A PHP callable (the controller)
   –  The arguments to pass to the callable
application.view




The controller must return a Response object
        except if a listener can convert
  the controller return value to a Response
application.exception




The request handler catches all exceptions
       and give a chance to listeners
        to return a Response object
Request Handler
•  Several listeners can be attached to a single event
•  Listeners are called in turn

                                                    sfEventDispatcher

                                  load_controller



                                                    controller




                                                                                    response
                       request




                                                                 view
                                                                        exception


         request                                    sfRequestHandler                           response
require_once dirname(__FILE__).'/sf20/autoload2/sfCore2Autoload.class.php';
sfCore2Autoload::register();

$app = new HelloApplication();
$app->run()->send();

class HelloApplication
{
  public function __construct()
  {
    $this->dispatcher = new sfEventDispatcher();
    $this->dispatcher->connect('application.load_controller', array($this, 'loadController'));
  }

    public function run()


                                                                                               Hello World
    {
      $request = new sfWebRequest($this->dispatcher);


                                                                                                  Symfony 2.0
      $handler = new sfRequestHandler($this->dispatcher);

                                                                                             with
      $response = $handler->handle($request);

        return $response;
    }

    public function loadController(sfEvent $event)
    {
      $event->setReturnValue(array(array($this, 'hello'), array($this->dispatcher, $event['request'])));

        return true;
    }

    public function hello($dispatcher, $request)
    {
      $response = new sfWebResponse($dispatcher);
      $response->setContent('Hello World');

        return $response;
    }
}
require_once '/path/to/sfCore2Autoload.class.php';
sfCore2Autoload::register();
$app = new HelloApplication();
$app->run()->send();
public function __construct()
 {
   $this->dispatcher = new sfEventDispatcher();
   $this->dispatcher->connect(
      'application.load_controller',
      array($this, 'loadController')
   );
 }

                                                  sfEventDispatcher




                                load_controller



                                                  controller




                                                                                  response
                      request




                                                               view
                                                                      exception


            request                               sfRequestHandler                           response
public function loadController(sfEvent $event)
 {
   $event->setReturnValue(array(
    array($this, 'hello'),
    array($this->dispatcher, $event['request'])
   ));

     return true;
 }
public function hello($dispatcher, $request)
 {
   $response = new sfWebResponse($dispatcher);
   $response->setContent('Hello World');

    return $response;
}
public function run()
 {
   $request = new sfWebRequest($this->dispatcher);
   $handler = new sfRequestHandler($this->dispatcher);
   $response = $handler->handle($request);

     return $response;
 }
Case study: dailymotion.com
•  The problem: the Dailymotion developers add new features on a nearly
   everyday basis
•  The challenge: Migrate by introducing small doses of Symfony
   goodness
•  The process
   –  Wrap everything with sfRequestHandler by implementing an
      application.load_controller listener that calls the old code, based on the
      request
   –  Migrate the mod_rewrite rules to the symfony routing
   –  Add unit and functional tests
Symfony 2: The Templating Framework
New Templating Framework
•  4 components
   –  Template Engine
   –  Template Renderers
   –  Template Loaders
   –  Template Storages



•  Independant library
require_once '/path/to/sfCore2Autoload.class.php';
sfCore2Autoload::register();

$dispatcher = new sfEventDispatcher();

$loader = new sfTemplateLoaderFilesystem($dispatcher,
  '/path/to/templates/%s.php');

$t = new sfTemplateEngine($dispatcher, $loader);

echo $t->render('index', array('name' => 'Fabien'));
Template Loaders
•  No assumption about where and how templates are to be found
   –  Filesystem
   –  Database
   –  Memory
   –  …
•  Template names are « logical » names:

  $loader = new sfTemplateLoaderFilesystem($dispatcher,
               '/path/to/templates/%s.php');
Template Renderers
•  No assumption about the format of the templates
•  Template names are prefixed with the renderer name:
   –  index == php:index
   –  user:index

$t = new sfTemplateEngine($dispatcher, $loader, array(
  'user' => new ProjectTemplateRenderer($dispatcher),
  'php' => new sfTemplateRendererPhp($dispatcher),
));
Template Embedding



Hello <?php echo $name ?>

<?php $this->render('embedded', array('name' => $name)) ?>

<?php $this->render('smarty:embedded') ?>
Template Inheritance
<?php $this->decorator('layout') ?>

Hello <?php echo $name ?>

<html>
  <head>
  </head>
  <body>
    <?php $this->output('content') ?>
  </body>
</html>
Template Slots
<html>
  <head>
    <title><?php $this->output('title') ?></title>
  </head>
  <body>
    <?php $this->output('content') ?>
  </body>
</html>

<?php $this->set('title', 'Hello World! ') ?>

<?php $this->start('title') ?>
  Hello World!
<?php $this->stop() ?>
Template Multiple Inheritance



A layout can be decorated by another layout

       Each layout can override slots
Templating: An example
CMS Templating
•  Imagine a CMS with the following features:
   –  The CMS comes bundled with default templates
   –  The developer can override default templates for a specific project
   –  The webmaster can override some templates
•  The CMS and developer templates are stored on the filesystem and are
   written with pure PHP code
•  The webmaster templates are stored in a database and are written in a
   simple templating language: Hello {{ name }}
CMS Templating
•  The CMS has several built-in sections and pages
   –  Each page is decorated by a layout, depending on the section
   –  Each section layout is decorated by a base layout


cms/templates/                          project/templates/
  base.php                                base.php
  articles/                               articles/
    layout.php                              layout.php
    article.php                             article.php
                                            content.php
articles/content.php



<h1>{{ title }}</h1>

<p>
  {{ content }}
</p>
articles/article.php


<?php $this->decorator('articles/layout') ?>

<?php $this->set('title', $title) ?>

<?php echo $this->render(
  'user:articles/content',
  array('title' => $title, 'content' => $content)
) ?>
articles/layout.php


<?php $this->decorator('base') ?>

<?php $this->set('title', 'Articles | '.$this->get('title')) ?>

<?php $this->start('head') ?>
  <?php $this->output('head') ?>
  <link rel="stylesheet" type="text/css" media="all" href="/css/
articles.css" />
<?php $this->stop() ?>

<?php $this->output('content') ?>
base.php
<html>
  <head>
    <title>
       <?php $this->output('title') ?>
    </title>
    <?php $this->output('head') ?>
  </head>
  <body>
    <?php $this->output('content') ?>
  </body>
</html>
Template Renderer



$t = new sfTemplateEngine($dispatcher, $loader, array(
  'user' => new ProjectTemplateRenderer($dispatcher),
  'php' => new sfTemplateRendererPhp($dispatcher),
));
Template Renderer
class ProjectTemplateRenderer extends sfTemplateRenderer
{
  public function evaluate($template, array $parameters = array())
  {
    if ($template instanceof sfTemplateStorageFile)
    {
      $template = file_get_contents($template);
    }

    $this->parameters = $parameters;

    return preg_replace_callback('/{{s*(.+?)s*}}/', array($this,
'replaceParameters'), $template);
  }

  public function replaceParameters($matches)
  {
    return isset($this->parameters[$matches[1]]) ? $this->parameters[$matches[1]] :
null;
  }
}
Template Loaders



$loader = new sfTemplateLoaderFilesystem($dispatcher,
  array(
    '/path/to/project/templates/%s.php',
    '/path/to/cms/templates/%s.php'
  ));
Template Loader Chain


$loader = new sfTemplateLoaderChain($dispatcher, array(
  new ProjectTemplateLoader(
     $dispatcher, array('pdo' => $pdo)),
  new sfTemplateLoaderFilesystem($dispatcher, array(
    '/path/to/project/templates/%s.php',
    '/path/to/cms/templates/%s.php'
  )),
));
Database Template Loader
class ProjectTemplateLoader extends sfTemplateLoader
{
  public function load($template)
  {
        $stmt = $this->options['pdo']->prepare('SELECT tpl FROM tpl WHERE name = :name');
        try
        {
          $stmt->execute(array('name' => $template));
          if (count($rows = $stmt->fetchAll(PDO::FETCH_NUM)))
          {
            return $rows[0][0];
          }
        }
        catch (PDOException $e)
        {
        }

        return false;
    }
}
Database Template Loader



$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE tpl (name, tpl)');
$pdo->exec('INSERT INTO tpl (name, tpl) VALUES
("articles/content", "{{ title }} {{ name }}")');
Template Loader Cache



$loader = new sfTemplateLoaderCache(
   $dispatcher,
   $loader,
   new sfFileCache(array('dir' => 'path/to/cache'))
);
$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE tpl (name, tpl)');
$pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content", "{{ title }}
{{ name }}")');

$loader = new sfTemplateLoaderCache(
   $dispatcher,
   new sfTemplateLoaderChain($dispatcher, array(
     new ProjectTemplateLoader($dispatcher, array('pdo' => $pdo)),
     new sfTemplateLoaderFilesystem($dispatcher, array(
       '/path/to/project/templates/%s.php',
       '/path/to/cms/templates/%s.php'
     )),
   )),
   new sfFileCache(array('dir' => 'path/to/cache'))
);

$t = new sfTemplateEngine($dispatcher, $loader, array(
  'user' => new ProjectTemplateRenderer($dispatcher)
));

$t->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
Symfony 2: Dependency Injection Container
« Dependency Injection is where
  components are given their dependencies
   through their constructors, methods, or
            directly into fields. »
http://www.picocontainer.org/injection.html
The Symfony 2 dependency injection container
replaces several symfony 1 concepts
into one integrated system:

   –  sfContext
   –  sfConfiguration
   –  sfConfig
   –  factories.yml
   –  settings.yml / logging.yml / i18n.yml
DI Hello World example
class Message
{
  public function __construct(OutputInterface $output, array $options)
  {
    $this->output = $output;
    $this->options = array_merge(array('with_newline' => false), $options);
  }

    public function say($msg)
    {
       $this->output->render($msg.($this->options['with_newline'] ? "n" : ''));
    }
}
DI Hello World example
interface OutputInterface
{
  public function render($msg);
}

class Output implements OutputInterface
{
  public function render($msg)
  {
    echo $msg;
  }
}

class FancyOutput implements OutputInterface
{
  public function render($msg)
  {
    echo sprintf("033[33m%s033[0m", $msg);
  }
}
DI Hello World example




$output = new FancyOutput();
$message = new Message($output, array('with_newline' => true));
$message->say('Hello World');
A DI container facilitates
objects description and object relationships,
    configures and instantiates objects
DI Container Hello World example

$container = new sfServiceContainer();

$outputDef = new sfServiceDefinition('FancyOutput');
$container->setServiceDefinition('output', $outputDef);

$msgDef = new sfServiceDefinition(
   'Message',
   array(new sfServiceReference('output'), array('with_newline' => true))
);
$container->setServiceDefinition('message', $msgDef);

$container->message->say('Hello World!');
$message = $container->message;


        Get the configuration for the message service

  The Message constructor must be given an output service

          Get the output object from the container

Create a Message object by passing the constructor arguments
$message = $container->message;


                     is roughly equivalent to

                  $output = new FancyOutput();
$message = new Message($output, array('with_newline' => true));!
$container = new sfServiceContainer();

$msgDef = new sfServiceDefinition(
   'Message',
   array(new sfServiceReference('output'), array('with_newline' => true))
);
$outputDef = new sfServiceDefinition('FancyOutput');                        PHP
$container->setServiceDefinition('message', $msgDef);
$container->setServiceDefinition('output', $outputDef);




<services>
  <service id="output" class="FancyOutput" />
                                                                            XML
  <service id="message" class="Message">
    <argument type="service" id="output" />
    <argument type="collection">
      <argument key="with_newline">true</argument>
    </argument>
  </service>
</services>

$container = new sfServiceContainer(new sfServiceLoaderXml());
$container->load('services.xml');
<services>
  <parameters>
    <parameter key="output.class">FancyOutput</parameter>
    <parameter key="message.options" type="collection">
      <parameter key="with_newline">true</parameter>
    </parameter>
  </parameters>

  <service id="output" class="%output.class%" />

  <service id="message" class="Message">
    <argument type="service" id="output" />
    <argument>%message.options%</argument>
  </service>
</services>

$container = new sfServiceContainer(new sfServiceLoaderXml());
$container->load('services.xml');
<services>
 <import resource="config.xml" />

  <service id="output" class="%output.class%" />
  <service id="message" class="Message">
    <argument type="service" id="output" />
    <argument>%message.options%</argument>
  </service>
</services>

<services>
  <parameters>
    <parameter key="output.class">FancyOutput</parameter>
    <parameter key="message.options" type="collection">
      <parameter key="with_newline">true</parameter>
    </parameter>
  </parameters>
</services>

$container = new sfServiceContainer(new sfServiceLoaderXml());
$container->load('services.xml');
<services>
 <import resource="config.yml" class="sfServiceLoaderYamlParameters" />

  <service id="output" class="%output.class%" />
  <service id="message" class="Message">
    <argument type="service" id="output" />
    <argument>%message.options%</argument>
  </service>
</services>

output.class: FancyOutput

message.options:
  with_newline: true

$container = new sfServiceContainer(new sfServiceLoaderXml());
$container->load('services.xml');
$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE tpl (name, tpl)');
$pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content", "{{ title }}
{{ name }}")');

$loader = new sfTemplateLoaderCache(
   $dispatcher,
   new sfTemplateLoaderChain($dispatcher, array(
     new ProjectTemplateLoader($dispatcher, array('pdo' => $pdo)),
     new sfTemplateLoaderFilesystem($dispatcher, array(
       '/path/to/project/templates/%s.php',
       '/path/to/cms/templates/%s.php'
     )),
   )),
   new sfFileCache(array('dir' => 'path/to/cache'))
);

$t = new sfTemplateEngine($dispatcher, $loader, array(
  'user' => new ProjectTemplateRenderer($dispatcher)
));

$t->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
$pdo = new PDO('sqlite::memory:');



<service id="pdo" class="PDO">
  <argument>sqlite::memory:</argument>
</service>
$container = new sfServiceContainer(new sfServiceLoaderXml());
$container->load(dirname(__FILE__).'/cms.xml');

$pdo->exec('CREATE TABLE tpl (name, tpl)');
$pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content",
"{{ title }} {{ name }}")');

echo $container->template->render('articles/article', array('title' => 'Title',
'content' => 'Lorem...'));
<services>
  <import resource="config.yml" class="sfServiceLoaderYamlParameters" />
  <import resource="template_loader.xml" />

  <service id="event_dispatcher" class="sfEventDispatcher" />

  <service id="pdo" class="PDO">
    <argument>sqlite::memory:</argument>
  </service>

  <service id="template_renderer" class="ProjectTemplateRenderer" lazy="true">
    <argument type="service" id="event_dispatcher" />
  </service>

  <service id="template" class="sfTemplateEngine" lazy="true">
    <argument type="service" id="event_dispatcher" />
    <argument type="service" id="template_loader" />
    <argument type="collection">
      <argument type="service" key="user" id="template_renderer" />
    </argument>
  </service>
</services>
<services>
  <service id="template_loader_project" class="ProjectTemplateLoader">
    <argument type="service" id="event_dispatcher" />
    <argument type="collection"><argument type="service" key="pdo" id="pdo" /></argument>
  </service>

  <service id="template_loader_filesystem" class="sfTemplateLoaderFilesystem">
    <argument type="service" id="event_dispatcher" />
    <argument>%template.filesystem_pattern%</argument>
  </service>

  <service id="template_loader_chain" class="sfTemplateLoaderChain">
    <argument type="service" id="event_dispatcher" />
    <argument type="collection">
      <argument type="service" id="template_loader_project" />
      <argument type="service" id="template_loader_filesystem" />
    </argument>
  </service>

  <service id="template_loader_cache" class="sfFileCache">
    <argument type="collection"><argument key="cache_dir">%application.dir%/cache</argument></argument>
  </service>

  <service id="template_loader" class="sfTemplateLoaderCache" lazy="true">
    <argument type="service" id="event_dispatcher" />
    <argument type="service" id="template_loader_chain" />
    <argument type="service" id="template_cache" />
  </service>
</services>
<services>
  <service id="template_loader" class="sfTemplateLoaderCache" lazy="true">
    <argument type="service" id="event_dispatcher" />
    <argument type="service">
      <service class="sfTemplateLoaderChain">
        <argument type="service" id="event_dispatcher" />
        <argument type="collection">
           <argument type="service">
             <service class="ProjectTemplateLoader">
               <argument type="service" id="event_dispatcher" />
               <argument type="collection"><argument type="service" key="pdo" id="pdo" /></argument>
             </service>
           </argument>
           <argument type="service">
             <service class="sfTemplateLoaderFilesystem">
               <argument type="service" id="event_dispatcher" />
               <argument>%template.filesystem_patterns%</argument>
             </service>
           </argument>
        </argument>
      </service>
    </argument>
    <argument type="service">
      <service class="sfFileCache">
        <argument type="collection"><argument key="cache_dir">%application.dir%/cache</argument></
argument>
      </service>
    </argument>
  </service>
</services>
Questions?
Sensio S.A.
     92-98, boulevard Victor Hugo
         92 115 Clichy Cedex
               FRANCE
       Tél. : +33 1 40 99 80 80

               Contact
           Fabien Potencier
    fabien.potencier at sensio.com




  http://www.sensiolabs.com/
http://www.symfony-project.org/
 http://fabien.potencier.org/

More Related Content

What's hot

Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
Kirill Chebunin
 
Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Fabien Potencier
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
Mark Baker
 
Real time voice call integration - Confoo 2012
Real time voice call integration - Confoo 2012Real time voice call integration - Confoo 2012
Real time voice call integration - Confoo 2012Michael Peacock
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 WorldFabien Potencier
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
Flavio Poletti
 
Dealing with Continuous Data Processing, ConFoo 2012
Dealing with Continuous Data Processing, ConFoo 2012Dealing with Continuous Data Processing, ConFoo 2012
Dealing with Continuous Data Processing, ConFoo 2012Michael Peacock
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
Hugo Hamon
 
Php Enums
Php EnumsPhp Enums
PHP 8.1: Enums
PHP 8.1: EnumsPHP 8.1: Enums
PHP 8.1: Enums
Ayesh Karunaratne
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
Javier Eguiluz
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
Konstantin Kudryashov
 
循環参照のはなし
循環参照のはなし循環参照のはなし
循環参照のはなし
Masahiro Honma
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
Konstantin Kudryashov
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
Nikita Popov
 
Dirty Secrets of the PHP SOAP Extension
Dirty Secrets of the PHP SOAP ExtensionDirty Secrets of the PHP SOAP Extension
Dirty Secrets of the PHP SOAP ExtensionAdam Trachtenberg
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
Samuel ROZE
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11
Combell NV
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
James Titcumb
 

What's hot (20)

Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
 
Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Real time voice call integration - Confoo 2012
Real time voice call integration - Confoo 2012Real time voice call integration - Confoo 2012
Real time voice call integration - Confoo 2012
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 
Dealing with Continuous Data Processing, ConFoo 2012
Dealing with Continuous Data Processing, ConFoo 2012Dealing with Continuous Data Processing, ConFoo 2012
Dealing with Continuous Data Processing, ConFoo 2012
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Php Enums
Php EnumsPhp Enums
Php Enums
 
PHP 8.1: Enums
PHP 8.1: EnumsPHP 8.1: Enums
PHP 8.1: Enums
 
dotCloud and go
dotCloud and godotCloud and go
dotCloud and go
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
循環参照のはなし
循環参照のはなし循環参照のはなし
循環参照のはなし
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
 
Dirty Secrets of the PHP SOAP Extension
Dirty Secrets of the PHP SOAP ExtensionDirty Secrets of the PHP SOAP Extension
Dirty Secrets of the PHP SOAP Extension
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 

Viewers also liked

Sympal The Flexible Symfony Cms
Sympal The Flexible Symfony CmsSympal The Flexible Symfony Cms
Sympal The Flexible Symfony Cmsnarkoza
 
What S New In Doctrine
What S New In DoctrineWhat S New In Doctrine
What S New In Doctrinenarkoza
 
Building A Platform From Open Source At Yahoo
Building A Platform From Open Source At YahooBuilding A Platform From Open Source At Yahoo
Building A Platform From Open Source At Yahoo
narkoza
 
Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2narkoza
 
антонич б. і. зелена євангелія. львів, 1938
антонич б. і. зелена євангелія. львів, 1938антонич б. і. зелена євангелія. львів, 1938
антонич б. і. зелена євангелія. львів, 1938narkoza
 
Entrepreneurship support - an entrepreneur's perspective
Entrepreneurship support - an entrepreneur's perspectiveEntrepreneurship support - an entrepreneur's perspective
Entrepreneurship support - an entrepreneur's perspective
Salim Virani
 

Viewers also liked (6)

Sympal The Flexible Symfony Cms
Sympal The Flexible Symfony CmsSympal The Flexible Symfony Cms
Sympal The Flexible Symfony Cms
 
What S New In Doctrine
What S New In DoctrineWhat S New In Doctrine
What S New In Doctrine
 
Building A Platform From Open Source At Yahoo
Building A Platform From Open Source At YahooBuilding A Platform From Open Source At Yahoo
Building A Platform From Open Source At Yahoo
 
Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2
 
антонич б. і. зелена євангелія. львів, 1938
антонич б. і. зелена євангелія. львів, 1938антонич б. і. зелена євангелія. львів, 1938
антонич б. і. зелена євангелія. львів, 1938
 
Entrepreneurship support - an entrepreneur's perspective
Entrepreneurship support - an entrepreneur's perspectiveEntrepreneurship support - an entrepreneur's perspective
Entrepreneurship support - an entrepreneur's perspective
 

Similar to Symfony 2 (PHP Quebec 2009)

Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Fabien Potencier
 
When symfony met promises
When symfony met promises When symfony met promises
When symfony met promises
Marc Morera
 
Using HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationUsing HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless Integration
CiaranMcNulty
 
The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)Fabien Potencier
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207patter
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinar
Yonni Mendes
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
Hisateru Tanaka
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Kacper Gunia
 
Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!
Kacper Gunia
 
Creating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 ComponentsCreating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 Components
Deepak Chandani
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
Lindsay Holmwood
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
chartjes
 
Harmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and PuppetHarmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and Puppet
Achieve Internet
 
Fatc
FatcFatc
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy Code
Rowan Merewood
 
From Code to Cloud - PHP on Red Hat's OpenShift
From Code to Cloud - PHP on Red Hat's OpenShiftFrom Code to Cloud - PHP on Red Hat's OpenShift
From Code to Cloud - PHP on Red Hat's OpenShiftEric D. Schabell
 
Anatomy of a PHP Request ( UTOSC 2010 )
Anatomy of a PHP Request ( UTOSC 2010 )Anatomy of a PHP Request ( UTOSC 2010 )
Anatomy of a PHP Request ( UTOSC 2010 )Joseph Scott
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 Framework
Ryan Weaver
 

Similar to Symfony 2 (PHP Quebec 2009) (20)

Symfony 2 (PHP day 2009)
Symfony 2 (PHP day 2009)Symfony 2 (PHP day 2009)
Symfony 2 (PHP day 2009)
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
 
When symfony met promises
When symfony met promises When symfony met promises
When symfony met promises
 
Using HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationUsing HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless Integration
 
The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinar
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers Cracow
 
Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!
 
Creating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 ComponentsCreating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 Components
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Harmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and PuppetHarmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and Puppet
 
Fatc
FatcFatc
Fatc
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy Code
 
From Code to Cloud - PHP on Red Hat's OpenShift
From Code to Cloud - PHP on Red Hat's OpenShiftFrom Code to Cloud - PHP on Red Hat's OpenShift
From Code to Cloud - PHP on Red Hat's OpenShift
 
Anatomy of a PHP Request ( UTOSC 2010 )
Anatomy of a PHP Request ( UTOSC 2010 )Anatomy of a PHP Request ( UTOSC 2010 )
Anatomy of a PHP Request ( UTOSC 2010 )
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 Framework
 

More from Fabien Potencier

Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Fabien Potencier
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Fabien Potencier
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Fabien Potencier
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Fabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Fabien Potencier
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
Fabien Potencier
 

More from Fabien Potencier (20)

Varnish
VarnishVarnish
Varnish
 
Look beyond PHP
Look beyond PHPLook beyond PHP
Look beyond PHP
 
Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Symfony Components
Symfony ComponentsSymfony Components
Symfony Components
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 

Recently uploaded

Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
RinaMondal9
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Nexer Digital
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
nkrafacyberclub
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 

Recently uploaded (20)

Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 

Symfony 2 (PHP Quebec 2009)

  • 1. Symfony 2 Fabien Potencier
  • 2. Who am I? •  Founder of Sensio –  Web Agency –  Since 1998 –  70 people –  Open-Source Specialists –  Big corporate customers •  Creator and lead developer of symfony
  • 3. How many of you have used symfony? 1.0? 1.1? 1.2?
  • 4. symfony 1.0 •  Started as a glue between existing Open-Source libraries: – Mojavi (heavily modified), Propel, Prado i18n, … •  Borrowed concepts from other languages and frameworks: – Routing, CLI, functional tests, YAML, Rails helpers… •  Added new concepts to the mix – Web Debug Toolbar, admin generator, configuration cascade, …
  • 5. symfony 1.2 •  Decoupled but cohesive components: the symfony platform –  Forms, Routing, Cache, YAML, ORMs, … •  Controller still based on Mojavi –  View, Filter Chain, … •  Could have been named 2.0 ;)
  • 6. symfony platform >= 1.1 2.0 sfRequest sfRouting sfLogger sfI18N sfUser sfResponse sfYAML sfDatabase sfForm sfEventDispatcher sfStorage sfCache sfOutputEscaper sfValidator sfWidget sfCoreAutoload platform
  • 8. $config = sfYaml::load(<<<EOF config: key: value foo: [bar, foobar] bar: { bar: foo } EOF ); print_r($config); echo sfYaml::dump($config);
  • 9. $cache = new sfSQLiteCache(array( 'database' => dirname(__FILE__).'/cache.db' )); $cache->set('foo', 'bar'); echo $cache->get('foo');
  • 10. Symfony 2 is an evolution of symfony 1 •  Same symfony platform •  Different controller implementation •  Oh! Symfony now takes a capital S!!!
  • 11. Symfony 2 main goals Flexibility Fast Smart
  • 12. Symfony 2: New components Dependency Injection Container Templating Framework Controller Handling
  • 13. Symfony 2 •  Not yet available as a full-stack MVC framework •  Some components have already been merged into Symfony 1 –  Event Dispatcher –  Form Framework •  Other new components will soon be released as standalone components: –  Controller Handling –  Templating Framework –  Dependency Injection Container
  • 14. symfony 1: Not fast enough?
  • 15. symfony 1 is one of the slowest framework when you test it against a simple Hello World application
  • 16. 1644& 1544& !"#$%&!'!& 1344& 1144& 1444& ;44& :44& x 19.5 944& 844& Hello World 744& 644& 544& Benchmark 344& ()"#*& 144& x 2.3 +,& -./0)%.&123& 4& based on numbers from http://paul-m-jones.com/?p=315
  • 18. Don’t use symfony for your next « Hello World » website Use PHP ;)
  • 19. By the way, the fastest implemention of a Hello World application with PHP: die('Hello World');
  • 20. But symfony 1 is probably fast enough for your next website
  • 21. … anyway, it is fast enough for Yahoo! Yahoo! Bookmarks sf-to.org/bookmarks Yahoo! Answers sf-to.org/answers delicious.com sf-to.org/delicious
  • 22. … and recently dailymotion.com announced its migration to Symfony sf-to.org/dailymotion
  • 23. Secondmost popular video sharing website One of the top 50 websites in the world 42 million unique users in December
  • 24. …and of course many other smaller websites…
  • 26. Symfony 2 core is so light and flexible that you can easily customize it to have outstanding performance for a Hello World application
  • 27. Symfony 2 core is so light and flexible that its raw performance is outstanding
  • 28. require_once dirname(__FILE__).'/sf20/autoload2/sfCore2Autoload.class.php'; sfCore2Autoload::register(); $app = new HelloApplication(); $app->run()->send(); class HelloApplication { public function __construct() { $this->dispatcher = new sfEventDispatcher(); $this->dispatcher->connect('application.load_controller', array($this, 'loadController')); } public function run() Hello World { $request = new sfWebRequest($this->dispatcher); Symfony 2.0 $handler = new sfRequestHandler($this->dispatcher); with $response = $handler->handle($request); return $response; } public function loadController(sfEvent $event) { $event->setReturnValue(array(array($this, 'hello'), array($this->dispatcher, $event['request']))); return true; } public function hello($dispatcher, $request) { $response = new sfWebResponse($dispatcher); $response->setContent('Hello World'); return $response; } }
  • 29. 7922& 7822& !"#$%&!'!& Hello World ()$*+& 7022& Benchmark 7722& 7222& >22& =22& <22& ;22& :22& ,-./+%-&012& 922& x 3 x 7 822& 022& 3+"#4& 722& 56& ,-./+%-&710& 2& based on numbers from http://paul-m-jones.com/?p=315
  • 31. Twitto: The PHP framework that fits in a tweet •  The fastest framework around? •  Uses some PHP 5.3 new features •  It also fits in a slide… require __DIR__.'/c.php'; if (!is_callable($c = @$_GET['c'] ?: function() { echo 'Woah!'; })) throw new Exception('Error'); $c(); twitt o.org
  • 32. Don’t use Twitto for your next website It is a joke ;)
  • 33. 7 times faster ?! You won’t have such a difference for real applications as most of the time, the limiting factor is not the framework itself
  • 34. 7 times faster ?! •  But raw speed matters because – It demonstrates that the core « kernel » is very light – It allows you to use several Symfony frameworks within a single application with the same behavior but different optimizations: •  One full-stack framework optimized for ease of use (think symfony 1) •  One light framework optimized for speed (think Rails Metal ;))
  • 35. symfony platform 2.0 sfRequestHandler sfRequest sfRouting sfLogger sfI18N sfUser sfTemplate sfResponse sfValidator sfForm sfWidget sfCache sfDatabase sfStorage sfYAML sfOutputEscaper sfServiceContainer sfEventDispatcher sfCoreAutoload platform
  • 36. Symfony 2 kernel: The Request Handler
  • 37. Symfony 2 secret weapon: The Request Handler
  • 38. The Request Handler •  The backbone of Symfony 2 controller implementation •  Class to build web frameworks, not only MVC ones •  Based on a simple assumption: –  The input is a request object –  The output is a response object •  The request object can be anything you want •  The response object must implement a send() method Web Request Web Response Request Handler
  • 39. The Request Handler $handler = new sfRequestHandler($dispatcher); $request = new sfWebRequest($dispatcher); $response = $handler->handle($request); $response->send();
  • 40. The Request Handler •  The sfRequestHandler does several things: –  Notify events –  Execute a callable (the controller) –  Ensure that the Request is converted to a Response object •  The framework is responsible for choosing the controller •  The controller is responsible for the conversion of the Request to a Response
  • 41. class sfRequestHandler { protected $dispatcher = null; public function __construct(sfEventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } sfRequestHandler public function handle($request) { try { return $this->handleRaw($request); s less than 100 } catch (Exception $e) i { $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'application.exception', array('request' => $request, 'exception' => $e))); if ($event->isProcessed()) { lines of PHP return $this->filterResponse($event->getReturnValue(), 'An "application.exception" listener returned a non response object.'); } throw $e; } } code! public function handleRaw($request) { $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'application.request', array('request' => $request))); if ($event->isProcessed()) { return $this->filterResponse($event->getReturnValue(), 'An "application.request" listener returned a non response object.'); } $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'application.load_controller', array('request' => $request))); if (!$event->isProcessed()) { throw new Exception('Unable to load the controller.'); } list($controller, $arguments) = $event->getReturnValue(); if (!is_callable($controller)) { throw new Exception(sprintf('The controller must be a callable (%s).', var_export($controller, true))); } $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'application.controller', array('request' => $request, 'controller' => &$controller, 'arguments' => &$arguments))); if ($event->isProcessed()) { try { return $this->filterResponse($event->getReturnValue(), 'An "application.controller" listener returned a non response object.'); } catch (Exception $e) { $retval = $event->getReturnValue(); } } else { $retval = call_user_func_array($controller, $arguments); } $event = $this->dispatcher->filter(new sfEvent($this, 'application.view'), $retval); return $this->filterResponse($event->getReturnValue(), sprintf('The controller must return a response (instead of %s).', is_object($event->getReturnValue()) ? 'an object of class '.get_class($event->getReturnValue()) : (string) $event->getReturnValue())); } protected function filterResponse($response, $message) { if (!is_object($response) || !method_exists($response, 'send')) { throw new RuntimeException($message); } $event = $this->dispatcher->filter(new sfEvent($this, 'application.response'), $response); $response = $event->getReturnValue(); if (!is_object($response) || !method_exists($response, 'send')) { throw new RuntimeException('An "application.response" listener returned a non response object.'); } return $response; } }
  • 43. application.response As the very last event notified, a listener can modify the Response object just before it is returned to the user
  • 44. application.request •  The very first event notified •  It can act as a short-circuit event •  If one listener returns a Response object, it stops the processing
  • 45. application.load_controller •  Only event for which at least one listener must be connected to •  A listener must return –  A PHP callable (the controller) –  The arguments to pass to the callable
  • 46. application.view The controller must return a Response object except if a listener can convert the controller return value to a Response
  • 47. application.exception The request handler catches all exceptions and give a chance to listeners to return a Response object
  • 48. Request Handler •  Several listeners can be attached to a single event •  Listeners are called in turn sfEventDispatcher load_controller controller response request view exception request sfRequestHandler response
  • 49. require_once dirname(__FILE__).'/sf20/autoload2/sfCore2Autoload.class.php'; sfCore2Autoload::register(); $app = new HelloApplication(); $app->run()->send(); class HelloApplication { public function __construct() { $this->dispatcher = new sfEventDispatcher(); $this->dispatcher->connect('application.load_controller', array($this, 'loadController')); } public function run() Hello World { $request = new sfWebRequest($this->dispatcher); Symfony 2.0 $handler = new sfRequestHandler($this->dispatcher); with $response = $handler->handle($request); return $response; } public function loadController(sfEvent $event) { $event->setReturnValue(array(array($this, 'hello'), array($this->dispatcher, $event['request']))); return true; } public function hello($dispatcher, $request) { $response = new sfWebResponse($dispatcher); $response->setContent('Hello World'); return $response; } }
  • 51. $app = new HelloApplication(); $app->run()->send();
  • 52. public function __construct() { $this->dispatcher = new sfEventDispatcher(); $this->dispatcher->connect( 'application.load_controller', array($this, 'loadController') ); } sfEventDispatcher load_controller controller response request view exception request sfRequestHandler response
  • 53. public function loadController(sfEvent $event) { $event->setReturnValue(array( array($this, 'hello'), array($this->dispatcher, $event['request']) )); return true; }
  • 54. public function hello($dispatcher, $request) { $response = new sfWebResponse($dispatcher); $response->setContent('Hello World'); return $response; }
  • 55. public function run() { $request = new sfWebRequest($this->dispatcher); $handler = new sfRequestHandler($this->dispatcher); $response = $handler->handle($request); return $response; }
  • 56. Case study: dailymotion.com •  The problem: the Dailymotion developers add new features on a nearly everyday basis •  The challenge: Migrate by introducing small doses of Symfony goodness •  The process –  Wrap everything with sfRequestHandler by implementing an application.load_controller listener that calls the old code, based on the request –  Migrate the mod_rewrite rules to the symfony routing –  Add unit and functional tests
  • 57. Symfony 2: The Templating Framework
  • 58. New Templating Framework •  4 components –  Template Engine –  Template Renderers –  Template Loaders –  Template Storages •  Independant library
  • 59. require_once '/path/to/sfCore2Autoload.class.php'; sfCore2Autoload::register(); $dispatcher = new sfEventDispatcher(); $loader = new sfTemplateLoaderFilesystem($dispatcher, '/path/to/templates/%s.php'); $t = new sfTemplateEngine($dispatcher, $loader); echo $t->render('index', array('name' => 'Fabien'));
  • 60. Template Loaders •  No assumption about where and how templates are to be found –  Filesystem –  Database –  Memory –  … •  Template names are « logical » names: $loader = new sfTemplateLoaderFilesystem($dispatcher, '/path/to/templates/%s.php');
  • 61. Template Renderers •  No assumption about the format of the templates •  Template names are prefixed with the renderer name: –  index == php:index –  user:index $t = new sfTemplateEngine($dispatcher, $loader, array( 'user' => new ProjectTemplateRenderer($dispatcher), 'php' => new sfTemplateRendererPhp($dispatcher), ));
  • 62. Template Embedding Hello <?php echo $name ?> <?php $this->render('embedded', array('name' => $name)) ?> <?php $this->render('smarty:embedded') ?>
  • 63. Template Inheritance <?php $this->decorator('layout') ?> Hello <?php echo $name ?> <html> <head> </head> <body> <?php $this->output('content') ?> </body> </html>
  • 64. Template Slots <html> <head> <title><?php $this->output('title') ?></title> </head> <body> <?php $this->output('content') ?> </body> </html> <?php $this->set('title', 'Hello World! ') ?> <?php $this->start('title') ?> Hello World! <?php $this->stop() ?>
  • 65. Template Multiple Inheritance A layout can be decorated by another layout Each layout can override slots
  • 67. CMS Templating •  Imagine a CMS with the following features: –  The CMS comes bundled with default templates –  The developer can override default templates for a specific project –  The webmaster can override some templates •  The CMS and developer templates are stored on the filesystem and are written with pure PHP code •  The webmaster templates are stored in a database and are written in a simple templating language: Hello {{ name }}
  • 68. CMS Templating •  The CMS has several built-in sections and pages –  Each page is decorated by a layout, depending on the section –  Each section layout is decorated by a base layout cms/templates/ project/templates/ base.php base.php articles/ articles/ layout.php layout.php article.php article.php content.php
  • 70. articles/article.php <?php $this->decorator('articles/layout') ?> <?php $this->set('title', $title) ?> <?php echo $this->render( 'user:articles/content', array('title' => $title, 'content' => $content) ) ?>
  • 71. articles/layout.php <?php $this->decorator('base') ?> <?php $this->set('title', 'Articles | '.$this->get('title')) ?> <?php $this->start('head') ?> <?php $this->output('head') ?> <link rel="stylesheet" type="text/css" media="all" href="/css/ articles.css" /> <?php $this->stop() ?> <?php $this->output('content') ?>
  • 72. base.php <html> <head> <title> <?php $this->output('title') ?> </title> <?php $this->output('head') ?> </head> <body> <?php $this->output('content') ?> </body> </html>
  • 73. Template Renderer $t = new sfTemplateEngine($dispatcher, $loader, array( 'user' => new ProjectTemplateRenderer($dispatcher), 'php' => new sfTemplateRendererPhp($dispatcher), ));
  • 74. Template Renderer class ProjectTemplateRenderer extends sfTemplateRenderer { public function evaluate($template, array $parameters = array()) { if ($template instanceof sfTemplateStorageFile) { $template = file_get_contents($template); } $this->parameters = $parameters; return preg_replace_callback('/{{s*(.+?)s*}}/', array($this, 'replaceParameters'), $template); } public function replaceParameters($matches) { return isset($this->parameters[$matches[1]]) ? $this->parameters[$matches[1]] : null; } }
  • 75. Template Loaders $loader = new sfTemplateLoaderFilesystem($dispatcher, array( '/path/to/project/templates/%s.php', '/path/to/cms/templates/%s.php' ));
  • 76. Template Loader Chain $loader = new sfTemplateLoaderChain($dispatcher, array( new ProjectTemplateLoader( $dispatcher, array('pdo' => $pdo)), new sfTemplateLoaderFilesystem($dispatcher, array( '/path/to/project/templates/%s.php', '/path/to/cms/templates/%s.php' )), ));
  • 77. Database Template Loader class ProjectTemplateLoader extends sfTemplateLoader { public function load($template) { $stmt = $this->options['pdo']->prepare('SELECT tpl FROM tpl WHERE name = :name'); try { $stmt->execute(array('name' => $template)); if (count($rows = $stmt->fetchAll(PDO::FETCH_NUM))) { return $rows[0][0]; } } catch (PDOException $e) { } return false; } }
  • 78. Database Template Loader $pdo = new PDO('sqlite::memory:'); $pdo->exec('CREATE TABLE tpl (name, tpl)'); $pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content", "{{ title }} {{ name }}")');
  • 79. Template Loader Cache $loader = new sfTemplateLoaderCache( $dispatcher, $loader, new sfFileCache(array('dir' => 'path/to/cache')) );
  • 80. $pdo = new PDO('sqlite::memory:'); $pdo->exec('CREATE TABLE tpl (name, tpl)'); $pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content", "{{ title }} {{ name }}")'); $loader = new sfTemplateLoaderCache( $dispatcher, new sfTemplateLoaderChain($dispatcher, array( new ProjectTemplateLoader($dispatcher, array('pdo' => $pdo)), new sfTemplateLoaderFilesystem($dispatcher, array( '/path/to/project/templates/%s.php', '/path/to/cms/templates/%s.php' )), )), new sfFileCache(array('dir' => 'path/to/cache')) ); $t = new sfTemplateEngine($dispatcher, $loader, array( 'user' => new ProjectTemplateRenderer($dispatcher) )); $t->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
  • 81. Symfony 2: Dependency Injection Container
  • 82. « Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields. » http://www.picocontainer.org/injection.html
  • 83. The Symfony 2 dependency injection container replaces several symfony 1 concepts into one integrated system: –  sfContext –  sfConfiguration –  sfConfig –  factories.yml –  settings.yml / logging.yml / i18n.yml
  • 84. DI Hello World example class Message { public function __construct(OutputInterface $output, array $options) { $this->output = $output; $this->options = array_merge(array('with_newline' => false), $options); } public function say($msg) { $this->output->render($msg.($this->options['with_newline'] ? "n" : '')); } }
  • 85. DI Hello World example interface OutputInterface { public function render($msg); } class Output implements OutputInterface { public function render($msg) { echo $msg; } } class FancyOutput implements OutputInterface { public function render($msg) { echo sprintf("033[33m%s033[0m", $msg); } }
  • 86. DI Hello World example $output = new FancyOutput(); $message = new Message($output, array('with_newline' => true)); $message->say('Hello World');
  • 87. A DI container facilitates objects description and object relationships, configures and instantiates objects
  • 88. DI Container Hello World example $container = new sfServiceContainer(); $outputDef = new sfServiceDefinition('FancyOutput'); $container->setServiceDefinition('output', $outputDef); $msgDef = new sfServiceDefinition( 'Message', array(new sfServiceReference('output'), array('with_newline' => true)) ); $container->setServiceDefinition('message', $msgDef); $container->message->say('Hello World!');
  • 89. $message = $container->message; Get the configuration for the message service The Message constructor must be given an output service Get the output object from the container Create a Message object by passing the constructor arguments
  • 90. $message = $container->message; is roughly equivalent to $output = new FancyOutput(); $message = new Message($output, array('with_newline' => true));!
  • 91. $container = new sfServiceContainer(); $msgDef = new sfServiceDefinition( 'Message', array(new sfServiceReference('output'), array('with_newline' => true)) ); $outputDef = new sfServiceDefinition('FancyOutput'); PHP $container->setServiceDefinition('message', $msgDef); $container->setServiceDefinition('output', $outputDef); <services> <service id="output" class="FancyOutput" /> XML <service id="message" class="Message"> <argument type="service" id="output" /> <argument type="collection"> <argument key="with_newline">true</argument> </argument> </service> </services> $container = new sfServiceContainer(new sfServiceLoaderXml()); $container->load('services.xml');
  • 92. <services> <parameters> <parameter key="output.class">FancyOutput</parameter> <parameter key="message.options" type="collection"> <parameter key="with_newline">true</parameter> </parameter> </parameters> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> $container = new sfServiceContainer(new sfServiceLoaderXml()); $container->load('services.xml');
  • 93. <services> <import resource="config.xml" /> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> <services> <parameters> <parameter key="output.class">FancyOutput</parameter> <parameter key="message.options" type="collection"> <parameter key="with_newline">true</parameter> </parameter> </parameters> </services> $container = new sfServiceContainer(new sfServiceLoaderXml()); $container->load('services.xml');
  • 94. <services> <import resource="config.yml" class="sfServiceLoaderYamlParameters" /> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> output.class: FancyOutput message.options: with_newline: true $container = new sfServiceContainer(new sfServiceLoaderXml()); $container->load('services.xml');
  • 95. $pdo = new PDO('sqlite::memory:'); $pdo->exec('CREATE TABLE tpl (name, tpl)'); $pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content", "{{ title }} {{ name }}")'); $loader = new sfTemplateLoaderCache( $dispatcher, new sfTemplateLoaderChain($dispatcher, array( new ProjectTemplateLoader($dispatcher, array('pdo' => $pdo)), new sfTemplateLoaderFilesystem($dispatcher, array( '/path/to/project/templates/%s.php', '/path/to/cms/templates/%s.php' )), )), new sfFileCache(array('dir' => 'path/to/cache')) ); $t = new sfTemplateEngine($dispatcher, $loader, array( 'user' => new ProjectTemplateRenderer($dispatcher) )); $t->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
  • 96. $pdo = new PDO('sqlite::memory:'); <service id="pdo" class="PDO"> <argument>sqlite::memory:</argument> </service>
  • 97. $container = new sfServiceContainer(new sfServiceLoaderXml()); $container->load(dirname(__FILE__).'/cms.xml'); $pdo->exec('CREATE TABLE tpl (name, tpl)'); $pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content", "{{ title }} {{ name }}")'); echo $container->template->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
  • 98. <services> <import resource="config.yml" class="sfServiceLoaderYamlParameters" /> <import resource="template_loader.xml" /> <service id="event_dispatcher" class="sfEventDispatcher" /> <service id="pdo" class="PDO"> <argument>sqlite::memory:</argument> </service> <service id="template_renderer" class="ProjectTemplateRenderer" lazy="true"> <argument type="service" id="event_dispatcher" /> </service> <service id="template" class="sfTemplateEngine" lazy="true"> <argument type="service" id="event_dispatcher" /> <argument type="service" id="template_loader" /> <argument type="collection"> <argument type="service" key="user" id="template_renderer" /> </argument> </service> </services>
  • 99. <services> <service id="template_loader_project" class="ProjectTemplateLoader"> <argument type="service" id="event_dispatcher" /> <argument type="collection"><argument type="service" key="pdo" id="pdo" /></argument> </service> <service id="template_loader_filesystem" class="sfTemplateLoaderFilesystem"> <argument type="service" id="event_dispatcher" /> <argument>%template.filesystem_pattern%</argument> </service> <service id="template_loader_chain" class="sfTemplateLoaderChain"> <argument type="service" id="event_dispatcher" /> <argument type="collection"> <argument type="service" id="template_loader_project" /> <argument type="service" id="template_loader_filesystem" /> </argument> </service> <service id="template_loader_cache" class="sfFileCache"> <argument type="collection"><argument key="cache_dir">%application.dir%/cache</argument></argument> </service> <service id="template_loader" class="sfTemplateLoaderCache" lazy="true"> <argument type="service" id="event_dispatcher" /> <argument type="service" id="template_loader_chain" /> <argument type="service" id="template_cache" /> </service> </services>
  • 100. <services> <service id="template_loader" class="sfTemplateLoaderCache" lazy="true"> <argument type="service" id="event_dispatcher" /> <argument type="service"> <service class="sfTemplateLoaderChain"> <argument type="service" id="event_dispatcher" /> <argument type="collection"> <argument type="service"> <service class="ProjectTemplateLoader"> <argument type="service" id="event_dispatcher" /> <argument type="collection"><argument type="service" key="pdo" id="pdo" /></argument> </service> </argument> <argument type="service"> <service class="sfTemplateLoaderFilesystem"> <argument type="service" id="event_dispatcher" /> <argument>%template.filesystem_patterns%</argument> </service> </argument> </argument> </service> </argument> <argument type="service"> <service class="sfFileCache"> <argument type="collection"><argument key="cache_dir">%application.dir%/cache</argument></ argument> </service> </argument> </service> </services>
  • 102. Sensio S.A. 92-98, boulevard Victor Hugo 92 115 Clichy Cedex FRANCE Tél. : +33 1 40 99 80 80 Contact Fabien Potencier fabien.potencier at sensio.com http://www.sensiolabs.com/ http://www.symfony-project.org/ http://fabien.potencier.org/