SlideShare una empresa de Scribd logo
1 de 86
Descargar para leer sin conexión
symfony
                                    Simplify your professional
                                    web development with PHP

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



International PHP 2007 Conference      www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Sensio
  • French Web Agency, founded in 1998
          – 150 people
          – 30 people dedicated to Web technologies

                                                               SENSIO
                                                              Web Agency




                                                                                 Web
                                              Webmarketing
                                                                             Technologies




                                                                              Open Source
                                                                             Technologies
                                                                           (Framework PHP)




International PHP 2007 Conference   www.symfony-project.com     fabien.potencier@sensio.com   www.sensiolabs.com
Sensio Labs
  • Open-Source technologies
          – Linux
          – Apache
          – MySQL / PostgreSQL
          – PHP / Perl / Python
  • Open-Source dedicated team
  • Big company customers
          – Web Consulting                                                                      symfony
                                                                                             PHP Framework
          – Audit / Training
          – Web Development

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
The symfony Framework
  •     PHP 5 Web Framework
  •     Based on 9 years of Sensio experience
  •     Based on well-known projets (Mojavi, Propel, Prado)
  •     Open-Source
  •     Built for :
          – Professional Websites
          – Complex needs
          – Demanding environments                                                                        Licence
                                                                                                            MIT


International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
The symfony Goals
  • Bring together the « Entreprise World »
    and the Open-Source World

  • Develop Faster

  • Don’t Reinvent the Wheel

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Develop Faster
  • Each line of code has a cost
          – To write the line                                                                   less code
                                                                                                    
          – To test it
                                                                                             less complexity
          – To maintain it                                                                          
                                                                                                less bugs
  • Write less code                                                                                 
          –    Architecture : controller, ORM, …                                            more productivity
                                                                                                    
          –    Configuration
                                                                                                more time
          –    Autoloading
          –    Generators
          –    Helpers
  • More time for business rules, edge cases, …
International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com    www.sensiolabs.com
Don’t Reinvent the Wheel
  • Follow best practices
  • MVC Pattern : Model / View / Controller

  • Unit and functional test framework
  •     Environment and deployment support
  •     Configurability
  •     Security (XSS and CSRF protection by default)
  •     Extensible (plugin system)
                                                 Simplify
  •     Admin Generator                        your Dev. Life

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Main Selling Points
  • symfony is about good code but also …

  • Documentation
          – GFDL book (450p)
          – The askeet tutorial (250p)

  • 1.0 maintained for a long time
          – 1 release a month (only bug fixes)                                                                1.0
          – Commercial support


International PHP 2007 Conference    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Let’s see some features




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Controller
  # apps/frontend/modules/blog/actions/actions.class.php
  class blogActions extends sfActions
  {                                               Controller blog/show
    function executeShow()
    {
      $id = $this->getRequestParameter('id');
                                                  Model call (Propel)
      $this->post = PostPeer::retrieveByPk($id);

              For the View


           $this->forward404Unless($this->post);
       }
                                    Shortcut
  }




International PHP 2007 Conference      www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Controller
  class blogActions extends sfActions
  {                                                                                                              1.0
    function executeShow()
    {
      $this->forward404Unless(
              $this->post = PostPeer::retrieveByPk($this->getRequestParameter('id'))
          );
      }
  }

  class blogActions extends sfActions
  {                                                                                                              1.1
    function showAction($request)
    {
      $this->forward404Unless(
               $this->post = PostPeer::retrieveByPk($request->getParameter('id'))
          );
      }
  }

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Controller (Doctrine)
  # apps/frontend/modules/blog/actions/actions.class.php
  class blogActions extends sfActions
  {
    function executeShow()
    {
      $id = $this->getRequestParameter('id');
      $this->post = Doctrine::getTable('Post')->find($id);

           $this->forward404Unless($this->post);
       }
  }




International PHP 2007 Conference     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Model (Propel)
  // lib/model/Author.php
  class Author extends BaseAuthor
  {
    function getFullName()
    {
      return $this->getFirstName().' '.$this->getLastName();
    }
  }

  $author = new Author();
  $author->setFirstName('Fabien');
  $author->setLastName('Potencier');
  $author->save();

  $post = new Post();
  $post->setAuthor($author);
  $post->setPublishedOn('tomorrow 12:00');
  $post->isPublished(true);
  $post->save();

  $posts = PostPeer::doSelect(new Criteria());



International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Model (Doctrine)
  // lib/model/doctrine/lib/Author.php
  class Author extends BaseAuthor
  {
    function getFullName()
    {
      return $this->getFirstName().' '.$this->getLastName();
    }
  }

  $author = new Author();
  $author->setFirstName('Fabien');
  $author->setLastName('Potencier');
                                                                       Same as in Propel
  $author->save();

  $post = new Post();
  $post->setAuthor($author);
  $post->setPublishedOn('tomorrow 12:00');
  $post->isPublished(true);
  $post->save();




  $posts = Doctrine::getTable('Post')->findAll();

  $post = Doctrine::getTable('Post')->find($request->getParameter('id'));




International PHP 2007 Conference            www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
View / Template
  # apps/frontend/modules/post/templates/showSuccess.php
  <h1 class="title">
    <?php echo $post->getTitle() ?>
  </h1>

  <h2>
    par <?php echo $post->getAuthor()->getFullName() ?>
  </h2>
                           Escaped       Escaped
  <p>
    <?php echo $post->getHtmlContent(ESC_RAW) ?>
  </p>
                                     Raw Value




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Routing
                                    homepage:
              /                       param: { module: blog, action: recent }                          url_for('@homepage')
                                      url:   /


                                    homepage:
               /                      param: { module: blog, action: list }
                                      url:   /
                                    recent:
         /recent
                                      param: { module: blog, action: recent }
                                      url:   /recent


                                    post:
                                                                                                  link_to(
                                      param: { module: blog, action: show }
        /blog/1                                                                                     $post->getTitle(),
                                      requirements:
                                                                                                    '@post?id='.$post->getId()
                                        id: d+
                                                                                                  )
                                      url:   /blog/:id



International PHP 2007 Conference         www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Routing in a Template
  <?php echo link_to($post->getTitle(), '@post?id='.$post->getId()) ?>




  <a href="<?php echo url_for('@post?id='.$post->getId()) ?>">Next Post</a>




  <?php echo link_to('Google', 'http://www.google.com/') ?>



  <a href="http://www.google.com/">Google</a>


                                                                                              Be pragmatic

International PHP 2007 Conference     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Tests: Database Fixtures
  • Test data
            # data/fixtures/data.yml
            Author:
              fabien:
                first_name: Fabien
                last_name: Potencier
            Post:
              first_post:
                author_id: fabien
                title:     IPC 2007 Conference

  $ ./symfony propel-load-data frontend



International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Functional Tests
  • Navigation simulation
          // test/functional/frontend/blogActionsTest.php
          $browser = new sfTestBrowser();
          $browser->initialize();
          $browser->
            get('/blog/1')->                                                                                        Fluent
            isStatusCode(200)->                                                                                     Interface
            checkResponseElement('h1.title', '/IPC 2007 Conference/');




           The power of CSS selectors

                                                                                                      TDD
                                                                                            Test Driven Development



International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com      www.sensiolabs.com
Be Happy… or not
  $ ./symfony test-functional frontend
  # get /
  ok 1 - status code is 200
  not ok 2 - response selector h1 does not match regex /IPC 2007 Conference/
  1..2
   Looks like you failed 1 tests of 2.




  $ ./symfony test-functional frontend
  # get /
  ok 1 - status code is 200
  ok 2 - response selector h1 matches regex /IPC 2007 Conference/
  1..2
   Looks like everything went fine.




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Functional Tests
  # simple CSS selectors
  checkResponseElement('h1.title', '/IPC 2007 Conference/')
  checkResponseElement('#title', '/IPC 2007 Conference/')

  # attribute selectors
  checkResponseElement('ul li a[class~="title"]', '/IPC 2007 Conference/')

  # combinators: > and +
  checkResponseElement('ul > li', '/IPC 2007 Conference/')

  # some CSS3 selectors
  checkResponseElement('#list li:first-child', '/IPC 2007 Conference/')
  checkResponseElement('#list li:nth-child(3)', '/IPC 2007 Conference/')
  checkResponseElement('#list li:contains("IPC 2007 Conference")')




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Functional Tests
  class ApplicationBrowser extends sfTestBrowser
  {
    public function signin($user, $password)
    {
      return $this->
        post('/signin', array('username' => $user, 'password' => $password))->
        isRedirect()->
        followRedirect()->
        checkResponseElement('div.username', 'Welcome back Fabien');
    }

      public function signout()
      {
        return $this->get('/signout');
      }                                                                                               DSL
  }                                                                                         Your own specific browser




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com      www.sensiolabs.com
Admin Generator: Backend Creation
  • Automatic generation of an Administration
    Backend, ready for production usage
          – Lists                          – Filters
          – Pagination                     – Validation
          – Sorting                        – CRUD

  $ ./symfony propel-init-admin frontend post Post



                                                                                            1) Creates a post module
                                                                                            2) Generates configuration


International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com     www.sensiolabs.com
Admin Generator
  • Generated code is MVC and customizable
          – Configuration file (generator.yml)
          – Extend the Controller
          – Override some Templates / Partials




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Admin Generator: Configurability
  # apps/frontend/modules/post/config/generator.yml
      generator:
         class:         sfPropelAdminGenerator
         param:
           model_class: Post
           list:
             display: [=title, author, created_at]
             filters: [title, author_id, published_on]
             max_per_page: 5




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Admin Generator
  • List




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Admin Generator
  • Edition




   __toString()


                                                              widgets                                      m2m relationship


International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Admin Generator: Extensibility
  • Module extension
          class postActions extends autoPostActions
          {
            protected function addFiltersCriteria($c)                                                        Generated
            {                                                                                                 module
              parent::addFiltersCriteria($c);
              $c->add(PostPeer::IS_PUBLISHED, true);
            }
          }

  • Template customization
               _edit_* : actions, footer, form, header, messages
               _list_* : footer, header, messages, td_actions, t(d|h)_stacked, t(d|h)_tabular
               _filters, editSuccess, listSuccess

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Debugging Tools
  • Web Debug Toolbar




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Debugging Tools
  • Error messages




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
What’s New in symfony 1.1?
  • A new task framework
  • Decoupling
          – Remove singletons
          – Remove dependencies between core classes
          – New Event Dispatcher system
  • Form / Validation framework




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
New Task Framework
  •     Easier to extend the symfony tasks
  •     Task namespaces
  •     Built-in help system
  •     Tasks are decoupled from the CLI
          – Can be called from the CLI
          – … or from your own code… easily




International PHP 2007 Conference     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Task Namespaces
  generate
    :app                              Generates               a   new    application (init-app)
    :batch                            Generates               a   new    batch (init-batch)
    :controller                       Generates               a   new    controller (init-controller)
    :module                           Generates               a   new    module (init-module)
    :project                          Generates               a   new    project (init-project)

  test
    :all                              Launches all tests
    :functional                       Launches functional tests
    :unit                             Launches unit tests

  i18n
    :extract                          Extracts i18n strings from php files
    :find                             Finds non "i18n ready" strings in an application



International PHP 2007 Conference   www.symfony-project.com       fabien.potencier@sensio.com   www.sensiolabs.com
Task Help
  $ ./symfony help plugin:install
  Usage:
   symfony plugin:install [--stability|-s="..."] [--release|-r="..."] [--channel|-
     c="..."] [--install_deps|-d] name

  Aliases: plugin-install

  Arguments:
   name                         The plugin name

  Options:
   --stability                  (-s)   The preferred stability (stable, beta, alpha)
   --release                    (-r)   The preferred version
   --channel                    (-c)   The PEAR channel name
   --install_deps               (-d)   Whether to force installation of required dependencies

  Description:
    …


International PHP 2007 Conference        www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Task Help
  Description:
   The plugin:install task installs a plugin:

      ./symfony plugin:install sfGuargPlugin

   By default, it installs the latest stable release.

    If you want to install a plugin that is not stable yet,
    use the stability option:

      ./symfony plugin:install --stability=beta sfGuargPlugin
      ./symfony plugin:install -s beta sfGuargPlugin

    You can also force the installation of a specific version:

      ./symfony plugin:install --release=1.0.0 sfGuargPlugin
      ./symfony plugin:install -r 1.0.0 sfGuargPlugin

   To force installation of all required dependencies, use the install_deps flag:

      ./symfony plugin:install --install-deps sfGuargPlugin
      ./symfony plugin:install -d sfGuargPlugin

   By default, the PEAR channel used is symfony-plugins
   (plugins.symfony-project.org).

   You can specify another channel with the channel option:

      ./symfony plugin:install --channel=mypearchannel sfGuargPlugin
      ./symfony plugin:install -c mypearchannel sfGuargPlugin
  …

International PHP 2007 Conference   www.symfony-project.com      fabien.potencier@sensio.com   www.sensiolabs.com
Task Calls in your Code
  # Somewhere in your code
  $task = new sfCacheClearTask($dispatcher);
  $task->run();




International PHP 2007 Conference   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

International PHP 2007 Conference     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

International PHP 2007 Conference      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


International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Form & Validation Framework
  •     Not a refactoring
  •     A different approach
  •     Almost no shared code
  •     Symfony 1.1 can still use the old system
          – set compat_10: on in settings.yml (off by default)
          – you can use the new and the old system in the same
            application
          – symfony 1.0 sfValidator class has been renamed to
            sfValidatorBase to avoid class name conflicts

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
The New Approach
  • Form as a first class object
  • Widget classes for form helpers
  • Validators validate arrays (it doesn’t care if it
    comes from a request, an XML file or a model
    object)
  • A decoupled system
          – Can be used without any other symfony class
          – 3 differents sub-systems
                 • Validators: can be used by themselves
                 • Widgets: can be used by themselves
                 • Form: glue between validators and widgets
International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Validators
  • Every validator extends sfValidator
  • A validator cleans and validates input values
  • sfValidator provides some common features
          – required (validation) > true by default
          – trim (cleaning) > false by default
  • Each validator can have options:
          – sfValidatorString: max_length, min_length



International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Validators
  // create a new string validator
  $v = new sfValidatorString(array('min_length' => 4));

  // clean and validate data
  $value = $v->clean('Fabien');

  // returns the input value
  $value == 'Fabien'

  // change some option
  $v->setOption('trim', true);

  $value = $v->clean(' Fabien ');

  // trims the input value
  $value == 'Fabien'                                                                    Validator objects
                                                                                          are stateless

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Custom Validator
  class CustomValidator extends sfValidator
  {
    protected function configure($options = array(), $messages = array())
    {
      $this->setOption('min_length', null);
      $this->setMessage('min_length', 'Too short.');
    }

      protected function doClean($value)
      {
        if (strlen($value) < $this->getOption('min_length'))
        {
          throw sfValidatorError($this, 'min_length', array('value' => $value));
        }

          return $value;
      }
  }




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Validators
  $v = new sfValidatorString(array('min_length' => 4));

  // throws a sfValidatorError
  $v->clean('Jon');

  $e->getCode() == 'min_length'
  $e->getMessage() == '"Jon" is too short (4 characters min).'

  $v->setMessage('min_length', 'Too short (%name%).');
  $e->getMessage() == 'Too short (Jon).'



                                                                                      Use error codes
                                                                                     or error messages

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Errors Internationalization
  $v = new sfValidatorString(array('min_length' => 4));

  try
  {
    $value = $v->clean('Jon');
  }
  catch (sfValidatorError $e)
  {
    echo $i18n->__($e->getMessageFormat(), $e->getArguments())."n";
    // or
    echo $i18n->__($e->getCode(), $e->getArguments())."n";
  }



                                                                                            Error messages
                                                                                             are i18n ready

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com    www.sensiolabs.com
sfValidator(All|Any)
  • You can aggregate validators to create a new validator:
          – sfValidatorAll: All validators must pass
          – sfValidatorAny: At least one validator must pass

  $v1 = new sfValidatorString(array('min_length' => 4));
  $v2 = new sfValidatorString(array('max_length' => 10));

  $v = new sfValidatorAll(array($v1, $v2));

  // values must validate both validators
  $v->clean('Fabien');




International PHP 2007 Conference    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidator(All|Any)
  • As they are validators themselves, you can create
    complex logic to validate your values:
       // v1 && (v2 || v3)
       $v = new sfValidatorAll(
              array($v1, sfValidatorAny($v2, $v3))
            );




International PHP 2007 Conference    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchema
  • A validator schema is composed of fields
  • A field is a named validator

  $v1 = new sfValidatorString(array('min_length' => 4));

  $v = new sfValidatorSchema(array(
         'first_name' => $v1,
         'last_name' => $v1,
       ));




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchema
  • The clean() method takes an array of named
    values and returns an array:
       $v->clean(array(
         'first_name' => 'Fabien',
         'last_name' => 'Potencier',
       ));




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchema
  • It collects all errors for all fields
  • It throws an exception with all errors

     sfValidatorErrorSchema:
        first_name: "Jon" is too short (4 characters min).
        last_name: "Jon" is too short (4 characters min).
      in ….php on line …




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchema
  • A named validator does not have access to the
    whole array of inputs, just its named value
  • Two special validators:
          – _pre_validator and _post_validator
          – They takes the array of values as input
          – They throw « global » errors



                                                                                                      Isolation


International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchema
  $v2 = new sfValidatorSchemaCompare(
     'password', '==', 'password_bis'
  );

  $v = new sfValidatorSchema(array(
    'password'     => $v1,
    'password_bis' => $v1,

    '_post_validator' => $v2,
  ));

  sfValidatorErrorSchema:
      "pass" does not match "word".
    in ….php on line …


International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchema
  • sfValidatorSchema is a sfValidator, so you can nest them

  $authorValidator = new sfValidatorSchema(array(
    'first_name' => $v1,
    'last_name' => $v1,
  ));

  $bookValidator =                  new sfValidatorSchema(array(
    'title'     =>                  $v1,
    'sub_title' =>                  $v1,
    'author'    =>                  $authorValidator,
  ));




International PHP 2007 Conference       www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchema
  $bookValidator->clean(array(
    'title'     => 'The symfony book',
    'sub_title' => 'The definitive guide',
    'author'    => array(
       'first_name' => 'Fabien',
       'last_name' => 'Potencier',
    ),
  ));




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchema
  • Secure by default
          – allow_extra_fields (false by default)
          – filter_extra_fields (true by default)
  • If you pass a value with no matching validator, sfValidatorSchema
    will throw an error
  • If you switch allow_extra_fields to true, then extra fields won’t
    trigger an error but will be removed from the cleaned values
  • If you also switch filter_extra_fields to false, then extra fields won’t
    be removed from the cleaned values




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchemaForEach
  $choiceValidator = new sfValidatorSchema(array(
    'choice' => $v1,
  ));

  $choicesValidator = new sfValidatorSchemaForEach($choiceValidator, 3);


  $pollValidator = new sfValidatorSchema(array(
    'question' => $v1,
    'choices' => $choicesValidator,
  ));




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfValidatorSchemaForEach
  $pollValidator->clean(array(
    'question' => 'Do you like symfony?',
    'choices' => array(
                    array('choice' => 'Yes'),
                    array('choice' => 'This is the best'),
                    array('choice' => 'A lot'),
                  ),
  ));




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Validators as Strings
  $postValidator = new sfValidatorOr(array(
    new sfValidatorSchemaFilter('age', new sfValidatorInteger(array('min' => 18))),
    new sfValidatorAll(array(
      new sfValidatorSchemaFilter('age', new sfValidatorInteger(array('max' => 18))),
      new sfValidatorSchemaFilter('is_young', new sfValidatorBoolean(array('required' => true))),
    )),
  ));



   $string = $postValidator->asString();
   '
     age:Integer({min: 18})
     or
     age:Integer({max: 18}) and is_young:Boolean({required: true})
   '

   $postValidator = new sfValidatorFromDescription($string);

   $postValidator->asPhp();

International PHP 2007 Conference    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Available Validators
  •     Boolean                                                •    All
  •     Choice                                                 •    Any
  •     ChoiceMany                                             •    Callback
  •     Date                                                   •    Decorator
  •     DateTime                                               •    Pass
  •     Email                                                  •    FromDescription
  •     Integer
  •     Number
                                                               •    Schema
  •     Regex
                                                               •    SchemaForEach
  •     String
                                                               •    SchemaCompare
  •     Time
                                                               •    SchemaFilter
  •     Url

International PHP 2007 Conference    www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Widgets
  • Every widget extends sfWidget
  • A widget is an object that can be rendered as an HTML
    string
  • sfWidget provides some common features
          –    renderTag()
          –    renderContentTag()
          –    Charset support
          –    XHTML or HTML closing tags
  • Each widget can have HTML attributes:
          – Takes care of escaping
          – Fixes double escaping problems


International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWidgetForm
  • Base class for all form widgets
  • Some more properties like isHidden()
  • Generates an id if none provided and the widget
    has a name
          – Default id is the widget name
          – Can be customized

                 $w = new sfWidgetFormInput();
                 $w->setIdFormat('id_%s');



International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWidgetForm classes
  // create a new input widget
  $w = new sfWidgetFormInput();

  // render widget
  echo $w->render('first_name', 'Fabien');

  // returns the widget as HTML
  <input type="text" name="first_name" value="Fabien" id="first_name" />


  // change some attributes
  $w->setAttribute('class', 'foo');

  <input … class="foo" />                                                                     Widget objects
                                                                                              are stateless

International PHP 2007 Conference     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWidgetForm classes
  // add default HTML attributes
  $w = new sfWidgetFormInput(array('class' => 'foo'));

  // render widget with some HTML attributes
  echo $w->render('first_name', 'Fabien', array('class' => 'foo'));




International PHP 2007 Conference     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWidgetFormSchema
  • A widget schema is composed of fields
  • A field is a named widget

  $w1 = new sfWidgetFormInput();

  $w = new sfWidgetFormSchema(array(
         'first_name' => $w1,
         'last_name' => $w1,
       ));




International PHP 2007 Conference     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWidgetFormSchema
  • The render() method takes an array of named
    values and returns an HTML string:
       $w->render(null, array(
         'first_name' => 'Fabien',
         'last_name' => 'Potencier',
       ));



  • You can also render individual fields


International PHP 2007 Conference     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWidgetFormSchema
  • sfWidgetFormSchema is a sfWidget, so you can nest
    them

  $authorWidget = new sfWidgetFormSchema(array(
    'first_name' => $w1,
    'last_name' => $w1,
  ));

  $bookWidget =                     new sfWidgetFormSchema(array(
    'title'                         => $w1,
    'sub_title'                     => $w1,
    'author'                        => $authorValidator,
  ));




International PHP 2007 Conference       www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWidgetFormSchema
  $bookWidget->render(null, array(
    'title'     => 'The symfony book',
    'sub_title' => 'The definitive guide',
    'author'    => array(
       'first_name' => 'Fabien',
       'last_name' => 'Potencier',
    ),
  ));




International PHP 2007 Conference     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfWidgetFormSchema
  • The render() method can also render
          – Errors
          – Nested form schema
  • The render() method uses a formatter class
          – sfWidgetFormSchemaFormatterList
          – sfWidgetFormSchemaFormatterTable
          – Or build your own




International PHP 2007 Conference     www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Forms
  • A sfForm is the glue between
          – A validator schema
          – A widget schema

  $validator = new sfValidatorSchema();
  $widget = new sfWidgetFormSchema();

  $form = new sfForm();
  $form->setValidatorSchema($validator);
  $form->setWidgetSchema($widget);




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfForm
  • You can also create your own form class

  class BookForm extends sfForm
  {
    public function configure()
    {
      $validator = new BookValidatorSchema();
      $widget    = new BookWidgetFormSchema();

            $this->setValidatorSchema($validator);
            $this->setWidgetSchema($widget);
       }
  }

International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
A Form in a Form
  $authorForm = new AuthorForm();

  $bookForm->embedForm($authorForm);



  $choiceForm = new ChoiceForm();

  $pollForm->embedFormForEach($choiceForm, 4);




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfForm
  $form = new AuthorForm();

  $input = array('first_name' => 'Fabien', 'last_name' => 'Potencier');
  $form->bind($input);
  if ($form->isValid())
  {
    // do something with the cleaned values
    $form->getValues();
  }
  else
  {
    // do something with the errors
    $form->getErrorSchema();
  }



International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfForm
  • sfForm can take default values
       $form = new AuthorForm(array('first_name' => 'Fabien'));



  • sfFormField objects are widgets bound to the
    input or default values
       echo $form->getFormField('first_name')->render();




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfForm
  $form = new AuthorForm();

  echo $form->getFormField('first_name')->render();
  // ===
  echo $form['first_name']->render();
  // ===
  echo $form['first_name'];

  // name and value are bound to the sfFormField object
  <input type="text" name="first_name" value="Fabien" id="first_name" />

  // add some HTML attributes
  echo $form['first_name']->render(array('class' => 'foo'));




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
For the laziest




                                                       echo $form




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Customize your Forms
                                                       $bookForm['author']

  <table>                           $bookForm['author']['first_name']->renderRow()

      <tr>
       <th>                 $bookForm['author']['first_name']->renderLabel()

            <label for="book_author_first_name">First Name</label>

                                         $bookForm['author']['first_name']->renderLabelName()
        </th>
        <td>
          <ul class="error_list">
            <li>Required.</li>                        $bookForm['author']['first_name']->renderError()
          </ul>
           <input type="text" name="book[author][first_name]" id="book_author_first_name" />


                                             $bookForm['author']['first_name']
     </td>
    </tr>
    ...
  </table>

International PHP 2007 Conference       www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Forms: In a symfony Action
  class bookActions extends sfActions
  {
    public function executeEdit($request)
    {
      $this->form = new AuthorForm();

          if ($request->isMethod('post'))
          {
            $this->form->bind($request->getParameter('book'));
            if ($this->form->isValid())
            {
              $values = $this->form->getValues();

                  $this->redirect('@homepage');
              }
          }
      }
  }




International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfFormPropel
  • Generated forms for Propel objects
  • Fully customizable
  • Introspects the Propel schema
          – Maps Propel/Creole types to symfony validators and
            widgets
          – Foreign keys
          – Many to many relationships
          – Internationalized tables


International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
sfFormPropel
  class bookActions                 extends sfActions
  {
    public function                 executeEdit($request)
    {
      $this->book =                 BookPeer::retrieveByPk($request->getParameter('id'));
      $this->form =                 new AuthorForm($this->book);

          if ($request->isMethod('post'))
          {
            $this->form->bind($request->getParameter('book');
            if ($this->form->isValid())
            {
              $book = $this->form->save();

                  $this->redirect('@book?id='.$book->getId());
              }
          }
      }
  }


International PHP 2007 Conference       www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Customize Propel Forms
  class BookForm extends BaseBookForm
  {
    public function configure()
    {
      $this->embedI18n(array('en', 'fr'));

           $this->widgetSchema['en']->setLabel('en', 'English');

           unset($this['created_at']);

           $this->validatorSchema['foo'] = new sfValidatorPass();
           $this->widgetSchema['foo'] = new sfWidgetIdentity();

           $this->setDefault('published_on', time());
       }
  }



International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
A Professional Web Framework
  • Built from experience
  • 1.0 stable, maintained with commercial support
  • Growing community
          – Developers in more than 80 countries
          – 200 000 visitors per month on symfony-project.com
          – 200 plugins in just 8 months
  • Open-Source Documentation
          – The book (450 pages - GFDL)
          – Askeet Tutorial (250 pages)


International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com
Yahoo! uses symfony
  • Yahoo! Bookmarks
          – 20 millions users
          – Web 2.0 / AJAX


  • del.icio.us
          – New beta on symfony
          – preview.delicious.com




International PHP 2007 Conference    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

International PHP 2007 Conference   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.


International PHP 2007 Conference   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/
International PHP 2007 Conference   www.symfony-project.com   fabien.potencier@sensio.com   www.sensiolabs.com

Más contenido relacionado

Similar a symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

symfony: An Open-Source Framework for Professionals (PHP Day 2008)
symfony: An Open-Source Framework for Professionals (PHP Day 2008)symfony: An Open-Source Framework for Professionals (PHP Day 2008)
symfony: An Open-Source Framework for Professionals (PHP Day 2008)Fabien Potencier
 
Write Plugins for symfony (Symfony Camp 2007)
Write Plugins for symfony (Symfony Camp 2007)Write Plugins for symfony (Symfony Camp 2007)
Write Plugins for symfony (Symfony Camp 2007)Fabien Potencier
 
Enterprise PHP (php|works 2008)
Enterprise PHP (php|works 2008)Enterprise PHP (php|works 2008)
Enterprise PHP (php|works 2008)Ivo Jansch
 
Continuous Integration Step-by-step
Continuous Integration Step-by-stepContinuous Integration Step-by-step
Continuous Integration Step-by-stepMichelangelo van Dam
 
Debugging with Zend Studio for Eclipse
Debugging with Zend Studio for EclipseDebugging with Zend Studio for Eclipse
Debugging with Zend Studio for EclipseOSSCube
 
DPC2007 Zend Framework (Gaylord Aulke)
DPC2007 Zend Framework (Gaylord Aulke)DPC2007 Zend Framework (Gaylord Aulke)
DPC2007 Zend Framework (Gaylord Aulke)dpc
 
Enterprise PHP Development - ZendCon 2008
Enterprise PHP Development - ZendCon 2008Enterprise PHP Development - ZendCon 2008
Enterprise PHP Development - ZendCon 2008Ivo Jansch
 
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
 
PHP - Programming language war, does it matter
PHP - Programming language war, does it matterPHP - Programming language war, does it matter
PHP - Programming language war, does it matterMizno Kruge
 
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
 
PHP in the Real World
PHP in the Real WorldPHP in the Real World
PHP in the Real WorldIvo Jansch
 
Introduction into PHP5 (Jeroen van Sluijs)
Introduction into PHP5 (Jeroen van Sluijs)Introduction into PHP5 (Jeroen van Sluijs)
Introduction into PHP5 (Jeroen van Sluijs)Stefan Koopmanschap
 
Streamlining Your Applications with Web Frameworks
Streamlining Your Applications with Web FrameworksStreamlining Your Applications with Web Frameworks
Streamlining Your Applications with Web Frameworksguestf7bc30
 
Plugin-able POS Solutions by Javascript @HDM9 Taiwan
Plugin-able POS Solutions by Javascript @HDM9 TaiwanPlugin-able POS Solutions by Javascript @HDM9 Taiwan
Plugin-able POS Solutions by Javascript @HDM9 TaiwanRack Lin
 
Lean Php Presentation
Lean Php PresentationLean Php Presentation
Lean Php PresentationAlan Pinstein
 
Integrating PHP With System-i using Web Services
Integrating PHP With System-i using Web ServicesIntegrating PHP With System-i using Web Services
Integrating PHP With System-i using Web ServicesIvo Jansch
 
Enterprise PHP (PHP London Conference 2008)
Enterprise PHP (PHP London Conference 2008)Enterprise PHP (PHP London Conference 2008)
Enterprise PHP (PHP London Conference 2008)Ivo Jansch
 
Symfony 2.0
Symfony 2.0Symfony 2.0
Symfony 2.0GrUSP
 

Similar a symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007) (20)

symfony: An Open-Source Framework for Professionals (PHP Day 2008)
symfony: An Open-Source Framework for Professionals (PHP Day 2008)symfony: An Open-Source Framework for Professionals (PHP Day 2008)
symfony: An Open-Source Framework for Professionals (PHP Day 2008)
 
Write Plugins for symfony (Symfony Camp 2007)
Write Plugins for symfony (Symfony Camp 2007)Write Plugins for symfony (Symfony Camp 2007)
Write Plugins for symfony (Symfony Camp 2007)
 
Enterprise PHP (php|works 2008)
Enterprise PHP (php|works 2008)Enterprise PHP (php|works 2008)
Enterprise PHP (php|works 2008)
 
Continuous Integration Step-by-step
Continuous Integration Step-by-stepContinuous Integration Step-by-step
Continuous Integration Step-by-step
 
Debugging with Zend Studio for Eclipse
Debugging with Zend Studio for EclipseDebugging with Zend Studio for Eclipse
Debugging with Zend Studio for Eclipse
 
DPC2007 Zend Framework (Gaylord Aulke)
DPC2007 Zend Framework (Gaylord Aulke)DPC2007 Zend Framework (Gaylord Aulke)
DPC2007 Zend Framework (Gaylord Aulke)
 
Enterprise PHP Development - ZendCon 2008
Enterprise PHP Development - ZendCon 2008Enterprise PHP Development - ZendCon 2008
Enterprise PHP Development - ZendCon 2008
 
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
 
PHP - Programming language war, does it matter
PHP - Programming language war, does it matterPHP - Programming language war, does it matter
PHP - Programming language war, does it matter
 
Symfony for non-techies
Symfony for non-techiesSymfony for non-techies
Symfony for non-techies
 
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
 
PHP in the Real World
PHP in the Real WorldPHP in the Real World
PHP in the Real World
 
Introduction into PHP5 (Jeroen van Sluijs)
Introduction into PHP5 (Jeroen van Sluijs)Introduction into PHP5 (Jeroen van Sluijs)
Introduction into PHP5 (Jeroen van Sluijs)
 
Streamlining Your Applications with Web Frameworks
Streamlining Your Applications with Web FrameworksStreamlining Your Applications with Web Frameworks
Streamlining Your Applications with Web Frameworks
 
Plugin-able POS Solutions by Javascript @HDM9 Taiwan
Plugin-able POS Solutions by Javascript @HDM9 TaiwanPlugin-able POS Solutions by Javascript @HDM9 Taiwan
Plugin-able POS Solutions by Javascript @HDM9 Taiwan
 
Lean Php Presentation
Lean Php PresentationLean Php Presentation
Lean Php Presentation
 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
 
Integrating PHP With System-i using Web Services
Integrating PHP With System-i using Web ServicesIntegrating PHP With System-i using Web Services
Integrating PHP With System-i using Web Services
 
Enterprise PHP (PHP London Conference 2008)
Enterprise PHP (PHP London Conference 2008)Enterprise PHP (PHP London Conference 2008)
Enterprise PHP (PHP London Conference 2008)
 
Symfony 2.0
Symfony 2.0Symfony 2.0
Symfony 2.0
 

Más 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.4Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Fabien Potencier
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Fabien Potencier
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Fabien Potencier
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Fabien Potencier
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 WorldFabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Fabien Potencier
 

Más 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
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
 
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
 

Último

DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
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 WorkerThousandEyes
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
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.pdfsudhanshuwaghmare1
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 

Último (20)

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
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 ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
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
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 

symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

  • 1. symfony Simplify your professional web development with PHP Fabien Potencier http://www.symfony-project.com/ http://www.sensiolabs.com/ International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 2. Sensio • French Web Agency, founded in 1998 – 150 people – 30 people dedicated to Web technologies SENSIO Web Agency Web Webmarketing Technologies Open Source Technologies (Framework PHP) International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 3. Sensio Labs • Open-Source technologies – Linux – Apache – MySQL / PostgreSQL – PHP / Perl / Python • Open-Source dedicated team • Big company customers – Web Consulting symfony PHP Framework – Audit / Training – Web Development International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 4. The symfony Framework • PHP 5 Web Framework • Based on 9 years of Sensio experience • Based on well-known projets (Mojavi, Propel, Prado) • Open-Source • Built for : – Professional Websites – Complex needs – Demanding environments Licence MIT International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 5. The symfony Goals • Bring together the « Entreprise World » and the Open-Source World • Develop Faster • Don’t Reinvent the Wheel International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 6. Develop Faster • Each line of code has a cost – To write the line less code  – To test it less complexity – To maintain it  less bugs • Write less code  – Architecture : controller, ORM, … more productivity  – Configuration more time – Autoloading – Generators – Helpers • More time for business rules, edge cases, … International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 7. Don’t Reinvent the Wheel • Follow best practices • MVC Pattern : Model / View / Controller • Unit and functional test framework • Environment and deployment support • Configurability • Security (XSS and CSRF protection by default) • Extensible (plugin system) Simplify • Admin Generator your Dev. Life International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 8. Main Selling Points • symfony is about good code but also … • Documentation – GFDL book (450p) – The askeet tutorial (250p) • 1.0 maintained for a long time – 1 release a month (only bug fixes) 1.0 – Commercial support International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 9. Let’s see some features International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 10. Controller # apps/frontend/modules/blog/actions/actions.class.php class blogActions extends sfActions { Controller blog/show function executeShow() { $id = $this->getRequestParameter('id'); Model call (Propel) $this->post = PostPeer::retrieveByPk($id); For the View $this->forward404Unless($this->post); } Shortcut } International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 11. Controller class blogActions extends sfActions { 1.0 function executeShow() { $this->forward404Unless( $this->post = PostPeer::retrieveByPk($this->getRequestParameter('id')) ); } } class blogActions extends sfActions { 1.1 function showAction($request) { $this->forward404Unless( $this->post = PostPeer::retrieveByPk($request->getParameter('id')) ); } } International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 12. Controller (Doctrine) # apps/frontend/modules/blog/actions/actions.class.php class blogActions extends sfActions { function executeShow() { $id = $this->getRequestParameter('id'); $this->post = Doctrine::getTable('Post')->find($id); $this->forward404Unless($this->post); } } International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 13. Model (Propel) // lib/model/Author.php class Author extends BaseAuthor { function getFullName() { return $this->getFirstName().' '.$this->getLastName(); } } $author = new Author(); $author->setFirstName('Fabien'); $author->setLastName('Potencier'); $author->save(); $post = new Post(); $post->setAuthor($author); $post->setPublishedOn('tomorrow 12:00'); $post->isPublished(true); $post->save(); $posts = PostPeer::doSelect(new Criteria()); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 14. Model (Doctrine) // lib/model/doctrine/lib/Author.php class Author extends BaseAuthor { function getFullName() { return $this->getFirstName().' '.$this->getLastName(); } } $author = new Author(); $author->setFirstName('Fabien'); $author->setLastName('Potencier'); Same as in Propel $author->save(); $post = new Post(); $post->setAuthor($author); $post->setPublishedOn('tomorrow 12:00'); $post->isPublished(true); $post->save(); $posts = Doctrine::getTable('Post')->findAll(); $post = Doctrine::getTable('Post')->find($request->getParameter('id')); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 15. View / Template # apps/frontend/modules/post/templates/showSuccess.php <h1 class="title"> <?php echo $post->getTitle() ?> </h1> <h2> par <?php echo $post->getAuthor()->getFullName() ?> </h2> Escaped Escaped <p> <?php echo $post->getHtmlContent(ESC_RAW) ?> </p> Raw Value International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 16. Routing homepage: / param: { module: blog, action: recent } url_for('@homepage') url: / homepage: / param: { module: blog, action: list } url: / recent: /recent param: { module: blog, action: recent } url: /recent post: link_to( param: { module: blog, action: show } /blog/1 $post->getTitle(), requirements: '@post?id='.$post->getId() id: d+ ) url: /blog/:id International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 17. Routing in a Template <?php echo link_to($post->getTitle(), '@post?id='.$post->getId()) ?> <a href="<?php echo url_for('@post?id='.$post->getId()) ?>">Next Post</a> <?php echo link_to('Google', 'http://www.google.com/') ?> <a href="http://www.google.com/">Google</a> Be pragmatic International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 18. Tests: Database Fixtures • Test data # data/fixtures/data.yml Author: fabien: first_name: Fabien last_name: Potencier Post: first_post: author_id: fabien title: IPC 2007 Conference $ ./symfony propel-load-data frontend International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 19. Functional Tests • Navigation simulation // test/functional/frontend/blogActionsTest.php $browser = new sfTestBrowser(); $browser->initialize(); $browser-> get('/blog/1')-> Fluent isStatusCode(200)-> Interface checkResponseElement('h1.title', '/IPC 2007 Conference/'); The power of CSS selectors TDD Test Driven Development International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 20. Be Happy… or not $ ./symfony test-functional frontend # get / ok 1 - status code is 200 not ok 2 - response selector h1 does not match regex /IPC 2007 Conference/ 1..2 Looks like you failed 1 tests of 2. $ ./symfony test-functional frontend # get / ok 1 - status code is 200 ok 2 - response selector h1 matches regex /IPC 2007 Conference/ 1..2 Looks like everything went fine. International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 21. Functional Tests # simple CSS selectors checkResponseElement('h1.title', '/IPC 2007 Conference/') checkResponseElement('#title', '/IPC 2007 Conference/') # attribute selectors checkResponseElement('ul li a[class~="title"]', '/IPC 2007 Conference/') # combinators: > and + checkResponseElement('ul > li', '/IPC 2007 Conference/') # some CSS3 selectors checkResponseElement('#list li:first-child', '/IPC 2007 Conference/') checkResponseElement('#list li:nth-child(3)', '/IPC 2007 Conference/') checkResponseElement('#list li:contains("IPC 2007 Conference")') International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 22. Functional Tests class ApplicationBrowser extends sfTestBrowser { public function signin($user, $password) { return $this-> post('/signin', array('username' => $user, 'password' => $password))-> isRedirect()-> followRedirect()-> checkResponseElement('div.username', 'Welcome back Fabien'); } public function signout() { return $this->get('/signout'); } DSL } Your own specific browser International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 23. Admin Generator: Backend Creation • Automatic generation of an Administration Backend, ready for production usage – Lists – Filters – Pagination – Validation – Sorting – CRUD $ ./symfony propel-init-admin frontend post Post 1) Creates a post module 2) Generates configuration International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 24. Admin Generator • Generated code is MVC and customizable – Configuration file (generator.yml) – Extend the Controller – Override some Templates / Partials International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 25. Admin Generator: Configurability # apps/frontend/modules/post/config/generator.yml generator: class: sfPropelAdminGenerator param: model_class: Post list: display: [=title, author, created_at] filters: [title, author_id, published_on] max_per_page: 5 International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 26. Admin Generator • List International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 27. Admin Generator • Edition __toString() widgets m2m relationship International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 28. Admin Generator: Extensibility • Module extension class postActions extends autoPostActions { protected function addFiltersCriteria($c) Generated { module parent::addFiltersCriteria($c); $c->add(PostPeer::IS_PUBLISHED, true); } } • Template customization _edit_* : actions, footer, form, header, messages _list_* : footer, header, messages, td_actions, t(d|h)_stacked, t(d|h)_tabular _filters, editSuccess, listSuccess International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 29. Debugging Tools • Web Debug Toolbar International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 30. Debugging Tools • Error messages International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 31. What’s New in symfony 1.1? • A new task framework • Decoupling – Remove singletons – Remove dependencies between core classes – New Event Dispatcher system • Form / Validation framework International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 32. New Task Framework • Easier to extend the symfony tasks • Task namespaces • Built-in help system • Tasks are decoupled from the CLI – Can be called from the CLI – … or from your own code… easily International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 33. Task Namespaces generate :app Generates a new application (init-app) :batch Generates a new batch (init-batch) :controller Generates a new controller (init-controller) :module Generates a new module (init-module) :project Generates a new project (init-project) test :all Launches all tests :functional Launches functional tests :unit Launches unit tests i18n :extract Extracts i18n strings from php files :find Finds non "i18n ready" strings in an application International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 34. Task Help $ ./symfony help plugin:install Usage: symfony plugin:install [--stability|-s="..."] [--release|-r="..."] [--channel|- c="..."] [--install_deps|-d] name Aliases: plugin-install Arguments: name The plugin name Options: --stability (-s) The preferred stability (stable, beta, alpha) --release (-r) The preferred version --channel (-c) The PEAR channel name --install_deps (-d) Whether to force installation of required dependencies Description: … International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 35. Task Help Description: The plugin:install task installs a plugin: ./symfony plugin:install sfGuargPlugin By default, it installs the latest stable release. If you want to install a plugin that is not stable yet, use the stability option: ./symfony plugin:install --stability=beta sfGuargPlugin ./symfony plugin:install -s beta sfGuargPlugin You can also force the installation of a specific version: ./symfony plugin:install --release=1.0.0 sfGuargPlugin ./symfony plugin:install -r 1.0.0 sfGuargPlugin To force installation of all required dependencies, use the install_deps flag: ./symfony plugin:install --install-deps sfGuargPlugin ./symfony plugin:install -d sfGuargPlugin By default, the PEAR channel used is symfony-plugins (plugins.symfony-project.org). You can specify another channel with the channel option: ./symfony plugin:install --channel=mypearchannel sfGuargPlugin ./symfony plugin:install -c mypearchannel sfGuargPlugin … International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 36. Task Calls in your Code # Somewhere in your code $task = new sfCacheClearTask($dispatcher); $task->run(); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 37. symfony 1.0 Dependencies sfView sfResponse sfContext sfI18N sfRequest sfLogger sfStorage sfUser sfRouting Cleanup dependency Dependencies singleton International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 38. symfony 1.1 Dependencies sfRequest sfView sfResponse sfI18N sfEventDispatcher sfUser sfRouting sfStorage sfLogger sfContext Cleanup dependency Dependencies singleton International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 39. 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 International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 40. Form & Validation Framework • Not a refactoring • A different approach • Almost no shared code • Symfony 1.1 can still use the old system – set compat_10: on in settings.yml (off by default) – you can use the new and the old system in the same application – symfony 1.0 sfValidator class has been renamed to sfValidatorBase to avoid class name conflicts International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 41. The New Approach • Form as a first class object • Widget classes for form helpers • Validators validate arrays (it doesn’t care if it comes from a request, an XML file or a model object) • A decoupled system – Can be used without any other symfony class – 3 differents sub-systems • Validators: can be used by themselves • Widgets: can be used by themselves • Form: glue between validators and widgets International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 42. Validators • Every validator extends sfValidator • A validator cleans and validates input values • sfValidator provides some common features – required (validation) > true by default – trim (cleaning) > false by default • Each validator can have options: – sfValidatorString: max_length, min_length International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 43. Validators // create a new string validator $v = new sfValidatorString(array('min_length' => 4)); // clean and validate data $value = $v->clean('Fabien'); // returns the input value $value == 'Fabien' // change some option $v->setOption('trim', true); $value = $v->clean(' Fabien '); // trims the input value $value == 'Fabien' Validator objects are stateless International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 44. Custom Validator class CustomValidator extends sfValidator { protected function configure($options = array(), $messages = array()) { $this->setOption('min_length', null); $this->setMessage('min_length', 'Too short.'); } protected function doClean($value) { if (strlen($value) < $this->getOption('min_length')) { throw sfValidatorError($this, 'min_length', array('value' => $value)); } return $value; } } International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 45. Validators $v = new sfValidatorString(array('min_length' => 4)); // throws a sfValidatorError $v->clean('Jon'); $e->getCode() == 'min_length' $e->getMessage() == '"Jon" is too short (4 characters min).' $v->setMessage('min_length', 'Too short (%name%).'); $e->getMessage() == 'Too short (Jon).' Use error codes or error messages International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 46. Errors Internationalization $v = new sfValidatorString(array('min_length' => 4)); try { $value = $v->clean('Jon'); } catch (sfValidatorError $e) { echo $i18n->__($e->getMessageFormat(), $e->getArguments())."n"; // or echo $i18n->__($e->getCode(), $e->getArguments())."n"; } Error messages are i18n ready International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 47. sfValidator(All|Any) • You can aggregate validators to create a new validator: – sfValidatorAll: All validators must pass – sfValidatorAny: At least one validator must pass $v1 = new sfValidatorString(array('min_length' => 4)); $v2 = new sfValidatorString(array('max_length' => 10)); $v = new sfValidatorAll(array($v1, $v2)); // values must validate both validators $v->clean('Fabien'); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 48. sfValidator(All|Any) • As they are validators themselves, you can create complex logic to validate your values: // v1 && (v2 || v3) $v = new sfValidatorAll( array($v1, sfValidatorAny($v2, $v3)) ); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 49. sfValidatorSchema • A validator schema is composed of fields • A field is a named validator $v1 = new sfValidatorString(array('min_length' => 4)); $v = new sfValidatorSchema(array( 'first_name' => $v1, 'last_name' => $v1, )); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 50. sfValidatorSchema • The clean() method takes an array of named values and returns an array: $v->clean(array( 'first_name' => 'Fabien', 'last_name' => 'Potencier', )); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 51. sfValidatorSchema • It collects all errors for all fields • It throws an exception with all errors sfValidatorErrorSchema: first_name: "Jon" is too short (4 characters min). last_name: "Jon" is too short (4 characters min). in ….php on line … International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 52. sfValidatorSchema • A named validator does not have access to the whole array of inputs, just its named value • Two special validators: – _pre_validator and _post_validator – They takes the array of values as input – They throw « global » errors Isolation International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 53. sfValidatorSchema $v2 = new sfValidatorSchemaCompare( 'password', '==', 'password_bis' ); $v = new sfValidatorSchema(array( 'password' => $v1, 'password_bis' => $v1, '_post_validator' => $v2, )); sfValidatorErrorSchema:   "pass" does not match "word". in ….php on line … International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 54. sfValidatorSchema • sfValidatorSchema is a sfValidator, so you can nest them $authorValidator = new sfValidatorSchema(array( 'first_name' => $v1, 'last_name' => $v1, )); $bookValidator = new sfValidatorSchema(array( 'title' => $v1, 'sub_title' => $v1, 'author' => $authorValidator, )); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 55. sfValidatorSchema $bookValidator->clean(array( 'title' => 'The symfony book', 'sub_title' => 'The definitive guide', 'author' => array( 'first_name' => 'Fabien', 'last_name' => 'Potencier', ), )); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 56. sfValidatorSchema • Secure by default – allow_extra_fields (false by default) – filter_extra_fields (true by default) • If you pass a value with no matching validator, sfValidatorSchema will throw an error • If you switch allow_extra_fields to true, then extra fields won’t trigger an error but will be removed from the cleaned values • If you also switch filter_extra_fields to false, then extra fields won’t be removed from the cleaned values International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 57. sfValidatorSchemaForEach $choiceValidator = new sfValidatorSchema(array( 'choice' => $v1, )); $choicesValidator = new sfValidatorSchemaForEach($choiceValidator, 3); $pollValidator = new sfValidatorSchema(array( 'question' => $v1, 'choices' => $choicesValidator, )); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 58. sfValidatorSchemaForEach $pollValidator->clean(array( 'question' => 'Do you like symfony?', 'choices' => array( array('choice' => 'Yes'), array('choice' => 'This is the best'), array('choice' => 'A lot'), ), )); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 59. Validators as Strings $postValidator = new sfValidatorOr(array( new sfValidatorSchemaFilter('age', new sfValidatorInteger(array('min' => 18))), new sfValidatorAll(array( new sfValidatorSchemaFilter('age', new sfValidatorInteger(array('max' => 18))), new sfValidatorSchemaFilter('is_young', new sfValidatorBoolean(array('required' => true))), )), )); $string = $postValidator->asString(); ' age:Integer({min: 18}) or age:Integer({max: 18}) and is_young:Boolean({required: true}) ' $postValidator = new sfValidatorFromDescription($string); $postValidator->asPhp(); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 60. Available Validators • Boolean • All • Choice • Any • ChoiceMany • Callback • Date • Decorator • DateTime • Pass • Email • FromDescription • Integer • Number • Schema • Regex • SchemaForEach • String • SchemaCompare • Time • SchemaFilter • Url International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 61. Widgets • Every widget extends sfWidget • A widget is an object that can be rendered as an HTML string • sfWidget provides some common features – renderTag() – renderContentTag() – Charset support – XHTML or HTML closing tags • Each widget can have HTML attributes: – Takes care of escaping – Fixes double escaping problems International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 62. sfWidgetForm • Base class for all form widgets • Some more properties like isHidden() • Generates an id if none provided and the widget has a name – Default id is the widget name – Can be customized $w = new sfWidgetFormInput(); $w->setIdFormat('id_%s'); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 63. sfWidgetForm classes // create a new input widget $w = new sfWidgetFormInput(); // render widget echo $w->render('first_name', 'Fabien'); // returns the widget as HTML <input type="text" name="first_name" value="Fabien" id="first_name" /> // change some attributes $w->setAttribute('class', 'foo'); <input … class="foo" /> Widget objects are stateless International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 64. sfWidgetForm classes // add default HTML attributes $w = new sfWidgetFormInput(array('class' => 'foo')); // render widget with some HTML attributes echo $w->render('first_name', 'Fabien', array('class' => 'foo')); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 65. sfWidgetFormSchema • A widget schema is composed of fields • A field is a named widget $w1 = new sfWidgetFormInput(); $w = new sfWidgetFormSchema(array( 'first_name' => $w1, 'last_name' => $w1, )); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 66. sfWidgetFormSchema • The render() method takes an array of named values and returns an HTML string: $w->render(null, array( 'first_name' => 'Fabien', 'last_name' => 'Potencier', )); • You can also render individual fields International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 67. sfWidgetFormSchema • sfWidgetFormSchema is a sfWidget, so you can nest them $authorWidget = new sfWidgetFormSchema(array( 'first_name' => $w1, 'last_name' => $w1, )); $bookWidget = new sfWidgetFormSchema(array( 'title' => $w1, 'sub_title' => $w1, 'author' => $authorValidator, )); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 68. sfWidgetFormSchema $bookWidget->render(null, array( 'title' => 'The symfony book', 'sub_title' => 'The definitive guide', 'author' => array( 'first_name' => 'Fabien', 'last_name' => 'Potencier', ), )); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 69. sfWidgetFormSchema • The render() method can also render – Errors – Nested form schema • The render() method uses a formatter class – sfWidgetFormSchemaFormatterList – sfWidgetFormSchemaFormatterTable – Or build your own International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 70. Forms • A sfForm is the glue between – A validator schema – A widget schema $validator = new sfValidatorSchema(); $widget = new sfWidgetFormSchema(); $form = new sfForm(); $form->setValidatorSchema($validator); $form->setWidgetSchema($widget); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 71. sfForm • You can also create your own form class class BookForm extends sfForm { public function configure() { $validator = new BookValidatorSchema(); $widget = new BookWidgetFormSchema(); $this->setValidatorSchema($validator); $this->setWidgetSchema($widget); } } International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 72. A Form in a Form $authorForm = new AuthorForm(); $bookForm->embedForm($authorForm); $choiceForm = new ChoiceForm(); $pollForm->embedFormForEach($choiceForm, 4); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 73. sfForm $form = new AuthorForm(); $input = array('first_name' => 'Fabien', 'last_name' => 'Potencier'); $form->bind($input); if ($form->isValid()) { // do something with the cleaned values $form->getValues(); } else { // do something with the errors $form->getErrorSchema(); } International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 74. sfForm • sfForm can take default values $form = new AuthorForm(array('first_name' => 'Fabien')); • sfFormField objects are widgets bound to the input or default values echo $form->getFormField('first_name')->render(); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 75. sfForm $form = new AuthorForm(); echo $form->getFormField('first_name')->render(); // === echo $form['first_name']->render(); // === echo $form['first_name']; // name and value are bound to the sfFormField object <input type="text" name="first_name" value="Fabien" id="first_name" /> // add some HTML attributes echo $form['first_name']->render(array('class' => 'foo')); International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 76. For the laziest echo $form International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 77. Customize your Forms $bookForm['author'] <table> $bookForm['author']['first_name']->renderRow() <tr> <th> $bookForm['author']['first_name']->renderLabel() <label for="book_author_first_name">First Name</label> $bookForm['author']['first_name']->renderLabelName() </th> <td> <ul class="error_list"> <li>Required.</li> $bookForm['author']['first_name']->renderError() </ul> <input type="text" name="book[author][first_name]" id="book_author_first_name" /> $bookForm['author']['first_name'] </td> </tr> ... </table> International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 78. Forms: In a symfony Action class bookActions extends sfActions { public function executeEdit($request) { $this->form = new AuthorForm(); if ($request->isMethod('post')) { $this->form->bind($request->getParameter('book')); if ($this->form->isValid()) { $values = $this->form->getValues(); $this->redirect('@homepage'); } } } } International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 79. sfFormPropel • Generated forms for Propel objects • Fully customizable • Introspects the Propel schema – Maps Propel/Creole types to symfony validators and widgets – Foreign keys – Many to many relationships – Internationalized tables International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 80. sfFormPropel class bookActions extends sfActions { public function executeEdit($request) { $this->book = BookPeer::retrieveByPk($request->getParameter('id')); $this->form = new AuthorForm($this->book); if ($request->isMethod('post')) { $this->form->bind($request->getParameter('book'); if ($this->form->isValid()) { $book = $this->form->save(); $this->redirect('@book?id='.$book->getId()); } } } } International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 81. Customize Propel Forms class BookForm extends BaseBookForm { public function configure() { $this->embedI18n(array('en', 'fr')); $this->widgetSchema['en']->setLabel('en', 'English'); unset($this['created_at']); $this->validatorSchema['foo'] = new sfValidatorPass(); $this->widgetSchema['foo'] = new sfWidgetIdentity(); $this->setDefault('published_on', time()); } } International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 82. A Professional Web Framework • Built from experience • 1.0 stable, maintained with commercial support • Growing community – Developers in more than 80 countries – 200 000 visitors per month on symfony-project.com – 200 plugins in just 8 months • Open-Source Documentation – The book (450 pages - GFDL) – Askeet Tutorial (250 pages) International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 83. Yahoo! uses symfony • Yahoo! Bookmarks – 20 millions users – Web 2.0 / AJAX • del.icio.us – New beta on symfony – preview.delicious.com International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 84. Next symfony Workshops En français : Paris, France - Dec 05, 2007 In English : Paris, France - Feb 13, 2008 More info on www.sensiolabs.com International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 85. 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. International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com
  • 86. 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/ International PHP 2007 Conference www.symfony-project.com fabien.potencier@sensio.com www.sensiolabs.com