SlideShare una empresa de Scribd logo
1 de 104
Descargar para leer sin conexión
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&          !quot;#$%&!'!&

1344&

1144&

1444&

 ;44&

 :44&
                                                                      x 19.5
 944&

 844&


        Hello World
 744&

 644&

 544&    Benchmark
 344&
                                     ()quot;#*&
 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&   !quot;#$%&!'!&
                                                                        Hello World
                      ()$*+&
7022&
                                                                         Benchmark
7722&

7222&

 >22&

 =22&

 <22&

 ;22&

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

 022&
                                                         3+quot;#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 quot;application.exceptionquot; 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 quot;application.requestquot; 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 quot;application.controllerquot; 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 quot;application.responsequot; 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=quot;stylesheetquot; type=quot;text/cssquot; media=quot;allquot; href=quot;/css/
articles.cssquot; />
<?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
(quot;articles/contentquot;, quot;{{ title }} {{ name }}quot;)');
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 (quot;articles/contentquot;, quot;{{ title }}
{{ name }}quot;)');

$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'] ? quot;nquot; : ''));
    }
}
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(quot;033[33m%s033[0mquot;, $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=quot;outputquot; class=quot;FancyOutputquot; />

    <service id=quot;messagequot; class=quot;Messagequot;>
      <argument type=quot;servicequot; id=quot;outputquot; />
      <argument type=quot;collectionquot;>
        <argument key=quot;with_newlinequot;>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=quot;output.classquot;>FancyOutput</parameter>
    <parameter key=quot;message.optionsquot; type=quot;collectionquot;>
      <parameter key=quot;with_newlinequot;>true</parameter>
    </parameter>
  </parameters>

  <services>
    <service id=quot;outputquot; class=quot;%output.class%quot; />

    <service id=quot;messagequot; class=quot;Messagequot;>
      <argument type=quot;servicequot; id=quot;outputquot; />
      <argument>%message.options%</argument>
    </service>
  </services>
</container>

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

  <services>
    <service id=quot;outputquot; class=quot;%output.class%quot; />
    <service id=quot;messagequot; class=quot;Messagequot;>
      <argument type=quot;servicequot; id=quot;outputquot; />
      <argument>%message.options%</argument>
    </service>
  </services>
</container>

<container>
  <parameters>
    <parameter key=quot;output.classquot;>FancyOutput</parameter>
    <parameter key=quot;message.optionsquot; type=quot;collectionquot;>
      <parameter key=quot;with_newlinequot;>true</parameter>
    </parameter>
  </parameters>
</container>

$container = new sfServiceContainerBuilder();
$loader = new sfServiceLoaderFileXml($container);
$loader->load('services.xml');
<services>
 <import resource=quot;config.ymlquot; class=quot;sfServiceLoaderFileYamlquot; />

  <service id=quot;outputquot; class=quot;%output.class%quot; />
  <service id=quot;messagequot; class=quot;Messagequot;>
    <argument type=quot;servicequot; id=quot;outputquot; />
    <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 (quot;articles/contentquot;, quot;{{ title }}
{{ name }}quot;)');

$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=quot;pdoquot; class=quot;PDOquot;>
  <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 (quot;articles/contentquot;,
quot;{{ title }} {{ name }}quot;)');

echo $container->template->render('articles/article', array('title' => 'Title',
'content' => 'Lorem...'));
<container>
  <imports>
    <import resource=quot;config.ymlquot; class=quot;sfServiceLoaderFileYamlquot; />
    <import resource=quot;template_loader.xmlquot; />
  </imports>

  <services>
    <service id=quot;event_dispatcherquot; class=quot;sfEventDispatcherquot; />

    <service id=quot;pdoquot; class=quot;PDOquot;>
      <argument>sqlite::memory:</argument>
    </service>

    <service id=quot;template_rendererquot; class=quot;ProjectTemplateRendererquot; lazy=quot;truequot;>
      <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
    </service>

    <service id=quot;templatequot; class=quot;sfTemplateEnginequot; lazy=quot;truequot;>
      <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
      <argument type=quot;servicequot; id=quot;template_loaderquot; />
      <argument type=quot;collectionquot;>
        <argument type=quot;servicequot; key=quot;userquot; id=quot;template_rendererquot; />
      </argument>
    </service>
  </services>
</container>
<services>
  <service id=quot;template_loader_projectquot; class=quot;ProjectTemplateLoaderquot;>
    <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
    <argument type=quot;collectionquot;><argument type=quot;servicequot; key=quot;pdoquot; id=quot;pdoquot; /></argument>
  </service>

  <service id=quot;template_loader_filesystemquot; class=quot;sfTemplateLoaderFilesystemquot;>
    <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
    <argument>%template.filesystem_pattern%</argument>
  </service>

  <service id=quot;template_loader_chainquot; class=quot;sfTemplateLoaderChainquot;>
    <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
    <argument type=quot;collectionquot;>
      <argument type=quot;servicequot; id=quot;template_loader_projectquot; />
      <argument type=quot;servicequot; id=quot;template_loader_filesystemquot; />
    </argument>
  </service>

  <service id=quot;template_loader_cachequot; class=quot;sfFileCachequot;>
    <argument type=quot;collectionquot;><argument key=quot;cache_dirquot;>%application.dir%/cache</argument></argument>
  </service>

  <service id=quot;template_loaderquot; class=quot;sfTemplateLoaderCachequot; lazy=quot;truequot;>
    <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
    <argument type=quot;servicequot; id=quot;template_loader_chainquot; />
    <argument type=quot;servicequot; id=quot;template_cachequot; />
  </service>
</services>
<services>
  <service id=quot;template_loaderquot; class=quot;sfTemplateLoaderCachequot; lazy=quot;truequot;>
    <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
    <argument type=quot;servicequot;>
      <service class=quot;sfTemplateLoaderChainquot;>
        <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
        <argument type=quot;collectionquot;>
           <argument type=quot;servicequot;>
             <service class=quot;ProjectTemplateLoaderquot;>
               <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
               <argument type=quot;collectionquot;><argument type=quot;servicequot; key=quot;pdoquot; id=quot;pdoquot; /></argument>
             </service>
           </argument>
           <argument type=quot;servicequot;>
             <service class=quot;sfTemplateLoaderFilesystemquot;>
               <argument type=quot;servicequot; id=quot;event_dispatcherquot; />
               <argument>%template.filesystem_patterns%</argument>
             </service>
           </argument>
        </argument>
      </service>
    </argument>
    <argument type=quot;servicequot;>
      <service class=quot;sfFileCachequot;>
        <argument type=quot;collectionquot;><argument key=quot;cache_dirquot;>%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/

Más contenido relacionado

La actualidad más candente

The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of LithiumNate Abele
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Leonardo Proietti
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixturesBill Chang
 
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 PimpleHugo Hamon
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Jakub Zalas
 
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 mockingKonstantin Kudryashov
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownpartsBastian Feder
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of LithiumNate Abele
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteLeonardo Proietti
 
The Beauty and the Beast
The Beauty and the BeastThe Beauty and the Beast
The Beauty and the BeastBastian Feder
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksNate Abele
 
PHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkPHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkG Woo
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium AppsNate Abele
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionNate Abele
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of LithiumNate Abele
 
Doctrine Internals. UnitOfWork
Doctrine Internals. UnitOfWorkDoctrine Internals. UnitOfWork
Doctrine Internals. UnitOfWorkAndrew Yatsenko
 
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
 

La actualidad más candente (20)

The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
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
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
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
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
The Beauty and the Beast
The Beauty and the BeastThe Beauty and the Beast
The Beauty and the Beast
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
PHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkPHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php framework
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of Lithium
 
Doctrine Internals. UnitOfWork
Doctrine Internals. UnitOfWorkDoctrine Internals. UnitOfWork
Doctrine Internals. UnitOfWork
 
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)
 

Similar a Symfony 2.0

Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Fabien Potencier
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Fabien 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 2narkoza
 
Using HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationUsing HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationCiaranMcNulty
 
Socket applications
Socket applicationsSocket applications
Socket applicationsJoão Moura
 
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 webinarYonni Mendes
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi
 
A complete guide to Node.js
A complete guide to Node.jsA complete guide to Node.js
A complete guide to Node.jsPrabin Silwal
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkRyan Weaver
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207patter
 
Deploying Symfony | symfony.cat
Deploying Symfony | symfony.catDeploying Symfony | symfony.cat
Deploying Symfony | symfony.catPablo Godel
 
LISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsLISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsTobias Oetiker
 
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 ComponentsDeepak Chandani
 

Similar a Symfony 2.0 (20)

Symfony 2 (PHP day 2009)
Symfony 2 (PHP day 2009)Symfony 2 (PHP day 2009)
Symfony 2 (PHP day 2009)
 
Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
 
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
 
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)
 
Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Using HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless IntegrationUsing HttpKernelInterface for Painless Integration
Using HttpKernelInterface for Painless Integration
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
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
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8
 
A complete guide to Node.js
A complete guide to Node.jsA complete guide to Node.js
A complete guide to Node.js
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 Framework
 
Dancing with websocket
Dancing with websocketDancing with websocket
Dancing with websocket
 
Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Deploying Symfony | symfony.cat
Deploying Symfony | symfony.catDeploying Symfony | symfony.cat
Deploying Symfony | symfony.cat
 
LISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsLISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial Handouts
 
PSGI/Plack OSDC.TW
PSGI/Plack OSDC.TWPSGI/Plack OSDC.TW
PSGI/Plack OSDC.TW
 
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
 

Más de GrUSP

REST e Resource Oriented Architectures
REST e Resource Oriented ArchitecturesREST e Resource Oriented Architectures
REST e Resource Oriented ArchitecturesGrUSP
 
Drupal come framework di sviluppo
Drupal come framework di sviluppoDrupal come framework di sviluppo
Drupal come framework di sviluppoGrUSP
 
PayPal e PHP
PayPal e PHPPayPal e PHP
PayPal e PHPGrUSP
 
Zend Server
Zend ServerZend Server
Zend ServerGrUSP
 
Zend Dojo
Zend DojoZend Dojo
Zend DojoGrUSP
 
PHP & IBM i
PHP & IBM iPHP & IBM i
PHP & IBM iGrUSP
 
Programmazione Ad Eventi In Php
Programmazione Ad Eventi In PhpProgrammazione Ad Eventi In Php
Programmazione Ad Eventi In PhpGrUSP
 
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatoriJoomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatoriGrUSP
 
Memi Beltrame Collaborative Design
Memi Beltrame Collaborative DesignMemi Beltrame Collaborative Design
Memi Beltrame Collaborative DesignGrUSP
 
Mocking Objects Practices
Mocking Objects PracticesMocking Objects Practices
Mocking Objects PracticesGrUSP
 

Más de GrUSP (10)

REST e Resource Oriented Architectures
REST e Resource Oriented ArchitecturesREST e Resource Oriented Architectures
REST e Resource Oriented Architectures
 
Drupal come framework di sviluppo
Drupal come framework di sviluppoDrupal come framework di sviluppo
Drupal come framework di sviluppo
 
PayPal e PHP
PayPal e PHPPayPal e PHP
PayPal e PHP
 
Zend Server
Zend ServerZend Server
Zend Server
 
Zend Dojo
Zend DojoZend Dojo
Zend Dojo
 
PHP & IBM i
PHP & IBM iPHP & IBM i
PHP & IBM i
 
Programmazione Ad Eventi In Php
Programmazione Ad Eventi In PhpProgrammazione Ad Eventi In Php
Programmazione Ad Eventi In Php
 
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatoriJoomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
 
Memi Beltrame Collaborative Design
Memi Beltrame Collaborative DesignMemi Beltrame Collaborative Design
Memi Beltrame Collaborative Design
 
Mocking Objects Practices
Mocking Objects PracticesMocking Objects Practices
Mocking Objects Practices
 

Último

What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 

Último (20)

What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 

Symfony 2.0

  • 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& !quot;#$%&!'!& 1344& 1144& 1444& ;44& :44& x 19.5 944& 844& Hello World 744& 644& 544& Benchmark 344& ()quot;#*& 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& !quot;#$%&!'!& Hello World ()$*+& 7022& Benchmark 7722& 7222& >22& =22& <22& ;22& :22& ,-./+%-&012& 922& x 3 x 7 822& 022& 3+quot;#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 quot;application.exceptionquot; 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 quot;application.requestquot; 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 quot;application.controllerquot; 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 quot;application.responsequot; 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=quot;stylesheetquot; type=quot;text/cssquot; media=quot;allquot; href=quot;/css/ articles.cssquot; /> <?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 (quot;articles/contentquot;, quot;{{ title }} {{ name }}quot;)');
  • 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 (quot;articles/contentquot;, quot;{{ title }} {{ name }}quot;)'); $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'] ? quot;nquot; : '')); } }
  • 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(quot;033[33m%s033[0mquot;, $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=quot;outputquot; class=quot;FancyOutputquot; /> <service id=quot;messagequot; class=quot;Messagequot;> <argument type=quot;servicequot; id=quot;outputquot; /> <argument type=quot;collectionquot;> <argument key=quot;with_newlinequot;>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=quot;output.classquot;>FancyOutput</parameter> <parameter key=quot;message.optionsquot; type=quot;collectionquot;> <parameter key=quot;with_newlinequot;>true</parameter> </parameter> </parameters> <services> <service id=quot;outputquot; class=quot;%output.class%quot; /> <service id=quot;messagequot; class=quot;Messagequot;> <argument type=quot;servicequot; id=quot;outputquot; /> <argument>%message.options%</argument> </service> </services> </container> $container = new sfServiceContainerBuilder(); $loader = new sfServiceLoaderFileXml($container); $loader->load('services.xml');
  • 94. <container> <imports> <import resource=quot;config.xmlquot; /> </imports> <services> <service id=quot;outputquot; class=quot;%output.class%quot; /> <service id=quot;messagequot; class=quot;Messagequot;> <argument type=quot;servicequot; id=quot;outputquot; /> <argument>%message.options%</argument> </service> </services> </container> <container> <parameters> <parameter key=quot;output.classquot;>FancyOutput</parameter> <parameter key=quot;message.optionsquot; type=quot;collectionquot;> <parameter key=quot;with_newlinequot;>true</parameter> </parameter> </parameters> </container> $container = new sfServiceContainerBuilder(); $loader = new sfServiceLoaderFileXml($container); $loader->load('services.xml');
  • 95. <services> <import resource=quot;config.ymlquot; class=quot;sfServiceLoaderFileYamlquot; /> <service id=quot;outputquot; class=quot;%output.class%quot; /> <service id=quot;messagequot; class=quot;Messagequot;> <argument type=quot;servicequot; id=quot;outputquot; /> <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 (quot;articles/contentquot;, quot;{{ title }} {{ name }}quot;)'); $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=quot;pdoquot; class=quot;PDOquot;> <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 (quot;articles/contentquot;, quot;{{ title }} {{ name }}quot;)'); echo $container->template->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
  • 99. <container> <imports> <import resource=quot;config.ymlquot; class=quot;sfServiceLoaderFileYamlquot; /> <import resource=quot;template_loader.xmlquot; /> </imports> <services> <service id=quot;event_dispatcherquot; class=quot;sfEventDispatcherquot; /> <service id=quot;pdoquot; class=quot;PDOquot;> <argument>sqlite::memory:</argument> </service> <service id=quot;template_rendererquot; class=quot;ProjectTemplateRendererquot; lazy=quot;truequot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> </service> <service id=quot;templatequot; class=quot;sfTemplateEnginequot; lazy=quot;truequot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> <argument type=quot;servicequot; id=quot;template_loaderquot; /> <argument type=quot;collectionquot;> <argument type=quot;servicequot; key=quot;userquot; id=quot;template_rendererquot; /> </argument> </service> </services> </container>
  • 100. <services> <service id=quot;template_loader_projectquot; class=quot;ProjectTemplateLoaderquot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> <argument type=quot;collectionquot;><argument type=quot;servicequot; key=quot;pdoquot; id=quot;pdoquot; /></argument> </service> <service id=quot;template_loader_filesystemquot; class=quot;sfTemplateLoaderFilesystemquot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> <argument>%template.filesystem_pattern%</argument> </service> <service id=quot;template_loader_chainquot; class=quot;sfTemplateLoaderChainquot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> <argument type=quot;collectionquot;> <argument type=quot;servicequot; id=quot;template_loader_projectquot; /> <argument type=quot;servicequot; id=quot;template_loader_filesystemquot; /> </argument> </service> <service id=quot;template_loader_cachequot; class=quot;sfFileCachequot;> <argument type=quot;collectionquot;><argument key=quot;cache_dirquot;>%application.dir%/cache</argument></argument> </service> <service id=quot;template_loaderquot; class=quot;sfTemplateLoaderCachequot; lazy=quot;truequot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> <argument type=quot;servicequot; id=quot;template_loader_chainquot; /> <argument type=quot;servicequot; id=quot;template_cachequot; /> </service> </services>
  • 101. <services> <service id=quot;template_loaderquot; class=quot;sfTemplateLoaderCachequot; lazy=quot;truequot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> <argument type=quot;servicequot;> <service class=quot;sfTemplateLoaderChainquot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> <argument type=quot;collectionquot;> <argument type=quot;servicequot;> <service class=quot;ProjectTemplateLoaderquot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> <argument type=quot;collectionquot;><argument type=quot;servicequot; key=quot;pdoquot; id=quot;pdoquot; /></argument> </service> </argument> <argument type=quot;servicequot;> <service class=quot;sfTemplateLoaderFilesystemquot;> <argument type=quot;servicequot; id=quot;event_dispatcherquot; /> <argument>%template.filesystem_patterns%</argument> </service> </argument> </argument> </service> </argument> <argument type=quot;servicequot;> <service class=quot;sfFileCachequot;> <argument type=quot;collectionquot;><argument key=quot;cache_dirquot;>%application.dir%/cache</argument></ argument> </service> </argument> </service> </services>
  • 102.
  • 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/