SlideShare uma empresa Scribd logo
1 de 48
Baixar para ler offline
symfony
                         symfony as a platform


                                  Fabien Potencier
                         http://www.symfony-project.com/
                            http://www.sensiolabs.com/



Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
symfony 1.1
  • A lot of internal refactoring… really a lot
  • Some new features… but not a lot
         – Tasks are now classes
         – More cache classes: APC, Eaccelerator, File,
           Memcache, SQLite, XCache
         – Configurable Routing: Pattern, PathInfo
         – … and some more
  • Yes, we will have a new form/validation system…
    but we still need some internal refactoring

Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Singletons
                         1.0                                            1.1
                    sfConfigCache                                  sfConfigCache
                    sfContext                                      sfContext
                    sfRouting
                    sfWebDebug
                    sfI18N
                    sfLogger
                                                                        Remove
                                                                       Singletons

Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Why?
  // somewhere in the backend application
  $frontendRouting = sfContext::getInstance('frontend')->getRouting();

  $url = $frontendRouting->generate('article', array('id' => 1));



  // somewhere in a functional test
  $fabien = new sfTestBrowser('frontend');
  $thomas = new sfTestBrowser('frontend');

  $fabien->get('/talk_to/thomas/say/Hello');
  $thomas->get('/last_messages');
  $thomas->checkResponseElement('li', '/Hello/i');


                    Don’t try this at home… it won’t work… yet
Symfony Camp 2007        www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
symfony 1.0 Dependencies
                    sfView

                                               sfResponse
                                                                                        sfContext

                              sfI18N                     sfRequest
                                                                                         sfLogger

          sfStorage              sfUser

                                                             sfRouting                     Cleanup
                    dependency
                                                                                         Dependencies
  singleton

Symfony Camp 2007        www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
symfony 1.1 Dependencies
                                      sfRequest                    sfView
                                                                                     sfResponse
                      sfI18N
                                             sfEventDispatcher


                      sfUser                                                           sfRouting

   sfStorage                         sfLogger                   sfContext

                                                                                           Cleanup
                    dependency
                                                                                         Dependencies
  singleton

Symfony Camp 2007        www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfEventDispatcher
  • Based on Cocoa Notification Center
  // sfUser
  $event = new sfEvent($this, 'user.change_culture', array('culture' => $culture));
  $dispatcher->notify($event);

  // sfI18N
  $callback = array($this, 'listenToChangeCultureEvent');
  $dispatcher->connect('user.change_culture', $callback);



  • sfI18N and sfUser are decoupled
  • « Anybody » can listen to any event
  • You can notify existing events or create new ones

Symfony Camp 2007    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Why?


     Let’s talk about symfony 2.0…




Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
The Web Workflow

                The User asks a Resource in a Browser

          The Browser sends a Request to the Server

                    The Server sends back a Response

     The Browser displays the Resource to the User

Symfony Camp 2007      www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_00.php?name=Fabien
  session_start();

  if (isset($_GET['name']))
  {
    $name = $_GET['name'];
  }
  else if (isset($_SESSION['name']))
  {
    $name = $_SESSION['name'];
  }
  else
  {
    $name = 'World';
  }

  $_SESSION['name'] = $name;

  echo 'Hello '.$name;

      User > Resource > Request > Response
                        Request   Response
Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWebRequest
                           PHP                                                              Object
  $_SERVER[‘REQUEST_METHOD’]                                                    >getMethod()
  $_GET[‘name’]                                                                 >getParameter(‘name’)

  get_magic_quotes_gpc() ?
   stripslashes($_COOKIE[$name]) : $_COOKIE[$name];
                                                                                >getCookie(‘name’)

  (
      isset($_SERVER['HTTPS'])
      && (
        strtolower($_SERVER ['HTTPS']) == 'on’
          ||
                                                                                >isSecure()
        strtolower($_SERVER ['HTTPS']) == 1)
        )
      || (
        isset($_SERVER ['HTTP_X_FORWARDED_PROTO'])
          &&
        strtolower($_SERVER ['HTTP_X_FORWARDED_PROTO']) == 'https')
        )                                                                               Mock sfWebRequest
  )
                                     Abstract                                                  to test
                                    Parameters                                          without a HTTP layer
                                     Headers
Symfony Camp 2007               www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_01.php?name=Fabien

  require dirname(__FILE__).'/../symfony_platform.php';

  $dispatcher = new sfEventDispatcher();
  $request = new sfWebRequest($dispatcher);

  session_start();

  if ($request->hasParameter('name'))
  {
    $name = $request->getParameter('name');
  }
  else if (isset($_SESSION['name']))
  {
    $name = $_SESSION['name'];
  }
  else
  {
    $name = 'World';
  }

  $_SESSION['name'] = $name;

  echo 'Hello '.$name;


      User > Resource > Request > Response
                        Request   Response
Symfony Camp 2007    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWebResponse
                    PHP                                                            Object
  echo ‘Hello World!’                                                 >setContent(‘Hello World’)

  header(‘HTTP/1.0 404 Not Found’)                                    >setStatusCode(404)

  setcookie(‘name’, ‘value’)                                          >setCookie(‘name’, ‘value’)




                                                                              Mock sfWebResponse
                             Abstract
                                                                                     to test
                             Headers
                                                                              without a HTTP layer
                             Cookies

Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com    www.sensiolabs.com
http://localhost/step_02.php?name=Fabien
  require dirname(__FILE__).'/../symfony_platform.php';

  $dispatcher = new sfEventDispatcher();
  $request = new sfWebRequest($dispatcher);
  session_start();

  if (!$name = $request->getParameter('name'))
  {
    if (isset($_SESSION['name']))
    {
      $name = $_SESSION['name'];
    }
    else
    {
      $name = 'World';
    }
  }

  $_SESSION['name'] = $name;

  $response = new sfWebResponse($dispatcher);
  $response->setContent('Hello '.$name);
  $response->send();


      User > Resource > Request > Response
                        Request   Response
Symfony Camp 2007    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfUser / sfStorage
                    PHP                                                           Object
  $_SESSION[‘name’] = ‘value’                                         >setAttribute(‘name’, ‘value’)

                                                                      >setCulture(‘fr’)

                                                                      >setAuthenticated(true)

                                                                      Native session storage +
                                                                      MySQL, PostgreSQL, PDO, …




                                                                                  Mock sfUser
                            Abstract
                                                                                     to test
                          $_SESSION
                                                                              without a HTTP layer
                          Add features

Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_03.php?name=Fabien
  require dirname(__FILE__).'/../symfony_platform.php';

  $dispatcher = new sfEventDispatcher();
  $storage = new sfSessionStorage();
  $user = new sfUser($dispatcher, $storage);
  $request = new sfWebRequest($dispatcher);

  if (!$name = $request->getParameter('name'))
  {
    if (!$name = $user->getAttribute('name'))
    {
      $name = 'World';
    }
  }

  $user->setAttribute('name', $name);

  $response = new sfWebResponse($dispatcher);
  $response->setContent('Hello '.$name);
  $response->send();


      User > Resource > Request > Response
                        Request   Response
Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_04.php?name=Fabien

  require dirname(__FILE__).'/../symfony_platform.php';

  $dispatcher = new sfEventDispatcher();
  $storage = new sfSessionStorage();
  $user = new sfUser($dispatcher, $storage);
  $request = new sfWebRequest($dispatcher);

  $name = $request->getParameter('name', $user->getAttribute('name', 'World')));


  $user->setAttribute('name', $name);

  $response = new sfWebResponse($dispatcher);
  $response->setContent('Hello '.$name);
  $response->send();




      User > Resource > Request > Response
                        Request   Response
Symfony Camp 2007    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfRouting
  • Clean URLs <> Resources
  • Parses PATH_INFO to inject parameters in the
    sfRequest object
  • Several strategies: PathInfo, Pattern
  • Decouples Request and Controller




Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_05.php/hello/Fabien

  require dirname(__FILE__).'/../symfony_platform.php';

  $dispatcher = new sfEventDispatcher();
  $storage = new sfSessionStorage();
  $user = new sfUser($dispatcher, $storage);
  $routing = new sfPatternRouting($dispatcher);
  $routing->connect('hello', '/hello/:name');
  $request = new sfWebRequest($dispatcher);

  $name = $request->getParameter('name', $user->getAttribute('name', 'World')));


  $user->setAttribute('name', $name);

  $response = new sfWebResponse($dispatcher);
  $response->setContent('Hello '.$name);
  $response->send();




      User > Resource > Request > Response
                        Request   Response
Symfony Camp 2007    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
The Web Workflow

                The User asks a Resource in a Browser

          The Browser sends a Request to the Server

                    The Server sends back a Response

     The Browser displays the Resource to the User

Symfony Camp 2007      www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
symfony 2.0 philosophy



               Request
                                               ?                                 Response




  symfony gives                                                              symfony wants
  you a sfRequest                                                            a sfResponse
Symfony Camp 2007    www.symfony-project.com   fabien.potencier@sensio.com    www.sensiolabs.com
Let’s create symfony 2.0…



Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
The Controller
  • The dispatching logic is the same for every
    resource
  • The business logic depends on the resource and
    is managed by the controller

  • The controller responsability is to « convert » the
    request to the response



Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_06.php/hello/Fabien
  require dirname(__FILE__).'/../symfony_platform.php';

  $dispatcher = new sfEventDispatcher();
  $storage = new sfSessionStorage();
  $user = new sfUser($dispatcher, $storage);
  $routing = new sfPatternRouting($dispatcher);
  $routing->connect('hello', '/hello/:name',
    array('controller' => 'hello', 'action' => 'index'));
  $request = new sfWebRequest($dispatcher);

  $class = $request->getParameter('controller').'Controller';
  $method = $request->getParameter('action').'Action';
  $controller = new $class();

  $response = $controller->$method($dispatcher, $request, $user);

  $response->send();




Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_06.php/hello/Fabien
  class helloController
  {
    function indexAction($dispatcher, $request, $user)
    {
          $name = $request->getParameter('name', $user->getAttribute('name', 'World')));


          $user->setAttribute('name', $name);

          $response = new sfWebResponse($dispatcher);
          $response->setContent('Hello '.$name);

          return $response;
      }
  }




Symfony Camp 2007       www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
The RequestHandler
  • Handles the dispatching of the request
  • Calls the Controller
  • Has the responsability to return a sfResponse




Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_07.php/hello/Fabien

  require dirname(__FILE__).'/../symfony_platform.php';
  require dirname(__FILE__).'/step_07_framework.php';

  $dispatcher = new sfEventDispatcher();
  $storage = new sfSessionStorage();
  $user = new sfUser($dispatcher, $storage);
  $routing = new sfPatternRouting($dispatcher);
  $routing->connect('hello', '/hello/:name',
    array('controller' => 'hello', 'action' => 'index'));
  $request = new sfWebRequest($dispatcher);

  $response = RequestHandler::handle($dispatcher, $request, $user);

  $response->send();




Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_07.php/hello/Fabien
  class RequestHandler
  {
    function handle($dispatcher, $request, $user)
    {
      $class = $request->getParameter('controller').'Controller';
      $method = $request->getParameter('action').'Action';

          $controller = new $class();
          try
          {
            $response = $controller->$method($dispatcher, $request, $user);
          }
          catch (Exception $e)
          {
            $response = new sfWebResponse($dispatcher);
            $response->setStatusCode(500);
              $response->setContent(sprintf('An error occurred: %s', $e->getMessage()));
          }

          return $response;
      }
  }

Symfony Camp 2007         www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
I WANT a sfResponse


Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_08.php/hello/Fabien
  try
  {
    if (!class_exists($class))
    {
      throw new Exception('Controller class does not exist');
    }

     $controller = new $class();

     if (!method_exists($class, $method))
     {
       throw new Exception('Controller method does not exist');
     }

     $response = $controller->$method($dispatcher, $request, $user);

     if (!is_object($response) || !$response instanceof sfResponse)
     {
       throw new Exception('Controller must return a sfResponse object');
     }
  }
  catch (Exception $e)
  {
    $response = new sfWebResponse($dispatcher);
    $response->setStatusCode(500);
    $response->setContent(sprintf('An error occurred: %s', $e->getMessage()));
  }
Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
The Application
  $response = $controller->$method($dispatcher, $request, $user);




  • I need a container for my application objects
         –   The dispatcher
         –   The user
         –   The routing
         –   The I18N
         –   The Database
         –   …
  • These objects are specific to my Application and does not
    depend on the request
Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_09.php/hello/Fabien
  abstract class Application
  {
    public $dispatcher, $user, $routing;

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

          $this->configure();
      }

      abstract function configure();

      function handle($request)
      {
        return RequestHandler::handle($this, $request);
      }
  }




Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_09.php/hello/Fabien
  class HelloApplication extends Application
  {
    function configure()
    {
      $storage = new sfSessionStorage();
      $this->user = new sfUser($this->dispatcher, $storage);

          $this->routing = new sfPatternRouting($this->dispatcher);
          $this->routing->connect('hello', '/hello/:name',
             array('controller' => 'hello', 'action' => 'index'));
      }
  }

  $dispatcher = new sfEventDispatcher();
  $request = new sfWebRequest($dispatcher);

  $application = new HelloApplication($dispatcher);
  $response = $application->handle($request);

  $response->send();




Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Sensible defaults
  • Most of the time
         – The dispatcher is a sfEventDispatcher
         – The request is a sfWebRequest object
         – The controller must create a sfWebResponse object


  • Let’s introduce a new Controller abstract class
  • Modify the Application to takes defaults



Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_10.php/hello/Fabien
  class Controller
  {
    public $application;

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

      function renderToResponse($content)
      {
        $response = new sfWebResponse($this->application->dispatcher);
        $response->setContent($content);

          return $response;
      }
  }

  class helloController extends Controller
  {
    function indexAction($request)
    {
          $name = $request->getParameter('name', $this->application->user->getAttribute('name', 'World')));


          $this->application->user->setAttribute('name', $name);

          return $this->renderToResponse('Hello '.$name);
      }
  }
Symfony Camp 2007             www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_10.php/hello/Fabien
  abstract class Application
  {
    function __construct($dispatcher = null)
    {
          $this->dispatcher = is_null($dispatcher) ? new sfEventDispatcher() : $dispatcher;


          $this->configure();
      }

      function handle($request = null)
      {
          $request = is_null($request) ? new sfWebRequest($this->dispatcher) : $request;


          return RequestHandler::handle($this, $request);
      }
  }




Symfony Camp 2007       www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Let’s have a look at the code




Symfony Camp 2007      www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
The directory structure
  • A directory for each application
         – An application class
         – A controller directory
         – A template directory




Symfony Camp 2007    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_11.php/hello/Fabien
  class HelloApplication extends Application
  {
    function configure()
    {
      $storage = new sfSessionStorage();
      $this->user = new sfUser($this->dispatcher, $storage);

          $this->routing = new sfPatternRouting($this->dispatcher);
          $this->routing->connect('hello', '/hello/:name',
             array('controller' => 'hello', 'action' => 'index'));

          $this->template = new Template();

          $this->root = dirname(__FILE__);
      }
  }




Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_11.php/hello/Fabien
  class Template
  {
    function render($template, $parameters = array())
    {
      extract($parameters);

          ob_start();
          require $template;

          return ob_get_clean();
      }
  }

  class Controller
  {
    …
    function renderToResponse($templateName, $parameters = array())
    {
      $content = $this->application->template->render($templateName, $parameters);

          $response = new sfWebResponse($this->application->dispatcher);
          $response->setContent($content);

          return $response;
      }
  }


Symfony Camp 2007         www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Customization
  • Add some events in the RequestHandler
         – application.request
         – application.controller
         – application.response
         – application.exception


  • They can return a sfResponse and stop the
    RequestHandler flow


Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
http://localhost/step_12.php/hello/Fabien



  $parameters = array('request' => $request);

  $event = new sfEvent($application, 'application.request', $parameters);

  $application->dispatcher->notifyUntil($event);

  if ($event->isProcessed())
  {
    return $event->getReturnValue();
  }




Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
What for?
  • Page caching
         – application.request: If I have the page in cache,
           unserialize the response from the cache and returns it
         – application.response : Serialize the response to the
           cache
  • Security
         – application.controller: Check security and change the
           controller if needed



Symfony Camp 2007   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
class HelloApplication extends Application
  {
    function configure()
    {
      $storage = new sfSessionStorage();
      $this->user = new sfUser($this->dispatcher, $storage);

          $this->routing = new sfPatternRouting($this->dispatcher);
          $this->routing->connect('hello', '/hello/:name',
             array('controller' => 'hello', 'action' => 'index'));

          $this->template = new Template();

          $this->root = dirname(__FILE__);

          CacheListener::register($dispatcher, $this->root.'/cache/cache.db');
      }
  }




Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
class CacheListener
  {
    public $cache, $key;

      static function register($dispatcher, $database)
      {
          $listener = new __CLASS__();
          $listener->cache = new sfSQLiteCache(array('database' => $database));
          $dispatcher->connect('application.request', array($listener, 'listenToRequest'));
          $dispatcher->connect('application.response', array($listener, 'listenToResponse'));
      }

      function listenToRequest($event)
      {
        $this->key = md5($event->getParameter('request')->getPathInfo());

          if ($cache = $this->cache->get($this->key))
          {
              $this->setProcessed(true);
              $this->setReturnValue(unserialize($cache));
          }
      }

      function listenToResponse($event, $response)
      {
        $this->cache->set($this->key, serialize($response);

          return $response;
      }
  }


Symfony Camp 2007             www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Next symfony Workshops


   En français : Paris, France - Dec 05, 2007

     In English : Paris, France - Feb 13, 2008

               More info on www.sensiolabs.com

Symfony Camp 2007    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Join Us
  • Sensio Labs is recruiting in France
         – project managers
         – web developers
  • You have a passion for the web?
         – Web Developer : You have a minimum of 3 years experience in web
           development with Open-Source projects and you wish to participate to
           development of Web 2.0 sites using the best frameworks available.
         – Project Manager : You have more than 5 years experience as a developer
           and/or a project manager and you want to manage complex Web projects for
           prestigious clients.




Symfony Camp 2007     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
SENSIO S.A.
                                  26, rue Salomon de Rothschild
                                      92 286 Suresnes Cedex
                                             FRANCE
                                         Tél. : +33 1 40 99 80 80
                                         Fax : +33 1 40 99 83 34

                                              Contact
                                         Fabien Potencier
                                   fabien.potencier@sensio.com




        http://www.sensiolabs.com/                                  http://www.symfony-project.com/
Symfony Camp 2007    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com

Mais conteúdo relacionado

Mais procurados

OSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP hatersOSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP haters
Lin Yo-An
 
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo
Introduction to CloudForecast / YAPC::Asia 2010 TokyoIntroduction to CloudForecast / YAPC::Asia 2010 Tokyo
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo
Masahiro Nagano
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92
 

Mais procurados (20)

Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015
 
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPIPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
 
OSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP hatersOSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP haters
 
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo
Introduction to CloudForecast / YAPC::Asia 2010 TokyoIntroduction to CloudForecast / YAPC::Asia 2010 Tokyo
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo
 
The promise of asynchronous PHP
The promise of asynchronous PHPThe promise of asynchronous PHP
The promise of asynchronous PHP
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
 
PHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkPHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php framework
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021
 
[PL] Jak nie zostać "programistą" PHP?
[PL] Jak nie zostać "programistą" PHP?[PL] Jak nie zostać "programistą" PHP?
[PL] Jak nie zostać "programistą" PHP?
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
 
Essentials and Impactful Features of ES6
Essentials and Impactful Features of ES6Essentials and Impactful Features of ES6
Essentials and Impactful Features of ES6
 
async/await Revisited
async/await Revisitedasync/await Revisited
async/await Revisited
 
Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?
 
TestFest - Respect\Validation 1.0
TestFest - Respect\Validation 1.0TestFest - Respect\Validation 1.0
TestFest - Respect\Validation 1.0
 
Melhorando sua API com DSLs
Melhorando sua API com DSLsMelhorando sua API com DSLs
Melhorando sua API com DSLs
 
Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"
 
Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
 

Destaque

Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
Hugo Hamon
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
Fabien Potencier
 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 Integration
Jonathan Wage
 

Destaque (20)

What Symfony Has To Do With My Garage - Home Automation With PHP
What Symfony Has To Do With My Garage - Home Automation With PHPWhat Symfony Has To Do With My Garage - Home Automation With PHP
What Symfony Has To Do With My Garage - Home Automation With PHP
 
Decoupling Content Management with Create.js and PHPCR
Decoupling Content Management with Create.js and PHPCRDecoupling Content Management with Create.js and PHPCR
Decoupling Content Management with Create.js and PHPCR
 
Plugins And Making Your Own
Plugins And Making Your OwnPlugins And Making Your Own
Plugins And Making Your Own
 
Debugging With Symfony
Debugging With SymfonyDebugging With Symfony
Debugging With Symfony
 
OkAPI meet symfony, symfony meet OkAPI
OkAPI meet symfony, symfony meet OkAPIOkAPI meet symfony, symfony meet OkAPI
OkAPI meet symfony, symfony meet OkAPI
 
Symfony Internals
Symfony InternalsSymfony Internals
Symfony Internals
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
The new form framework
The new form frameworkThe new form framework
The new form framework
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
PHP, Cloud And Microsoft Symfony Live 2010
PHP,  Cloud And  Microsoft    Symfony  Live 2010PHP,  Cloud And  Microsoft    Symfony  Live 2010
PHP, Cloud And Microsoft Symfony Live 2010
 
Symfony in the Cloud
Symfony in the CloudSymfony in the Cloud
Symfony in the Cloud
 
How to Clear Cache in a Symfony Cross Application
How to Clear Cache in a Symfony Cross ApplicationHow to Clear Cache in a Symfony Cross Application
How to Clear Cache in a Symfony Cross Application
 
Apostrophe
ApostropheApostrophe
Apostrophe
 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 Integration
 
Doctrine in the Real World
Doctrine in the Real WorldDoctrine in the Real World
Doctrine in the Real World
 
Developing for Developers
Developing for DevelopersDeveloping for Developers
Developing for Developers
 
Doctrine Php Object Relational Mapper
Doctrine Php Object Relational MapperDoctrine Php Object Relational Mapper
Doctrine Php Object Relational Mapper
 
Symfony and eZ Publish
Symfony and eZ PublishSymfony and eZ Publish
Symfony and eZ Publish
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
Implementing a Symfony Based CMS in a Publishing Company
Implementing a Symfony Based CMS in a Publishing CompanyImplementing a Symfony Based CMS in a Publishing Company
Implementing a Symfony Based CMS in a Publishing Company
 

Semelhante a Symfony As A Platform (Symfony Camp 2007)

The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)
Fabien Potencier
 
Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)
Fabien Potencier
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
patter
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
Michael Peacock
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
Fabien Potencier
 

Semelhante a Symfony As A Platform (Symfony Camp 2007) (20)

The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)
 
Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Symfony 2 (PHP day 2009)
Symfony 2 (PHP day 2009)Symfony 2 (PHP day 2009)
Symfony 2 (PHP day 2009)
 
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!
 
Symfony 2.0
Symfony 2.0Symfony 2.0
Symfony 2.0
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers Cracow
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
PHP pod mikroskopom
PHP pod mikroskopomPHP pod mikroskopom
PHP pod mikroskopom
 
When symfony met promises
When symfony met promises When symfony met promises
When symfony met promises
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
 
Symfony internals [english]
Symfony internals [english]Symfony internals [english]
Symfony internals [english]
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 

Mais de Fabien Potencier

Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4
Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
Fabien Potencier
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
Fabien Potencier
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
Fabien Potencier
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
Fabien Potencier
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
Fabien Potencier
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
Fabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
Fabien Potencier
 
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
Fabien Potencier
 
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
Fabien Potencier
 

Mais de Fabien Potencier (20)

Varnish
VarnishVarnish
Varnish
 
Look beyond PHP
Look beyond PHPLook beyond PHP
Look beyond PHP
 
Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 
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
 
Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3
 
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
 
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
 
Playing With PHP 5.3
Playing With PHP 5.3Playing With PHP 5.3
Playing With PHP 5.3
 

Último

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Último (20)

Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 

Symfony As A Platform (Symfony Camp 2007)

  • 1. symfony symfony as a platform Fabien Potencier http://www.symfony-project.com/ http://www.sensiolabs.com/ Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 2. symfony 1.1 • A lot of internal refactoring… really a lot • Some new features… but not a lot – Tasks are now classes – More cache classes: APC, Eaccelerator, File, Memcache, SQLite, XCache – Configurable Routing: Pattern, PathInfo – … and some more • Yes, we will have a new form/validation system… but we still need some internal refactoring Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 3. Singletons 1.0 1.1 sfConfigCache sfConfigCache sfContext sfContext sfRouting sfWebDebug sfI18N sfLogger Remove Singletons Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 4. Why? // somewhere in the backend application $frontendRouting = sfContext::getInstance('frontend')->getRouting(); $url = $frontendRouting->generate('article', array('id' => 1)); // somewhere in a functional test $fabien = new sfTestBrowser('frontend'); $thomas = new sfTestBrowser('frontend'); $fabien->get('/talk_to/thomas/say/Hello'); $thomas->get('/last_messages'); $thomas->checkResponseElement('li', '/Hello/i'); Don’t try this at home… it won’t work… yet Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 5. symfony 1.0 Dependencies sfView sfResponse sfContext sfI18N sfRequest sfLogger sfStorage sfUser sfRouting Cleanup dependency Dependencies singleton Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 6. symfony 1.1 Dependencies sfRequest sfView sfResponse sfI18N sfEventDispatcher sfUser sfRouting sfStorage sfLogger sfContext Cleanup dependency Dependencies singleton Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 7. sfEventDispatcher • Based on Cocoa Notification Center // sfUser $event = new sfEvent($this, 'user.change_culture', array('culture' => $culture)); $dispatcher->notify($event); // sfI18N $callback = array($this, 'listenToChangeCultureEvent'); $dispatcher->connect('user.change_culture', $callback); • sfI18N and sfUser are decoupled • « Anybody » can listen to any event • You can notify existing events or create new ones Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 8. Why? Let’s talk about symfony 2.0… Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 9. The Web Workflow The User asks a Resource in a Browser The Browser sends a Request to the Server The Server sends back a Response The Browser displays the Resource to the User Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 10. http://localhost/step_00.php?name=Fabien session_start(); if (isset($_GET['name'])) { $name = $_GET['name']; } else if (isset($_SESSION['name'])) { $name = $_SESSION['name']; } else { $name = 'World'; } $_SESSION['name'] = $name; echo 'Hello '.$name; User > Resource > Request > Response Request Response Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 11. sfWebRequest PHP Object $_SERVER[‘REQUEST_METHOD’] >getMethod() $_GET[‘name’] >getParameter(‘name’) get_magic_quotes_gpc() ? stripslashes($_COOKIE[$name]) : $_COOKIE[$name]; >getCookie(‘name’) ( isset($_SERVER['HTTPS']) && ( strtolower($_SERVER ['HTTPS']) == 'on’ || >isSecure() strtolower($_SERVER ['HTTPS']) == 1) ) || ( isset($_SERVER ['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER ['HTTP_X_FORWARDED_PROTO']) == 'https') ) Mock sfWebRequest ) Abstract to test Parameters without a HTTP layer Headers Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 12. http://localhost/step_01.php?name=Fabien require dirname(__FILE__).'/../symfony_platform.php'; $dispatcher = new sfEventDispatcher(); $request = new sfWebRequest($dispatcher); session_start(); if ($request->hasParameter('name')) { $name = $request->getParameter('name'); } else if (isset($_SESSION['name'])) { $name = $_SESSION['name']; } else { $name = 'World'; } $_SESSION['name'] = $name; echo 'Hello '.$name; User > Resource > Request > Response Request Response Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 13. sfWebResponse PHP Object echo ‘Hello World!’ >setContent(‘Hello World’) header(‘HTTP/1.0 404 Not Found’) >setStatusCode(404) setcookie(‘name’, ‘value’) >setCookie(‘name’, ‘value’) Mock sfWebResponse Abstract to test Headers without a HTTP layer Cookies Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 14. http://localhost/step_02.php?name=Fabien require dirname(__FILE__).'/../symfony_platform.php'; $dispatcher = new sfEventDispatcher(); $request = new sfWebRequest($dispatcher); session_start(); if (!$name = $request->getParameter('name')) { if (isset($_SESSION['name'])) { $name = $_SESSION['name']; } else { $name = 'World'; } } $_SESSION['name'] = $name; $response = new sfWebResponse($dispatcher); $response->setContent('Hello '.$name); $response->send(); User > Resource > Request > Response Request Response Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 15. sfUser / sfStorage PHP Object $_SESSION[‘name’] = ‘value’ >setAttribute(‘name’, ‘value’) >setCulture(‘fr’) >setAuthenticated(true) Native session storage + MySQL, PostgreSQL, PDO, … Mock sfUser Abstract to test $_SESSION without a HTTP layer Add features Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 16. http://localhost/step_03.php?name=Fabien require dirname(__FILE__).'/../symfony_platform.php'; $dispatcher = new sfEventDispatcher(); $storage = new sfSessionStorage(); $user = new sfUser($dispatcher, $storage); $request = new sfWebRequest($dispatcher); if (!$name = $request->getParameter('name')) { if (!$name = $user->getAttribute('name')) { $name = 'World'; } } $user->setAttribute('name', $name); $response = new sfWebResponse($dispatcher); $response->setContent('Hello '.$name); $response->send(); User > Resource > Request > Response Request Response Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 17. http://localhost/step_04.php?name=Fabien require dirname(__FILE__).'/../symfony_platform.php'; $dispatcher = new sfEventDispatcher(); $storage = new sfSessionStorage(); $user = new sfUser($dispatcher, $storage); $request = new sfWebRequest($dispatcher); $name = $request->getParameter('name', $user->getAttribute('name', 'World'))); $user->setAttribute('name', $name); $response = new sfWebResponse($dispatcher); $response->setContent('Hello '.$name); $response->send(); User > Resource > Request > Response Request Response Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 18. sfRouting • Clean URLs <> Resources • Parses PATH_INFO to inject parameters in the sfRequest object • Several strategies: PathInfo, Pattern • Decouples Request and Controller Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 19. http://localhost/step_05.php/hello/Fabien require dirname(__FILE__).'/../symfony_platform.php'; $dispatcher = new sfEventDispatcher(); $storage = new sfSessionStorage(); $user = new sfUser($dispatcher, $storage); $routing = new sfPatternRouting($dispatcher); $routing->connect('hello', '/hello/:name'); $request = new sfWebRequest($dispatcher); $name = $request->getParameter('name', $user->getAttribute('name', 'World'))); $user->setAttribute('name', $name); $response = new sfWebResponse($dispatcher); $response->setContent('Hello '.$name); $response->send(); User > Resource > Request > Response Request Response Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 20. The Web Workflow The User asks a Resource in a Browser The Browser sends a Request to the Server The Server sends back a Response The Browser displays the Resource to the User Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 21. symfony 2.0 philosophy Request ? Response symfony gives symfony wants you a sfRequest a sfResponse Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 22. Let’s create symfony 2.0… Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 23. The Controller • The dispatching logic is the same for every resource • The business logic depends on the resource and is managed by the controller • The controller responsability is to « convert » the request to the response Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 24. http://localhost/step_06.php/hello/Fabien require dirname(__FILE__).'/../symfony_platform.php'; $dispatcher = new sfEventDispatcher(); $storage = new sfSessionStorage(); $user = new sfUser($dispatcher, $storage); $routing = new sfPatternRouting($dispatcher); $routing->connect('hello', '/hello/:name', array('controller' => 'hello', 'action' => 'index')); $request = new sfWebRequest($dispatcher); $class = $request->getParameter('controller').'Controller'; $method = $request->getParameter('action').'Action'; $controller = new $class(); $response = $controller->$method($dispatcher, $request, $user); $response->send(); Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 25. http://localhost/step_06.php/hello/Fabien class helloController { function indexAction($dispatcher, $request, $user) { $name = $request->getParameter('name', $user->getAttribute('name', 'World'))); $user->setAttribute('name', $name); $response = new sfWebResponse($dispatcher); $response->setContent('Hello '.$name); return $response; } } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 26. The RequestHandler • Handles the dispatching of the request • Calls the Controller • Has the responsability to return a sfResponse Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 27. http://localhost/step_07.php/hello/Fabien require dirname(__FILE__).'/../symfony_platform.php'; require dirname(__FILE__).'/step_07_framework.php'; $dispatcher = new sfEventDispatcher(); $storage = new sfSessionStorage(); $user = new sfUser($dispatcher, $storage); $routing = new sfPatternRouting($dispatcher); $routing->connect('hello', '/hello/:name', array('controller' => 'hello', 'action' => 'index')); $request = new sfWebRequest($dispatcher); $response = RequestHandler::handle($dispatcher, $request, $user); $response->send(); Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 28. http://localhost/step_07.php/hello/Fabien class RequestHandler { function handle($dispatcher, $request, $user) { $class = $request->getParameter('controller').'Controller'; $method = $request->getParameter('action').'Action'; $controller = new $class(); try { $response = $controller->$method($dispatcher, $request, $user); } catch (Exception $e) { $response = new sfWebResponse($dispatcher); $response->setStatusCode(500); $response->setContent(sprintf('An error occurred: %s', $e->getMessage())); } return $response; } } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 29. I WANT a sfResponse Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 30. http://localhost/step_08.php/hello/Fabien try { if (!class_exists($class)) { throw new Exception('Controller class does not exist'); } $controller = new $class(); if (!method_exists($class, $method)) { throw new Exception('Controller method does not exist'); } $response = $controller->$method($dispatcher, $request, $user); if (!is_object($response) || !$response instanceof sfResponse) { throw new Exception('Controller must return a sfResponse object'); } } catch (Exception $e) { $response = new sfWebResponse($dispatcher); $response->setStatusCode(500); $response->setContent(sprintf('An error occurred: %s', $e->getMessage())); } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 31. The Application $response = $controller->$method($dispatcher, $request, $user); • I need a container for my application objects – The dispatcher – The user – The routing – The I18N – The Database – … • These objects are specific to my Application and does not depend on the request Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 32. http://localhost/step_09.php/hello/Fabien abstract class Application { public $dispatcher, $user, $routing; function __construct($dispatcher) { $this->dispatcher = $dispatcher; $this->configure(); } abstract function configure(); function handle($request) { return RequestHandler::handle($this, $request); } } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 33. http://localhost/step_09.php/hello/Fabien class HelloApplication extends Application { function configure() { $storage = new sfSessionStorage(); $this->user = new sfUser($this->dispatcher, $storage); $this->routing = new sfPatternRouting($this->dispatcher); $this->routing->connect('hello', '/hello/:name', array('controller' => 'hello', 'action' => 'index')); } } $dispatcher = new sfEventDispatcher(); $request = new sfWebRequest($dispatcher); $application = new HelloApplication($dispatcher); $response = $application->handle($request); $response->send(); Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 34. Sensible defaults • Most of the time – The dispatcher is a sfEventDispatcher – The request is a sfWebRequest object – The controller must create a sfWebResponse object • Let’s introduce a new Controller abstract class • Modify the Application to takes defaults Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 35. http://localhost/step_10.php/hello/Fabien class Controller { public $application; function __construct($application) { $this->application = $application; } function renderToResponse($content) { $response = new sfWebResponse($this->application->dispatcher); $response->setContent($content); return $response; } } class helloController extends Controller { function indexAction($request) { $name = $request->getParameter('name', $this->application->user->getAttribute('name', 'World'))); $this->application->user->setAttribute('name', $name); return $this->renderToResponse('Hello '.$name); } } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 36. http://localhost/step_10.php/hello/Fabien abstract class Application { function __construct($dispatcher = null) { $this->dispatcher = is_null($dispatcher) ? new sfEventDispatcher() : $dispatcher; $this->configure(); } function handle($request = null) { $request = is_null($request) ? new sfWebRequest($this->dispatcher) : $request; return RequestHandler::handle($this, $request); } } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 37. Let’s have a look at the code Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 38. The directory structure • A directory for each application – An application class – A controller directory – A template directory Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 39. http://localhost/step_11.php/hello/Fabien class HelloApplication extends Application { function configure() { $storage = new sfSessionStorage(); $this->user = new sfUser($this->dispatcher, $storage); $this->routing = new sfPatternRouting($this->dispatcher); $this->routing->connect('hello', '/hello/:name', array('controller' => 'hello', 'action' => 'index')); $this->template = new Template(); $this->root = dirname(__FILE__); } } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 40. http://localhost/step_11.php/hello/Fabien class Template { function render($template, $parameters = array()) { extract($parameters); ob_start(); require $template; return ob_get_clean(); } } class Controller { … function renderToResponse($templateName, $parameters = array()) { $content = $this->application->template->render($templateName, $parameters); $response = new sfWebResponse($this->application->dispatcher); $response->setContent($content); return $response; } } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 41. Customization • Add some events in the RequestHandler – application.request – application.controller – application.response – application.exception • They can return a sfResponse and stop the RequestHandler flow Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 42. http://localhost/step_12.php/hello/Fabien $parameters = array('request' => $request); $event = new sfEvent($application, 'application.request', $parameters); $application->dispatcher->notifyUntil($event); if ($event->isProcessed()) { return $event->getReturnValue(); } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 43. What for? • Page caching – application.request: If I have the page in cache, unserialize the response from the cache and returns it – application.response : Serialize the response to the cache • Security – application.controller: Check security and change the controller if needed Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 44. class HelloApplication extends Application { function configure() { $storage = new sfSessionStorage(); $this->user = new sfUser($this->dispatcher, $storage); $this->routing = new sfPatternRouting($this->dispatcher); $this->routing->connect('hello', '/hello/:name', array('controller' => 'hello', 'action' => 'index')); $this->template = new Template(); $this->root = dirname(__FILE__); CacheListener::register($dispatcher, $this->root.'/cache/cache.db'); } } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 45. class CacheListener { public $cache, $key; static function register($dispatcher, $database) { $listener = new __CLASS__(); $listener->cache = new sfSQLiteCache(array('database' => $database)); $dispatcher->connect('application.request', array($listener, 'listenToRequest')); $dispatcher->connect('application.response', array($listener, 'listenToResponse')); } function listenToRequest($event) { $this->key = md5($event->getParameter('request')->getPathInfo()); if ($cache = $this->cache->get($this->key)) { $this->setProcessed(true); $this->setReturnValue(unserialize($cache)); } } function listenToResponse($event, $response) { $this->cache->set($this->key, serialize($response); return $response; } } Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 46. Next symfony Workshops En français : Paris, France - Dec 05, 2007 In English : Paris, France - Feb 13, 2008 More info on www.sensiolabs.com Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 47. Join Us • Sensio Labs is recruiting in France – project managers – web developers • You have a passion for the web? – Web Developer : You have a minimum of 3 years experience in web development with Open-Source projects and you wish to participate to development of Web 2.0 sites using the best frameworks available. – Project Manager : You have more than 5 years experience as a developer and/or a project manager and you want to manage complex Web projects for prestigious clients. Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 48. SENSIO S.A. 26, rue Salomon de Rothschild 92 286 Suresnes Cedex FRANCE Tél. : +33 1 40 99 80 80 Fax : +33 1 40 99 83 34 Contact Fabien Potencier fabien.potencier@sensio.com http://www.sensiolabs.com/ http://www.symfony-project.com/ Symfony Camp 2007 www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com