SlideShare a Scribd company logo
Symfony 2

 Fabien Potencier
Who am I?
•  Founder of Sensio
   –  Web Agency (France and USA)
   –  Since 1998
   –  70 people
   –  Open-Source Specialists
   –  Big corporate customers
   –  Consulting, training, development, web design, …
   –  Main sponsor of symfony and Doctrine


•  Creator and lead developer of symfony
How many of you have used symfony?
         1.0? 1.1? 1.2?
symfony 1.0 – January 2007
•  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 – November 2008


•  Decoupled but cohesive components: the symfony platform

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

•  Controller still based on Mojavi

   –  View, Filter Chain, …
Roadmap
•  1.0 – January 2007
•  1.1 – June 2008
•  1.2 – November 2008
•  1.3 – November 2009
•  Version 2.0 …
•  1.4 – Last 1.X version
  – same as 1.3 but with all deprecated features removed
symfony platform                                 >= 1.1
                                                                                  2.0


    sfRequest    sfRouting     sfLogger   sfI18N    sfUser      sfResponse




sfYAML   sfDatabase   sfForm    sfEventDispatcher   sfStorage     sfCache    sfOutputEscaper



             sfValidator     sfWidget                            sfCoreAutoload
                                                                                   platform
Symfony Components
•  Standalone components
•  Packaged individually
•  Upcoming dedicated website
    –  http://components.symfony-project.org/
•  Dedicated section for each component
•  Dedicated documentation
•  Dedicated Subversion repository
    –  http://svn.symfony-project.com/components/
•  Git mirror
    –  http://github.com/fabpot
•  Already published components:
    –  YAML, Dependency Injection, Event Dispatcher
Symfony 2 is an evolution of symfony 1


•  Same Symfony platform / components

•  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 (done)
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
Second most 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
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
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 ?!
•  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'));
  }



                                                                            Hello World
    public function run()
    {

                                                                                  y Components
      $request = new sfWebRequest($this->dispatcher);

                                                                      with Symfon
      $handler = new sfRequestHandler($this->dispatcher);
      $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') ?>
articles/layout.php



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

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

<?php $this->stylesheets->add('/css/articles.css') ?>

<?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 sfServiceContainerBuilder();

$container->register('output', 'FancyOutput');

$container->
  register('message', 'Message')->
  setArguments(array(new sfServiceReference('output'), array('with_newline' => true)))
;

$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 sfServiceContainerBuilder();

$container->register('output', 'FancyOutput');
$container->
  register('message', 'Message')->
  setArguments(array(new sfServiceReference('output'), array('with_newline' => true)))
;

$container->message->say('Hello World!');
                                                                                         PHP
<container>
  <services>                                                                             XML
    <service id="output" class="FancyOutput" />

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

$container = new sfServiceContainerBuilder();
$loader = new sfServiceLoaderFileXml($container);
$loader->load('services.xml');
$container = new sfServiceContainerBuilder();

$container->register('output', 'FancyOutput');
$container->
  register('message', 'Message')->
  setArguments(array(new sfServiceReference('output'), array('with_newline' => true)))
;

$container->message->say('Hello World!');
                                                                                         PHP
services:
  output: { class: FancyOutput }                                                         YAML
  message:
    class: Message
    arguments:
      - @output
      - { with_newline: true }

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

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

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

$container = new sfServiceContainerBuilder();
$loader = new sfServiceLoaderFileXml($container);
$loader->load('services.xml');
<container>
  <imports>
    <import resource="config.xml" />
  </imports>

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

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

$container = new sfServiceContainerBuilder();
$loader = new sfServiceLoaderFileXml($container);
$loader->load('services.xml');
<services>
 <import resource="config.yml" class="sfServiceLoaderFileYaml" />

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

parameters:
  output.class: FancyOutput

  message.options: { with_newline: true }

$container = new sfServiceContainerBuilder();
$loader = new sfServiceLoaderFileXml($container);
$loader->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 sfServiceContainerBuilder();
$loader = new sfServiceLoaderFileXml($container);
$loader->load('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...'));
<container>
  <imports>
    <import resource="config.yml" class="sfServiceLoaderFileYaml" />
    <import resource="template_loader.xml" />
  </imports>

  <services>
    <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>
</container>
<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>
Symfony 2 (PHP day 2009)
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/
Ad

More Related Content

What's hot (20)

dotCloud and go
dotCloud and godotCloud and go
dotCloud and go
Flavio Poletti
 
Developing apps using Perl
Developing apps using PerlDeveloping apps using Perl
Developing apps using Perl
Anatoly Sharifulin
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perl
deepfountainconsulting
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
diego_k
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
Shmuel Fomberg
 
Smolder @Silex
Smolder @SilexSmolder @Silex
Smolder @Silex
Jeen Lee
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
bpmedley
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
Domenic Denicola
 
Any event intro
Any event introAny event intro
Any event intro
qiang
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
Flavio Poletti
 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
Fabien Potencier
 
A Gentle Introduction to Event Loops
A Gentle Introduction to Event LoopsA Gentle Introduction to Event Loops
A Gentle Introduction to Event Loops
deepfountainconsulting
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
Flavio Poletti
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
julien pauli
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Ville Mattila
 
When symfony met promises
When symfony met promises When symfony met promises
When symfony met promises
Marc Morera
 
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
clkao
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Kacper Gunia
 
Using ngx_lua in UPYUN
Using ngx_lua in UPYUNUsing ngx_lua in UPYUN
Using ngx_lua in UPYUN
Cong Zhang
 
Fabric Python Lib
Fabric Python LibFabric Python Lib
Fabric Python Lib
Simone Federici
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perl
deepfountainconsulting
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
diego_k
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
Shmuel Fomberg
 
Smolder @Silex
Smolder @SilexSmolder @Silex
Smolder @Silex
Jeen Lee
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
bpmedley
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
Domenic Denicola
 
Any event intro
Any event introAny event intro
Any event intro
qiang
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Ville Mattila
 
When symfony met promises
When symfony met promises When symfony met promises
When symfony met promises
Marc Morera
 
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
clkao
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Kacper Gunia
 
Using ngx_lua in UPYUN
Using ngx_lua in UPYUNUsing ngx_lua in UPYUN
Using ngx_lua in UPYUN
Cong Zhang
 

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

Symfony 2.0
Symfony 2.0Symfony 2.0
Symfony 2.0
GrUSP
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
Fabien Potencier
 
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
Fabien Potencier
 
Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2
narkoza
 
Symfony As A Platform (Symfony Camp 2007)
Symfony As A Platform (Symfony Camp 2007)Symfony As A Platform (Symfony Camp 2007)
Symfony As A Platform (Symfony Camp 2007)
Fabien Potencier
 
Using HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationUsing HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless Integration
CiaranMcNulty
 
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
 
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
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
patter
 
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
 
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
 
A complete guide to Node.js
A complete guide to Node.jsA complete guide to Node.js
A complete guide to Node.js
Prabin Silwal
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi
 
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
 
LISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsLISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial Handouts
Tobias Oetiker
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?
Christophe Porteneuve
 
Mojolicious
MojoliciousMojolicious
Mojolicious
Marcus Ramberg
 
Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
Emanuele DelBono
 
Socket applications
Socket applicationsSocket applications
Socket applications
João Moura
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
Ben Lin
 
Symfony 2.0
Symfony 2.0Symfony 2.0
Symfony 2.0
GrUSP
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
Fabien Potencier
 
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
Fabien Potencier
 
Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2
narkoza
 
Symfony As A Platform (Symfony Camp 2007)
Symfony As A Platform (Symfony Camp 2007)Symfony As A Platform (Symfony Camp 2007)
Symfony As A Platform (Symfony Camp 2007)
Fabien Potencier
 
Using HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationUsing HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless Integration
CiaranMcNulty
 
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
 
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
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
patter
 
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
 
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
 
A complete guide to Node.js
A complete guide to Node.jsA complete guide to Node.js
A complete guide to Node.js
Prabin Silwal
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi
 
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
 
LISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsLISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial Handouts
Tobias Oetiker
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?
Christophe Porteneuve
 
Socket applications
Socket applicationsSocket applications
Socket applications
João Moura
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
Ben Lin
 
Ad

More from Fabien Potencier (20)

Varnish
VarnishVarnish
Varnish
Fabien Potencier
 
Look beyond PHP
Look beyond PHPLook beyond PHP
Look beyond PHP
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.4
Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
Fabien Potencier
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
Fabien 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.3
Fabien Potencier
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
Fabien Potencier
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
Fabien Potencier
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
Fabien Potencier
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
Fabien Potencier
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
Fabien Potencier
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
Fabien Potencier
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
Fabien Potencier
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
Fabien Potencier
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
Fabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
Fabien Potencier
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
Fabien Potencier
 
Symfony Components
Symfony ComponentsSymfony Components
Symfony Components
Fabien Potencier
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
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.4
Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
Fabien 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.3
Fabien Potencier
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
Fabien Potencier
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
Fabien Potencier
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
Fabien Potencier
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
Fabien Potencier
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
Fabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
Fabien Potencier
 
Ad

Recently uploaded (20)

IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Semantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AISemantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AI
artmondano
 
TrsLabs Consultants - DeFi, WEb3, Token Listing
TrsLabs Consultants - DeFi, WEb3, Token ListingTrsLabs Consultants - DeFi, WEb3, Token Listing
TrsLabs Consultants - DeFi, WEb3, Token Listing
Trs Labs
 
MINDCTI revenue release Quarter 1 2025 PR
MINDCTI revenue release Quarter 1 2025 PRMINDCTI revenue release Quarter 1 2025 PR
MINDCTI revenue release Quarter 1 2025 PR
MIND CTI
 
Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdfThe Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
Abi john
 
Web and Graphics Designing Training in Rajpura
Web and Graphics Designing Training in RajpuraWeb and Graphics Designing Training in Rajpura
Web and Graphics Designing Training in Rajpura
Erginous Technology
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes
 
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
BookNet Canada
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Top 10 IT Help Desk Outsourcing Services
Top 10 IT Help Desk Outsourcing ServicesTop 10 IT Help Desk Outsourcing Services
Top 10 IT Help Desk Outsourcing Services
Infrassist Technologies Pvt. Ltd.
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
Procurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptxProcurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptx
Jon Hansen
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
Mastering Advance Window Functions in SQL.pdf
Mastering Advance Window Functions in SQL.pdfMastering Advance Window Functions in SQL.pdf
Mastering Advance Window Functions in SQL.pdf
Spiral Mantra
 
HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Semantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AISemantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AI
artmondano
 
TrsLabs Consultants - DeFi, WEb3, Token Listing
TrsLabs Consultants - DeFi, WEb3, Token ListingTrsLabs Consultants - DeFi, WEb3, Token Listing
TrsLabs Consultants - DeFi, WEb3, Token Listing
Trs Labs
 
MINDCTI revenue release Quarter 1 2025 PR
MINDCTI revenue release Quarter 1 2025 PRMINDCTI revenue release Quarter 1 2025 PR
MINDCTI revenue release Quarter 1 2025 PR
MIND CTI
 
Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdfThe Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
Abi john
 
Web and Graphics Designing Training in Rajpura
Web and Graphics Designing Training in RajpuraWeb and Graphics Designing Training in Rajpura
Web and Graphics Designing Training in Rajpura
Erginous Technology
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes
 
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
BookNet Canada
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
Procurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptxProcurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptx
Jon Hansen
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
Mastering Advance Window Functions in SQL.pdf
Mastering Advance Window Functions in SQL.pdfMastering Advance Window Functions in SQL.pdf
Mastering Advance Window Functions in SQL.pdf
Spiral Mantra
 
HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 

Symfony 2 (PHP day 2009)

  • 1. Symfony 2 Fabien Potencier
  • 2. Who am I? •  Founder of Sensio –  Web Agency (France and USA) –  Since 1998 –  70 people –  Open-Source Specialists –  Big corporate customers –  Consulting, training, development, web design, … –  Main sponsor of symfony and Doctrine •  Creator and lead developer of symfony
  • 3. How many of you have used symfony? 1.0? 1.1? 1.2?
  • 4. symfony 1.0 – January 2007 •  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 – November 2008 •  Decoupled but cohesive components: the symfony platform –  Forms, Routing, Cache, YAML, ORMs, … •  Controller still based on Mojavi –  View, Filter Chain, …
  • 6. Roadmap •  1.0 – January 2007 •  1.1 – June 2008 •  1.2 – November 2008 •  1.3 – November 2009 •  Version 2.0 … •  1.4 – Last 1.X version – same as 1.3 but with all deprecated features removed
  • 7. symfony platform >= 1.1 2.0 sfRequest sfRouting sfLogger sfI18N sfUser sfResponse sfYAML sfDatabase sfForm sfEventDispatcher sfStorage sfCache sfOutputEscaper sfValidator sfWidget sfCoreAutoload platform
  • 8. Symfony Components •  Standalone components •  Packaged individually •  Upcoming dedicated website –  http://components.symfony-project.org/ •  Dedicated section for each component •  Dedicated documentation •  Dedicated Subversion repository –  http://svn.symfony-project.com/components/ •  Git mirror –  http://github.com/fabpot •  Already published components: –  YAML, Dependency Injection, Event Dispatcher
  • 9. Symfony 2 is an evolution of symfony 1 •  Same Symfony platform / components •  Different controller implementation •  Oh! Symfony now takes a capital S!!!
  • 10. Symfony 2 main goals Flexibility Fast Smart
  • 11. Symfony 2: New components Dependency Injection Container Templating Framework Controller Handling
  • 12. 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 (done)
  • 13. symfony 1: Not fast enough?
  • 14. symfony 1 is one of the slowest framework when you test it against a simple Hello World application
  • 15. 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
  • 17. Don’t use symfony for your next « Hello World » website Use PHP ;)
  • 18. By the way, the fastest implemention of a Hello World application with PHP: die('Hello World');
  • 19. But symfony 1 is probably fast enough for your next website
  • 20. … 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
  • 21. … and recently dailymotion.com announced its migration to Symfony sf-to.org/dailymotion
  • 22. Second most popular video sharing website One of the top 50 websites in the world 42 million unique users in December
  • 23. …and of course many other smaller websites…
  • 25. Symfony 2 core is so light and flexible that you can easily customize it to have outstanding performance for a Hello World application
  • 26. Symfony 2 core is so light and flexible that its raw performance is outstanding
  • 27. 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; } }
  • 28. 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
  • 29. 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
  • 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 ?! •  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 ;))
  • 34. symfony platform 2.0 sfRequestHandler sfRequest sfRouting sfLogger sfI18N sfUser sfTemplate sfResponse sfValidator sfForm sfWidget sfCache sfDatabase sfStorage sfYAML sfOutputEscaper sfServiceContainer sfEventDispatcher sfCoreAutoload platform
  • 35. Symfony 2 kernel: The Request Handler
  • 36. Symfony 2 secret weapon: The Request Handler
  • 37. 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
  • 38. The Request Handler $handler = new sfRequestHandler($dispatcher); $request = new sfWebRequest($dispatcher); $response = $handler->handle($request); $response->send();
  • 39. 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
  • 40. 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; } }
  • 42. application.response As the very last event notified, a listener can modify the Response object just before it is returned to the user
  • 43. 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
  • 44. 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
  • 45. application.view The controller must return a Response object except if a listener can convert the controller return value to a Response
  • 46. application.exception The request handler catches all exceptions and give a chance to listeners to return a Response object
  • 47. 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
  • 48. 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')); } Hello World public function run() { y Components $request = new sfWebRequest($this->dispatcher); with Symfon $handler = new sfRequestHandler($this->dispatcher); $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; } }
  • 50. $app = new HelloApplication(); $app->run()->send();
  • 51. 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
  • 52. public function loadController(sfEvent $event) { $event->setReturnValue(array( array($this, 'hello'), array($this->dispatcher, $event['request']) )); return true; }
  • 53. public function hello($dispatcher, $request) { $response = new sfWebResponse($dispatcher); $response->setContent('Hello World'); return $response; }
  • 54. public function run() { $request = new sfWebRequest($this->dispatcher); $handler = new sfRequestHandler($this->dispatcher); $response = $handler->handle($request); return $response; }
  • 55. 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
  • 56. Symfony 2: The Templating Framework
  • 57. New Templating Framework •  4 components –  Template Engine –  Template Renderers –  Template Loaders –  Template Storages •  Independant library
  • 58. 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'));
  • 59. 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');
  • 60. 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), ));
  • 61. Template Embedding Hello <?php echo $name ?> <?php $this->render('embedded', array('name' => $name)) ?> <?php $this->render('smarty:embedded') ?>
  • 62. Template Inheritance <?php $this->decorator('layout') ?> Hello <?php echo $name ?> <html> <head> </head> <body> <?php $this->output('content') ?> </body> </html>
  • 63. 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() ?>
  • 64. Template Multiple Inheritance A layout can be decorated by another layout Each layout can override slots
  • 66. 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 }}
  • 67. 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
  • 69. 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) ) ?>
  • 70. 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') ?>
  • 71. articles/layout.php <?php $this->decorator('base') ?> <?php $this->set('title', 'Articles | '.$this->get('title')) ?> <?php $this->stylesheets->add('/css/articles.css') ?> <?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 sfServiceContainerBuilder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new sfServiceReference('output'), array('with_newline' => true))) ; $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 sfServiceContainerBuilder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new sfServiceReference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!'); PHP <container> <services> XML <service id="output" class="FancyOutput" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument type="collection"> <argument key="with_newline">true</argument> </argument> </service> </services> </container> $container = new sfServiceContainerBuilder(); $loader = new sfServiceLoaderFileXml($container); $loader->load('services.xml');
  • 92. $container = new sfServiceContainerBuilder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new sfServiceReference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!'); PHP services: output: { class: FancyOutput } YAML message: class: Message arguments: - @output - { with_newline: true } $container = new sfServiceContainerBuilder(); $loader = new sfServiceLoaderFileYaml($container); $loader->load('services.yml');
  • 93. <container> <parameters> <parameter key="output.class">FancyOutput</parameter> <parameter key="message.options" type="collection"> <parameter key="with_newline">true</parameter> </parameter> </parameters> <services> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> </container> $container = new sfServiceContainerBuilder(); $loader = new sfServiceLoaderFileXml($container); $loader->load('services.xml');
  • 94. <container> <imports> <import resource="config.xml" /> </imports> <services> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> </container> <container> <parameters> <parameter key="output.class">FancyOutput</parameter> <parameter key="message.options" type="collection"> <parameter key="with_newline">true</parameter> </parameter> </parameters> </container> $container = new sfServiceContainerBuilder(); $loader = new sfServiceLoaderFileXml($container); $loader->load('services.xml');
  • 95. <services> <import resource="config.yml" class="sfServiceLoaderFileYaml" /> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> parameters: output.class: FancyOutput message.options: { with_newline: true } $container = new sfServiceContainerBuilder(); $loader = new sfServiceLoaderFileXml($container); $loader->load('services.xml');
  • 96. $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...'));
  • 97. $pdo = new PDO('sqlite::memory:'); <service id="pdo" class="PDO"> <argument>sqlite::memory:</argument> </service>
  • 98. $container = new sfServiceContainerBuilder(); $loader = new sfServiceLoaderFileXml($container); $loader->load('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...'));
  • 99. <container> <imports> <import resource="config.yml" class="sfServiceLoaderFileYaml" /> <import resource="template_loader.xml" /> </imports> <services> <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> </container>
  • 100. <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>
  • 101. <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>
  • 104. 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/