SlideShare a Scribd company logo
1 of 118
Download to read offline
Symfony 2.0 on PHP 5.3!

Fabien Potencier
Fabien Potencier
•  Serial entrepreneur and developer by passion
•  Founder of Sensio (in 1998)
   –  A services and consulting company
      specialized in Web technologies
      and Internet marketing (France and USA)
   –  70 people
   –  Open-Source specialists
   –  Big corporate customers
   –  Consulting, training, development, web design, … and more
   –  Sponsor of a lot of Open-Source projects
      like symfony and Doctrine
Fabien Potencier
•  Creator and lead developer of symfony…
•  and creator and lead developer of some more:
   –  symfony components
   –  Swift Mailer : Powerful component based mailing library for PHP
   –  Twig : Fexible, fast, and secure template language for PHP
   –  Pirum : Simple PEAR Channel Server Manager
   –  Sismo : PHP continuous integration server
   –  Lime : Easy to use unit testing library for PHP
   –  Twitto : A web framework in a tweet
   –  Twittee : A Dependency Injection Container in a tweet
   –  Pimple : A small PHP 5.3 dependency injection container
Fabien Potencier

•  Read my technical blog: http://fabien.potencier.org/

•  Follow me on Twitter: @fabpot

•  Fork my code on Github: http://github.com/fabpot/
How many of you have used symfony?
      1.0? 1.1? 1.2? 1.3?
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
•  1.4 – Last 1.X version (LTS release : 3 years of support)
   – same as 1.3 but without deprecated features
•  Version 2.0 – Hopefully at the end of 2010
Symfony 2.0

•  PHP 5.3 only - http://sf-to.org/sf20onPHP53

•  Same Symfony core components (updated for PHP 5.3)

•  Different controller implementation

•  Oh! Symfony now takes a capital S!!!
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, Templating
Symfony Components
•  Existing components
   –  will soon be released as 1.0 (for PHP 5.2)

   –  will then be migrated to PHP 5.3 (mainly introducing namespaces)

•  New components:
   –  will work with PHP 5.3 only right from the start
Symfony 2 main goals


   Flexibility
       Fast
      Smart
Symfony 2 core


       Event Dispatcher
Dependency Injection Container
     Controller Handling
Symfony 2
•  Obviously 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 be released as standalone components:
   –  Controller Handling
   –  Output Escaping                           will be
                                              migrated to
   –  Forms
                                              PHP 5.3 soon
   –  Routing
   –  Templating Framework (done)
   –  Dependency Injection Container (done)
symfony 1.X
Not fast enough?
symfony 1 is
  one of the slowest framework
     when you test it against
a simple Hello World application
1644&

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

         1344&


Hello World
        1144&


 Benchmark
        1444&

          ;44&
                                                                              x 19.5
          :44&

          944&

          844&

          744&

          644&

          544&

          344&
                                                  ()"#*&                               x 2.3
          144&                                                          +,&       -./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 30 websites in the world
     59 million unique users in July 2009
…and of course
many other smaller websites…
Symfony 2
Faster?
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();


                                                                                          Hello World
$app = new HelloApplication();
$app->run()->send();
                                                                                                         0
class HelloApplication                                                                  wit h Symfony 2.
{
  public function __construct()
  {
    $this->dispatcher = new sfEventDispatcher();
    $this->dispatcher->connect('application.load_controller', array($this, 'loadController'));
  }

  public function run()

                                                                                             OUTDATED
  {
    $request = new sfWebRequest($this->dispatcher);
    $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 __DIR__.'/lib/Symfony/Core/ClassLoader.php';

use   SymfonyComponentsEventDispatcherEvent;

                                                                     Hello World
use   SymfonyComponentsEventDispatcherEventDispatcher;
use   SymfonyComponentsRequestHandlerRequestHandler;

                                                                         ymfony 2.0
use   SymfonyComponentsRequestHandlerRequest;
use   SymfonyComponentsRequestHandlerResponse;
                                                                   with S
$classLoader = new ClassLoader('Symfony', __DIR__.'/lib');
$classLoader->register();                                             on PHP 5.3
$dispatcher = new EventDispatcher();
$dispatcher->connect('core.load_controller', function (Event $event)
{
  $event->setReturnValue(array(
    function (Request $request)
    {
       return new Response('Hello '.$request->getQueryParameter('name'));
    },
    array($event['request'])
  ));

  return true;
});

$request = new Request();
$request->setQueryParameters(array('name' => 'Fabien'));

$handler = new RequestHandler($dispatcher);
$response = $handler->handle($request);
$response->send();
7922&

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

7722&

7222&

 >22&

 =22&

 <22&                           Symfony 2.0 on PHP 5.3
 ;22&

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

 022&
                                               3+"#4&
 722&                                                     56&    ,-./+%-&710&
   2&


        based on numbers from http://paul-m-jones.com/?p=315
10 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
… and PHP 5.3 helps
•  The Hello World code on PHP 5.3 is 50% faster than the one on PHP 5.2
   (for the same code!)
•  All frameworks will benefit from some speed improvements
•  Again, real applications won’t have such a speed difference just by
   upgrading to PHP 5.3
                                         !
                     Upgrad e to PHP 5.3
                                          e
                     It mean s performanc
                     improveme nts for FREE
10 times faster?!
•  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 ;))
How many of you
have used PHP 5.3?
This presentation is full of


                  
… the new PHP developer best friend
Namespaces

from sfRequest to SymfonyCoreRequest

use SymfonyCoreRequest;

$request = new Request();
Anonymous Functions

$a = function ($msg)
{
  echo $msg;
}

$a('Hello World');
Symfony 2
The Event Dispatcher
EventDispatcher
 •  Observer Design Pattern
 •  Based on Cocoa Notification Center
// sfI18N
$callback = array($this, 'listenToChangeCultureEvent');
$dispatcher->connect('user.change_culture', $callback);

// sfUser
$event = new Event($this, 'user.change_culture', array('culture' =>
$culture));
$dispatcher->notify($event);
 •    I18N and User are decoupled
 •    An event is defined by a unique string
 •    « Anybody » can listen to any event
 •    You can notify existing events or create new ones easily
require __DIR__.'/lib/Symfony/Core/ClassLoader.php';

use SymfonyComponentsEventDispatcherEvent;
use SymfonyComponentsEventDispatcherEventDispatcher;

$classLoader = new ClassLoader('Symfony', __DIR__.'/lib');
$classLoader->register();

$dispatcher = new EventDispatcher();

$listener = function ($event)
{
   echo sprintf("Hello %s!n", $event['name']);
};
$dispatcher->connect('foo', $listener);       Can be any PHP callable

$event = new Event(null, 'foo', array('name' => 'Fabien'));
$dispatcher->notify($event);
Symfony 2
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
The Request Handler
use SymfonyComponentsRequestHandlerRequestHandler;
use SymfonyComponentsRequestHandlerRequest;

$handler = new RequestHandler($dispatcher);

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

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

   –  Executes a callable (the controller)

   –  Ensures 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
namespace SymfonyComponentsRequestHandler;

use SymfonyComponentsEventDispatcherEvent;
use SymfonyComponentsEventDispatcherEventDispatcher;

class RequestHandler
{
  protected $dispatcher = null;

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

    public function handle(RequestInterface $request)
    {
      try
      {
        return $this->handleRaw($request);
      }
      catch (Exception $e)
      {
        // exception




                                                                                                                                                                                                                                    RequestHandler is
        $event = $this->dispatcher->notifyUntil(new Event($this, 'core.exception', array('request' => $request, 'exception' => $e)));
        if ($event->isProcessed())
        {
          return $this->filterResponse($event->getReturnValue(), 'An "core.exception" listener returned a non response object.');
        }




                                                                                                                                                                                                                                   less than 100 lines
            throw $e;
        }
    }

    public function handleRaw(RequestInterface $request)
    {




                                                                                                                                                                                                                                       of PHP code!
      // request
      $event = $this->dispatcher->notifyUntil(new Event($this, 'core.request', array('request' => $request)));
      if ($event->isProcessed())
      {
        return $this->filterResponse($event->getReturnValue(), 'An "core.request" listener returned a non response object.');
      }

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

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

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

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

        // view
        $event = $this->dispatcher->filter(new Event($this, 'core.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 (!$response instanceof ResponseInterface)
      {
        throw new RuntimeException($message);
      }

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

        if (!$response instanceof ResponseInterface)
        {
          throw new RuntimeException('An "core.response" listener returned a non response object.');
        }

        return $response;
    }

    public function getEventDispatcher()
    {
      return $this->dispatcher;
    }
}
Request Handler Events
core.request

core.load_controller

core.controller

core.view

core.response

core.exception
core.response




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

$dispatcher->connect('core.response',
  function (Event $event, Response $response)
  {
    $response->setContent(
       $response->getContent().
       'The Web Debug Toolbar'
    );
                          Content of the
                          response is changed
      return $response;
  }
);
core.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
core.request

$dispatcher->connect('core.request',
  function (Event $event)
  {
    $event->setReturnValue(
       new Response('Website unavailable...')
    );
                            Don’t go any further!
      return true;
  }
);
core.load_controller



•  The 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
core.load_controller

$dispatcher->connect('core.load_controller',
  function (Event $event)
  {
    $event->setReturnValue(array(
      function ()
      {
         return new Response('Hello World');
      },
      array()                            Whatever the request,
    ));                                  always return Hello World

      return true;
  }
);
core.view




The controller must return a Response object
        except if a listener can convert
  the controller returned value to a Response
core.view


$dispatcher->connect('core.load_controller',
  function (Event $event)
  {
    $event->setReturnValue(array(
      function () { return 'Hello World'; },
      array()
    ));                             The controller returns a string,
                                             not a Response
      return true;
  }
);
core.view

                                               The value returned
$dispatcher->connect('core.view',
                                               by the controller
  function (Event $event, $value)
  {
    if (is_string($value))
    {                                              The view “convert” the
      return new Response($value);                 controller returned value to a
    }                                              Response if it’s a string

      return $value;
  }
         If not, it just returns the
);
         original value and it lets
         another view handle it if
         needed
core.exception




The request handler catches all exceptions
       and give a chance to listeners
        to return a Response object
core.exception


$dispatcher->connect('core.exception',
  function (Event $event)
  {
    $event->setReturnValue(
       new Response(
         'An error occurred: '.$event['exception']->getMessage()
       )
    );
                                   Mask the exception and return a
    return true;                   “nice” message to the user
  }
);
Request Handler
•  Several listeners can be attached to a single event
•  Listeners are called in turn
require __DIR__.'/lib/Symfony/Core/ClassLoader.php';


                                                                      Hello World
use   SymfonyComponentsEventDispatcherEvent;
use   SymfonyComponentsEventDispatcherEventDispatcher;
use   SymfonyComponentsRequestHandlerRequestHandler;
                                                                          with
use   SymfonyComponentsRequestHandlerRequest;
                                                                                      ts
use   SymfonyComponentsRequestHandlerResponse;
                                                                 Symfony 2.0 Componen
$classLoader = new ClassLoader('Symfony', __DIR__.'/lib');
$classLoader->register();

$dispatcher = new EventDispatcher();
$dispatcher->connect('core.load_controller', function (Event $event)
{
  $event->setReturnValue(array(
    function (Request $request)
    {
       return new Response('Hello '.$request->getQueryParameter('name'));
    },
    array($event['request'])
  ));

  return true;
});

$request = new Request();
$request->setQueryParameters(array('name' => 'Fabien'));

$handler = new RequestHandler($dispatcher);
$response = $handler->handle($request);
$response->send();
require __DIR__.'/lib/Symfony/Core/ClassLoader.php';
use   SymfonyComponentsEventDispatcherEvent;
use   SymfonyComponentsEventDispatcherEventDispatcher;
use   SymfonyComponentsRequestHandlerRequestHandler;
use   SymfonyComponentsRequestHandlerRequest;
use   SymfonyComponentsRequestHandlerResponse;




$classLoader = new ClassLoader('Symfony', __DIR__.'/lib');
$classLoader->register();
Autoloading in PHP 5.3
•  Will be hopefully standardized
   for major/all PHP 5.3 frameworks/libraries
•  Main goal:
   –  provide a better interoperability between PHP frameworks/libraries


•  A group of people is discussing this “standard” (nothing decided yet)

         http://groups.google.com/group/php-standards
Autoloading in PHP 5.3
•  Current proposal

http://groups.google.com/group/php-standards/web/php-coding-
  standard-version-2


•  Used for this presentation examples
•  Tested by real-world projects:
   –  Doctrine 2
   –  Lithium
   –  Symfony 2 Components
$dispatcher = new EventDispatcher();
$dispatcher->connect(
   'core.load_controller',
   $controllerLoader
);
$controllerLoader = function (Event $event)
{
  $event->setReturnValue(array(
     $controller,                  Can be any PHP callable
     array($event['request'])
  );
}                             Arguments to pass
                                     to the controller
Arguments passed
                              to the controller


$controller = function (Request $request)
{
  $name = $request->getQueryParameter('name');

  return new Response('Hello '.$name);
};

        A controller should
        return a Response
$request = new Request();
$request->setQueryParameters(array('name' => 'Fabien'));

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

          Sends the response
          to the browser
Symfony 2
The Templating Framework
New Templating Framework
•  4 components
   –  Template Engine
   –  Template Renderers
   –  Template Loaders
   –  Template Storages



•  Independant library
require __DIR__.'/lib/Symfony/Core/ClassLoader.php';

use SymfonyComponentsTemplatingEngine;
use SymfonyComponentsTemplatingLoaderFilesystemLoader;

$classLoader = new ClassLoader('Symfony', __DIR__.'/lib');
$classLoader->register();

$loader = new FilesystemLoader(
   '/path/to/templates/%name%.php'
);

$t = new Engine($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 FilesystemLoader('/path/to/templates/%name%.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 Engine($loader, array(
  'user' => new ProjectTemplateRenderer(),
  'php' => new PhpRenderer(),
));
Template Embedding



Hello <?php echo $name ?>

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

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

<?php $this->extend('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
A CMS 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->extend('articles/layout') ?>

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

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


<?php $this->extend ('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->extend('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 Engine($loader, array(
  'user' => new ProjectTemplateRenderer(),
  'php' => new PhpRenderer(),
));
Template Renderer
use SymfonyComponentsTemplatingRendererRenderer;

class ProjectTemplateRenderer extends Renderer
{
  public function evaluate(Storage $template, array $parameters = array())
  {
    if ($template instanceof FileStorage)
    {
      $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 FilesystemLoader(array(
  '/path/to/project/templates/%name%.php',
  '/path/to/cms/templates/%name%.php',
));
Template Loader Chain


$loader = new ChainLoader(array(
  new ProjectTemplateLoader($pdo),
  new FilesystemLoader(array(
    '/path/to/project/templates/%name%.php',
    '/path/to/cms/templates/%name%.php',
  )),
));
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 }}")');
Database Template Loader
use SymfonyComponentsTemplatingLoaderLoader;

class ProjectTemplateLoader extends Loader
{
    protected $pdo;

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



     public function load($template, $renderer = 'php')
     {
       $stmt = $this->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;
     }
}
Template Loader Cache




$loader = new CacheLoader($loader, '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 CacheLoader(
   new ChainLoader(array(
     new ProjectTemplateLoader($pdo),
     new FilesystemLoader(array(
       '/path/to/project/templates/%name%.php',
       '/path/to/cms/templates/%name%.php',
     )),
   )),
   'path/to/cache'
);

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

$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
   –  … and some more
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

require __DIR__.'/lib/Symfony/Core/ClassLoader.php';

use SymfonyComponentsDependencyInjectionBuilder;
use SymfonyComponentsDependencyInjectionReference;

$classLoader = new ClassLoader('Symfony', __DIR__.'/lib');
$classLoader->register();

$container = new Builder();

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

$container->
  register('message', 'Message')->
  setArguments(array(new Reference('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 Builder();

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

$container->message->say('Hello World!');                                                PHP
<container xmlns="http://symfony-project.org/2.0/container">
  <services>
    <service id="output" class="FancyOutput" />                                          XML
    <service id="message" class="Message">                            XML is validated
      <argument type="service" id="output" />
      <argument type="collection">
                                                                      against an XSD
        <argument key="with_newline">true</argument>
      </argument>
    </service>
  </services>
</container>

$container = new Builder();
$loader = new XmlFileLoader($container);
$loader->load('services.xml');
$container = new Builder();

$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 }
  message:                                                                               YAML
    class: Message
    arguments:
      - @output
      - { with_newline: true }

$container = new Builder();
$loader = new YamlFileLoader($container);
$loader->load('services.yml');
<container xmlns="http://symfony-project.org/2.0/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 rBuilder();
$loader = new XmlFileLoader($container);
$loader->load('services.xml');
<container xmlns="http://symfony-project.org/2.0/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 xmlns="http://symfony-project.org/2.0/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 Builder();
$loader = new FileXmlFileLoader($container);
$loader->load('services.xml');
<services>
 <import resource="config.yml" class="SymfonyComponentsDependencyInjectionLoader
YamlFileLoader" />

  <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 Builder();
$loader = new XmlFileLoader($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 CacheLoader(
   new ChainLoader(array(
     new ProjectTemplateLoader($pdo),
     new FilesystemLoader(array(
       '/path/to/project/templates/%name%.php',
       '/path/to/cms/templates/%name%.php',
     )),
   )),
   'path/to/cache'
);

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

$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 Builder();
$loader = new FileXmlLoader($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 xmlns="http://symfony-project.org/2.0/container">
  <imports>
    <import resource="config.yml" class="SymfonyComponentsDependencyInjectionLoader
YamlFileLoader" />
    <import resource="template_loader.xml" />
  </imports>

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

    <service id="template_renderer" class="ProjectTemplateRenderer" />

    <service id="template" class="SymfonyComponentsTemplatingEngine">
      <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" key="pdo" id="pdo" />
  </service>

  <service id="template_loader_filesystem" class="SymfonyComponentsTemplatingLoader
FilesystemLoader">
    <argument>%template.filesystem_pattern%</argument>
  </service>

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

  <service id="template_loader" class="SymfonyComponentsTemplatingLoaderCacheLoader">
    <argument type="service" id="template_loader_chain" />
    <argument>%application.dir%/cache</argument>
  </service>
</services>
<services>
  <service id="template_loader" class="SymfonyComponentsTemplatingLoaderCacheLoader">
    <argument type="service">
      <service class="SymfonyComponentsTemplatingLoaderChainLoader">
        <argument type="collection">
           <argument type="service">
             <service class="ProjectTemplateLoader">
               <argument type="service" key="pdo" id="pdo" />
             </service>
           </argument>
           <argument type="service">
             <service class="SymfonyComponentsTemplatingLoaderFilesystemLoader">
               <argument>%template.filesystem_patterns%</argument>
             </service>
           </argument>
        </argument>
      </service>
    </argument>
    <argument>%application.dir%/cache</argument>
  </service>
</services>
partners.sensiolabs.com

•  SITE PARTNERS
                          Coming soon…

                           Contact me
                           if you are
                            interested
symfony-live.com
           with Matthew Weier O’Pheinney




     I will reveal the first alpha release of Symfony 2!
symfony-live.com
           with Matthew Weier O’Pheinney




   and with Matthew Weier O'Phinney as a special guest
Questions?
Sensio S.A.
    92-98, boulevard Victor Hugo
        92 115 Clichy Cedex
              FRANCE
       Tél. : +33 1 40 99 80 80

               Contact
           Fabien Potencier
    fabien.potencier at sensio.com




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

More Related Content

What's hot

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
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Kris Wallsmith
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsMark Baker
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Jakub Zalas
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War StoriesJakub Zalas
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark Baker
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojobpmedley
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Fabien Potencier
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of LithiumNate Abele
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworksdiego_k
 
Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Fabien Potencier
 
Symfony internals [english]
Symfony internals [english]Symfony internals [english]
Symfony internals [english]Raul Fraile
 

What's hot (20)

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)
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War Stories
 
New in php 7
New in php 7New in php 7
New in php 7
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
Zero to SOLID
Zero to SOLIDZero to SOLID
Zero to SOLID
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 
Perl5i
Perl5iPerl5i
Perl5i
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
 
Symfony internals [english]
Symfony internals [english]Symfony internals [english]
Symfony internals [english]
 

Similar to Symfony 2.0 on PHP 5.3

Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Fabien Potencier
 
Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2narkoza
 
Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Fabien Potencier
 
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 2.0
Symfony 2.0Symfony 2.0
Symfony 2.0GrUSP
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi
 
Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Fabien Potencier
 
Symfony Nano Framework
Symfony Nano FrameworkSymfony Nano Framework
Symfony Nano FrameworkLoïc Faugeron
 
Fabien Potencier "Symfony 4 in action"
Fabien Potencier "Symfony 4 in action"Fabien Potencier "Symfony 4 in action"
Fabien Potencier "Symfony 4 in action"Fwdays
 
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
 
Symfony 4: A new way to develop applications #ipc19
Symfony 4: A new way to develop applications #ipc19Symfony 4: A new way to develop applications #ipc19
Symfony 4: A new way to develop applications #ipc19Antonio Peric-Mazar
 
Unleash your Symfony projects with eZ Platform
Unleash your Symfony projects with eZ PlatformUnleash your Symfony projects with eZ Platform
Unleash your Symfony projects with eZ PlatformSébastien Morel
 
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 4: A new way to develop applications #phpsrb
 Symfony 4: A new way to develop applications #phpsrb Symfony 4: A new way to develop applications #phpsrb
Symfony 4: A new way to develop applications #phpsrbAntonio Peric-Mazar
 
Symfony2 components to the rescue of your PHP projects
Symfony2 components to the rescue of your PHP projectsSymfony2 components to the rescue of your PHP projects
Symfony2 components to the rescue of your PHP projectsXavier Lacot
 
Php through the eyes of a hoster confoo
Php through the eyes of a hoster confooPhp through the eyes of a hoster confoo
Php through the eyes of a hoster confooCombell NV
 
How Symfony changed my life (#SfPot, Paris, 19th November 2015)
How Symfony changed my life (#SfPot, Paris, 19th November 2015)How Symfony changed my life (#SfPot, Paris, 19th November 2015)
How Symfony changed my life (#SfPot, Paris, 19th November 2015)Matthias Noback
 
Simplify your professional web development with symfony
Simplify your professional web development with symfonySimplify your professional web development with symfony
Simplify your professional web development with symfonyFrancois Zaninotto
 
How Symfony Changed My Life
How Symfony Changed My LifeHow Symfony Changed My Life
How Symfony Changed My LifeMatthias Noback
 

Similar to Symfony 2.0 on PHP 5.3 (20)

Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
 
Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2
 
Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 Framework
 
Symfony 2.0
Symfony 2.0Symfony 2.0
Symfony 2.0
 
Symfony 2 (PHP day 2009)
Symfony 2 (PHP day 2009)Symfony 2 (PHP day 2009)
Symfony 2 (PHP day 2009)
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8
 
Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)
 
Symfony Nano Framework
Symfony Nano FrameworkSymfony Nano Framework
Symfony Nano Framework
 
Fabien Potencier "Symfony 4 in action"
Fabien Potencier "Symfony 4 in action"Fabien Potencier "Symfony 4 in action"
Fabien Potencier "Symfony 4 in action"
 
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
 
Symfony 4: A new way to develop applications #ipc19
Symfony 4: A new way to develop applications #ipc19Symfony 4: A new way to develop applications #ipc19
Symfony 4: A new way to develop applications #ipc19
 
Unleash your Symfony projects with eZ Platform
Unleash your Symfony projects with eZ PlatformUnleash your Symfony projects with eZ Platform
Unleash your Symfony projects with eZ Platform
 
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 4: A new way to develop applications #phpsrb
 Symfony 4: A new way to develop applications #phpsrb Symfony 4: A new way to develop applications #phpsrb
Symfony 4: A new way to develop applications #phpsrb
 
Symfony2 components to the rescue of your PHP projects
Symfony2 components to the rescue of your PHP projectsSymfony2 components to the rescue of your PHP projects
Symfony2 components to the rescue of your PHP projects
 
Php through the eyes of a hoster confoo
Php through the eyes of a hoster confooPhp through the eyes of a hoster confoo
Php through the eyes of a hoster confoo
 
How Symfony changed my life (#SfPot, Paris, 19th November 2015)
How Symfony changed my life (#SfPot, Paris, 19th November 2015)How Symfony changed my life (#SfPot, Paris, 19th November 2015)
How Symfony changed my life (#SfPot, Paris, 19th November 2015)
 
Simplify your professional web development with symfony
Simplify your professional web development with symfonySimplify your professional web development with symfony
Simplify your professional web development with symfony
 
How Symfony Changed My Life
How Symfony Changed My LifeHow Symfony Changed My Life
How Symfony Changed My Life
 

More from Fabien Potencier

Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Fabien Potencier
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Fabien Potencier
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Fabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Fabien Potencier
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Fabien Potencier
 
Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009Fabien Potencier
 
Twig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHPTwig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHPFabien Potencier
 
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)Fabien Potencier
 
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
 

More from Fabien Potencier (19)

Varnish
VarnishVarnish
Varnish
 
Look beyond PHP
Look beyond PHPLook beyond PHP
Look beyond PHP
 
Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Symfony Components
Symfony ComponentsSymfony Components
Symfony Components
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3
 
Playing With PHP 5.3
Playing With PHP 5.3Playing With PHP 5.3
Playing With PHP 5.3
 
Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009
 
Twig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHPTwig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHP
 
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 2008)
symfony: Un Framework Open-Source pour les Entreprises (Solutions Linux 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)
The symfony platform: Create your very own framework (PHP Quebec 2008)
 

Recently uploaded

Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
"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
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
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
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
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
 

Recently uploaded (20)

Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
"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
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
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
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
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
 

Symfony 2.0 on PHP 5.3

  • 1. Symfony 2.0 on PHP 5.3! Fabien Potencier
  • 2. Fabien Potencier •  Serial entrepreneur and developer by passion •  Founder of Sensio (in 1998) –  A services and consulting company specialized in Web technologies and Internet marketing (France and USA) –  70 people –  Open-Source specialists –  Big corporate customers –  Consulting, training, development, web design, … and more –  Sponsor of a lot of Open-Source projects like symfony and Doctrine
  • 3. Fabien Potencier •  Creator and lead developer of symfony… •  and creator and lead developer of some more: –  symfony components –  Swift Mailer : Powerful component based mailing library for PHP –  Twig : Fexible, fast, and secure template language for PHP –  Pirum : Simple PEAR Channel Server Manager –  Sismo : PHP continuous integration server –  Lime : Easy to use unit testing library for PHP –  Twitto : A web framework in a tweet –  Twittee : A Dependency Injection Container in a tweet –  Pimple : A small PHP 5.3 dependency injection container
  • 4. Fabien Potencier •  Read my technical blog: http://fabien.potencier.org/ •  Follow me on Twitter: @fabpot •  Fork my code on Github: http://github.com/fabpot/
  • 5. How many of you have used symfony? 1.0? 1.1? 1.2? 1.3?
  • 6. 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, …
  • 7. 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, …
  • 8. Roadmap •  1.0 – January 2007 •  1.1 – June 2008 •  1.2 – November 2008 •  1.3 – November 2009 •  1.4 – Last 1.X version (LTS release : 3 years of support) – same as 1.3 but without deprecated features •  Version 2.0 – Hopefully at the end of 2010
  • 9. Symfony 2.0 •  PHP 5.3 only - http://sf-to.org/sf20onPHP53 •  Same Symfony core components (updated for PHP 5.3) •  Different controller implementation •  Oh! Symfony now takes a capital S!!!
  • 10. 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, Templating
  • 11. Symfony Components •  Existing components –  will soon be released as 1.0 (for PHP 5.2) –  will then be migrated to PHP 5.3 (mainly introducing namespaces) •  New components: –  will work with PHP 5.3 only right from the start
  • 12. Symfony 2 main goals Flexibility Fast Smart
  • 13. Symfony 2 core Event Dispatcher Dependency Injection Container Controller Handling
  • 14. Symfony 2 •  Obviously 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 be released as standalone components: –  Controller Handling –  Output Escaping will be migrated to –  Forms PHP 5.3 soon –  Routing –  Templating Framework (done) –  Dependency Injection Container (done)
  • 16. symfony 1 is one of the slowest framework when you test it against a simple Hello World application
  • 17. 1644& 1544& !"#$%&!'!& 1344& Hello World 1144& Benchmark 1444& ;44& x 19.5 :44& 944& 844& 744& 644& 544& 344& ()"#*& x 2.3 144& +,& -./0)%.&123& 4& based on numbers from http://paul-m-jones.com/?p=315
  • 19. Don’t use symfony for your next « Hello World » website Use PHP ;)
  • 20. By the way, the fastest implemention of a Hello World application with PHP: die('Hello World');
  • 21. But symfony 1 is probably fast enough for your next website
  • 22. … 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
  • 23. … and recently dailymotion.com announced its migration to Symfony sf-to.org/dailymotion
  • 24. Second most popular video sharing website One of the top 30 websites in the world 59 million unique users in July 2009
  • 25. …and of course many other smaller websites…
  • 27. Symfony 2 core is so light and flexible that its raw performance is outstanding
  • 28. require_once dirname(__FILE__).'/sf20/autoload2/sfCore2Autoload.class.php'; sfCore2Autoload::register(); Hello World $app = new HelloApplication(); $app->run()->send(); 0 class HelloApplication wit h Symfony 2. { public function __construct() { $this->dispatcher = new sfEventDispatcher(); $this->dispatcher->connect('application.load_controller', array($this, 'loadController')); } public function run() OUTDATED { $request = new sfWebRequest($this->dispatcher); $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; }
  • 29. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsEventDispatcherEvent; Hello World use SymfonyComponentsEventDispatcherEventDispatcher; use SymfonyComponentsRequestHandlerRequestHandler; ymfony 2.0 use SymfonyComponentsRequestHandlerRequest; use SymfonyComponentsRequestHandlerResponse; with S $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); on PHP 5.3 $dispatcher = new EventDispatcher(); $dispatcher->connect('core.load_controller', function (Event $event) { $event->setReturnValue(array( function (Request $request) { return new Response('Hello '.$request->getQueryParameter('name')); }, array($event['request']) )); return true; }); $request = new Request(); $request->setQueryParameters(array('name' => 'Fabien')); $handler = new RequestHandler($dispatcher); $response = $handler->handle($request); $response->send();
  • 30. 7922& 7822& !"#$%&!'!& Hello World Benchmark ()$*+& 7022& 7722& 7222& >22& =22& <22& Symfony 2.0 on PHP 5.3 ;22& :22& ,-./+%-&012& x 10 922& x 3 x 7 822& 022& 3+"#4& 722& 56& ,-./+%-&710& 2& based on numbers from http://paul-m-jones.com/?p=315
  • 31. 10 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
  • 32. … and PHP 5.3 helps •  The Hello World code on PHP 5.3 is 50% faster than the one on PHP 5.2 (for the same code!) •  All frameworks will benefit from some speed improvements •  Again, real applications won’t have such a speed difference just by upgrading to PHP 5.3 ! Upgrad e to PHP 5.3 e It mean s performanc improveme nts for FREE
  • 33. 10 times faster?! •  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. How many of you have used PHP 5.3?
  • 35. This presentation is full of … the new PHP developer best friend
  • 36. Namespaces from sfRequest to SymfonyCoreRequest use SymfonyCoreRequest; $request = new Request();
  • 37. Anonymous Functions $a = function ($msg) { echo $msg; } $a('Hello World');
  • 38. Symfony 2 The Event Dispatcher
  • 39. EventDispatcher •  Observer Design Pattern •  Based on Cocoa Notification Center // sfI18N $callback = array($this, 'listenToChangeCultureEvent'); $dispatcher->connect('user.change_culture', $callback); // sfUser $event = new Event($this, 'user.change_culture', array('culture' => $culture)); $dispatcher->notify($event); •  I18N and User are decoupled •  An event is defined by a unique string •  « Anybody » can listen to any event •  You can notify existing events or create new ones easily
  • 40. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsEventDispatcherEvent; use SymfonyComponentsEventDispatcherEventDispatcher; $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); $dispatcher = new EventDispatcher(); $listener = function ($event) { echo sprintf("Hello %s!n", $event['name']); }; $dispatcher->connect('foo', $listener); Can be any PHP callable $event = new Event(null, 'foo', array('name' => 'Fabien')); $dispatcher->notify($event);
  • 42. 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
  • 43. The Request Handler use SymfonyComponentsRequestHandlerRequestHandler; use SymfonyComponentsRequestHandlerRequest; $handler = new RequestHandler($dispatcher); $request = new Request(); $response = $handler->handle($request); $response->send();
  • 44. The Request Handler •  The RequestHandler does several things: –  Notifies events –  Executes a callable (the controller) –  Ensures 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
  • 45. namespace SymfonyComponentsRequestHandler; use SymfonyComponentsEventDispatcherEvent; use SymfonyComponentsEventDispatcherEventDispatcher; class RequestHandler { protected $dispatcher = null; public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function handle(RequestInterface $request) { try { return $this->handleRaw($request); } catch (Exception $e) { // exception RequestHandler is $event = $this->dispatcher->notifyUntil(new Event($this, 'core.exception', array('request' => $request, 'exception' => $e))); if ($event->isProcessed()) { return $this->filterResponse($event->getReturnValue(), 'An "core.exception" listener returned a non response object.'); } less than 100 lines throw $e; } } public function handleRaw(RequestInterface $request) { of PHP code! // request $event = $this->dispatcher->notifyUntil(new Event($this, 'core.request', array('request' => $request))); if ($event->isProcessed()) { return $this->filterResponse($event->getReturnValue(), 'An "core.request" listener returned a non response object.'); } // load controller $event = $this->dispatcher->notifyUntil(new Event($this, 'core.load_controller', array('request' => $request))); if (!$event->isProcessed()) { throw new LogicException('Unable to load the controller.'); } list($controller, $arguments) = $event->getReturnValue(); // controller must be a callable if (!is_callable($controller)) { throw new LogicException(sprintf('The controller must be a callable (%s).', var_export($controller, true))); } // controller $event = $this->dispatcher->notifyUntil(new Event($this, 'core.controller', array('request' => $request, 'controller' => &$controller, 'arguments' => &$arguments))); if ($event->isProcessed()) { try { return $this->filterResponse($event->getReturnValue(), 'An "core.controller" listener returned a non response object.'); } catch (Exception $e) { $retval = $event->getReturnValue(); } } else { // call controller $retval = call_user_func_array($controller, $arguments); } // view $event = $this->dispatcher->filter(new Event($this, 'core.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 (!$response instanceof ResponseInterface) { throw new RuntimeException($message); } $event = $this->dispatcher->filter(new Event($this, 'core.response'), $response); $response = $event->getReturnValue(); if (!$response instanceof ResponseInterface) { throw new RuntimeException('An "core.response" listener returned a non response object.'); } return $response; } public function getEventDispatcher() { return $this->dispatcher; } }
  • 47. core.response As the very last event notified, a listener can modify the Response object just before it is returned to the user
  • 48. core.response $dispatcher->connect('core.response', function (Event $event, Response $response) { $response->setContent( $response->getContent(). 'The Web Debug Toolbar' ); Content of the response is changed return $response; } );
  • 49. core.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
  • 50. core.request $dispatcher->connect('core.request', function (Event $event) { $event->setReturnValue( new Response('Website unavailable...') ); Don’t go any further! return true; } );
  • 51. core.load_controller •  The 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
  • 52. core.load_controller $dispatcher->connect('core.load_controller', function (Event $event) { $event->setReturnValue(array( function () { return new Response('Hello World'); }, array() Whatever the request, )); always return Hello World return true; } );
  • 53. core.view The controller must return a Response object except if a listener can convert the controller returned value to a Response
  • 54. core.view $dispatcher->connect('core.load_controller', function (Event $event) { $event->setReturnValue(array( function () { return 'Hello World'; }, array() )); The controller returns a string, not a Response return true; } );
  • 55. core.view The value returned $dispatcher->connect('core.view', by the controller function (Event $event, $value) { if (is_string($value)) { The view “convert” the return new Response($value); controller returned value to a } Response if it’s a string return $value; } If not, it just returns the ); original value and it lets another view handle it if needed
  • 56. core.exception The request handler catches all exceptions and give a chance to listeners to return a Response object
  • 57. core.exception $dispatcher->connect('core.exception', function (Event $event) { $event->setReturnValue( new Response( 'An error occurred: '.$event['exception']->getMessage() ) ); Mask the exception and return a return true; “nice” message to the user } );
  • 58. Request Handler •  Several listeners can be attached to a single event •  Listeners are called in turn
  • 59. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; Hello World use SymfonyComponentsEventDispatcherEvent; use SymfonyComponentsEventDispatcherEventDispatcher; use SymfonyComponentsRequestHandlerRequestHandler; with use SymfonyComponentsRequestHandlerRequest; ts use SymfonyComponentsRequestHandlerResponse; Symfony 2.0 Componen $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); $dispatcher = new EventDispatcher(); $dispatcher->connect('core.load_controller', function (Event $event) { $event->setReturnValue(array( function (Request $request) { return new Response('Hello '.$request->getQueryParameter('name')); }, array($event['request']) )); return true; }); $request = new Request(); $request->setQueryParameters(array('name' => 'Fabien')); $handler = new RequestHandler($dispatcher); $response = $handler->handle($request); $response->send();
  • 60. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsEventDispatcherEvent; use SymfonyComponentsEventDispatcherEventDispatcher; use SymfonyComponentsRequestHandlerRequestHandler; use SymfonyComponentsRequestHandlerRequest; use SymfonyComponentsRequestHandlerResponse; $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register();
  • 61. Autoloading in PHP 5.3 •  Will be hopefully standardized for major/all PHP 5.3 frameworks/libraries •  Main goal: –  provide a better interoperability between PHP frameworks/libraries •  A group of people is discussing this “standard” (nothing decided yet) http://groups.google.com/group/php-standards
  • 62. Autoloading in PHP 5.3 •  Current proposal http://groups.google.com/group/php-standards/web/php-coding- standard-version-2 •  Used for this presentation examples •  Tested by real-world projects: –  Doctrine 2 –  Lithium –  Symfony 2 Components
  • 63. $dispatcher = new EventDispatcher(); $dispatcher->connect( 'core.load_controller', $controllerLoader );
  • 64. $controllerLoader = function (Event $event) { $event->setReturnValue(array( $controller, Can be any PHP callable array($event['request']) ); } Arguments to pass to the controller
  • 65. Arguments passed to the controller $controller = function (Request $request) { $name = $request->getQueryParameter('name'); return new Response('Hello '.$name); }; A controller should return a Response
  • 66. $request = new Request(); $request->setQueryParameters(array('name' => 'Fabien')); $handler = new RequestHandler($dispatcher); $response = $handler->handle($request); $response->send(); Sends the response to the browser
  • 68. New Templating Framework •  4 components –  Template Engine –  Template Renderers –  Template Loaders –  Template Storages •  Independant library
  • 69. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsTemplatingEngine; use SymfonyComponentsTemplatingLoaderFilesystemLoader; $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); $loader = new FilesystemLoader( '/path/to/templates/%name%.php' ); $t = new Engine($loader); echo $t->render('index', array('name' => 'Fabien'));
  • 70. Template Loaders •  No assumption about where and how templates are to be found –  Filesystem –  Database –  Memory, … •  Template names are « logical » names: $loader = new FilesystemLoader('/path/to/templates/%name%.php');
  • 71. 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 Engine($loader, array( 'user' => new ProjectTemplateRenderer(), 'php' => new PhpRenderer(), ));
  • 72. Template Embedding Hello <?php echo $name ?> <?php $this->render('embedded', array('name' => $name)) ?> <?php $this->render('smarty:embedded') ?>
  • 73. Template Inheritance <?php $this->extend('layout') ?> Hello <?php echo $name ?> <html> <head> </head> <body> <?php $this->output('content') ?> </body> </html>
  • 74. 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() ?>
  • 75. Template Multiple Inheritance A layout can be decorated by another layout Each layout can override slots
  • 77. 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 }}
  • 78. 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
  • 80. articles/article.php <?php $this->extend('articles/layout') ?> <?php $this->set('title', $title) ?> <?php echo $this->render( 'user:articles/content', array('title' => $title, 'content' => $content) ) ?>
  • 81. articles/layout.php <?php $this->extend ('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') ?>
  • 82. articles/layout.php <?php $this->extend('base') ?> <?php $this->set('title', 'Articles | '.$this->get('title')) ?> <?php $this->stylesheets->add('/css/articles.css') ?> <?php $this->output('content') ?>
  • 83. base.php <html> <head> <title> <?php $this->output('title') ?> </title> <?php $this->output('head') ?> </head> <body> <?php $this->output('content') ?> </body> </html>
  • 84. Template Renderer $t = new Engine($loader, array( 'user' => new ProjectTemplateRenderer(), 'php' => new PhpRenderer(), ));
  • 85. Template Renderer use SymfonyComponentsTemplatingRendererRenderer; class ProjectTemplateRenderer extends Renderer { public function evaluate(Storage $template, array $parameters = array()) { if ($template instanceof FileStorage) { $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; } }
  • 86. Template Loaders $loader = new FilesystemLoader(array( '/path/to/project/templates/%name%.php', '/path/to/cms/templates/%name%.php', ));
  • 87. Template Loader Chain $loader = new ChainLoader(array( new ProjectTemplateLoader($pdo), new FilesystemLoader(array( '/path/to/project/templates/%name%.php', '/path/to/cms/templates/%name%.php', )), ));
  • 88. 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 }}")');
  • 89. Database Template Loader use SymfonyComponentsTemplatingLoaderLoader; class ProjectTemplateLoader extends Loader { protected $pdo; public function __construct($pdo) { $this->pdo = $pdo; } public function load($template, $renderer = 'php') { $stmt = $this->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; } }
  • 90. Template Loader Cache $loader = new CacheLoader($loader, 'path/to/cache');
  • 91. $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 CacheLoader( new ChainLoader(array( new ProjectTemplateLoader($pdo), new FilesystemLoader(array( '/path/to/project/templates/%name%.php', '/path/to/cms/templates/%name%.php', )), )), 'path/to/cache' ); $t = new Engine($loader, array( 'user' => new ProjectTemplateRenderer() )); $t->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
  • 93. « Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields. » http://www.picocontainer.org/injection.html
  • 94. 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 –  … and some more
  • 95. 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" : '')); } }
  • 96. 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); } }
  • 97. DI Hello World example $output = new FancyOutput(); $message = new Message($output, array('with_newline' => true)); $message->say('Hello World');
  • 98. A DI container facilitates objects description and object relationships, configures and instantiates objects
  • 99. DI Container Hello World example require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsDependencyInjectionBuilder; use SymfonyComponentsDependencyInjectionReference; $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); $container = new Builder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new Reference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!');
  • 100. $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
  • 101. $message = $container->message; is roughly equivalent to $output = new FancyOutput(); $message = new Message($output, array('with_newline' => true));!
  • 102. $container = new Builder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new Reference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!'); PHP <container xmlns="http://symfony-project.org/2.0/container"> <services> <service id="output" class="FancyOutput" /> XML <service id="message" class="Message"> XML is validated <argument type="service" id="output" /> <argument type="collection"> against an XSD <argument key="with_newline">true</argument> </argument> </service> </services> </container> $container = new Builder(); $loader = new XmlFileLoader($container); $loader->load('services.xml');
  • 103. $container = new Builder(); $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 } message: YAML class: Message arguments: - @output - { with_newline: true } $container = new Builder(); $loader = new YamlFileLoader($container); $loader->load('services.yml');
  • 104. <container xmlns="http://symfony-project.org/2.0/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 rBuilder(); $loader = new XmlFileLoader($container); $loader->load('services.xml');
  • 105. <container xmlns="http://symfony-project.org/2.0/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 xmlns="http://symfony-project.org/2.0/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 Builder(); $loader = new FileXmlFileLoader($container); $loader->load('services.xml');
  • 106. <services> <import resource="config.yml" class="SymfonyComponentsDependencyInjectionLoader YamlFileLoader" /> <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 Builder(); $loader = new XmlFileLoader($container); $loader->load('services.xml');
  • 107. $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 CacheLoader( new ChainLoader(array( new ProjectTemplateLoader($pdo), new FilesystemLoader(array( '/path/to/project/templates/%name%.php', '/path/to/cms/templates/%name%.php', )), )), 'path/to/cache' ); $t = new Engine($loader, array( 'user' => new ProjectTemplateRenderer() )); $t->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
  • 108. $pdo = new PDO('sqlite::memory:'); <service id="pdo" class="PDO"> <argument>sqlite::memory:</argument> </service>
  • 109. $container = new Builder(); $loader = new FileXmlLoader($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...'));
  • 110. <container xmlns="http://symfony-project.org/2.0/container"> <imports> <import resource="config.yml" class="SymfonyComponentsDependencyInjectionLoader YamlFileLoader" /> <import resource="template_loader.xml" /> </imports> <services> <service id="pdo" class="PDO"> <argument>sqlite::memory:</argument> </service> <service id="template_renderer" class="ProjectTemplateRenderer" /> <service id="template" class="SymfonyComponentsTemplatingEngine"> <argument type="service" id="template_loader" /> <argument type="collection"> <argument type="service" key="user" id="template_renderer" /> </argument> </service> </services> </container>
  • 111. <services> <service id="template_loader_project" class="ProjectTemplateLoader"> <argument type="service" key="pdo" id="pdo" /> </service> <service id="template_loader_filesystem" class="SymfonyComponentsTemplatingLoader FilesystemLoader"> <argument>%template.filesystem_pattern%</argument> </service> <service id="template_loader_chain" class="SymfonyComponentsTemplatingLoaderChainLoader"> <argument type="collection"> <argument type="service" id="template_loader_project" /> <argument type="service" id="template_loader_filesystem" /> </argument> </service> <service id="template_loader" class="SymfonyComponentsTemplatingLoaderCacheLoader"> <argument type="service" id="template_loader_chain" /> <argument>%application.dir%/cache</argument> </service> </services>
  • 112. <services> <service id="template_loader" class="SymfonyComponentsTemplatingLoaderCacheLoader"> <argument type="service"> <service class="SymfonyComponentsTemplatingLoaderChainLoader"> <argument type="collection"> <argument type="service"> <service class="ProjectTemplateLoader"> <argument type="service" key="pdo" id="pdo" /> </service> </argument> <argument type="service"> <service class="SymfonyComponentsTemplatingLoaderFilesystemLoader"> <argument>%template.filesystem_patterns%</argument> </service> </argument> </argument> </service> </argument> <argument>%application.dir%/cache</argument> </service> </services>
  • 113.
  • 114. partners.sensiolabs.com •  SITE PARTNERS Coming soon… Contact me if you are interested
  • 115. symfony-live.com with Matthew Weier O’Pheinney I will reveal the first alpha release of Symfony 2!
  • 116. symfony-live.com with Matthew Weier O’Pheinney and with Matthew Weier O'Phinney as a special guest
  • 118. 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/