SlideShare a Scribd company logo
1 of 91
Download to read offline
Symfony2 components to
the rescue of your PHP projects
Xavier Lacot – June 2012
Hello

     My name is Xavier Lacot
      ■    Web and Mobile at                             http://jolicode.com
      ■    Formerly PHP technical leader at Clever Age
      ■    Open Source convinced and contributor
            ■   In PHP, mainly Symfony
            ■   In javascript, etc.
      ■    Président of AFUP – the French PHP Users Association
           (afup.org)
            ■   Forum PHP
            ■   PHP Tour
      ■    http://twitter.com/xavierlacot
Symfony2 components to the rescue of your PHP projects                         2
JoliCode | Xavier Lacot | Symfony Live 2012
Summary


   1. PHP in 2012, a living ecosystem
   2. 2005's PHP is now just pain
   3. Migration strategies
        ■   The slow path
        ■   Switch progressively
   4. Symfony components for your pleasure
        ■   Your prefered migration toolkit
        ■   Case Study


Symfony2 components to the rescue of your PHP projects             3
JoliCode | Xavier Lacot | Symfony Live 2012
Before we start




How many of you use a framework on a regular basis?


      How many of you must deal with no-framework
                     applications?




Symfony2 components to the rescue of your PHP projects                     4
JoliCode | Xavier Lacot | Symfony Live 2012
PHP in 2012, a living ecosystem
A few things about PHP

■    A pragmatic language built for the Web
■    PHP5 since 2005
■    One of the most used languages on the Web




                          PHP – solves problems since 1995

Symfony2 components to the rescue of your PHP projects                            6
JoliCode | Xavier Lacot | Symfony Live 2012
The language improves

■   PHP 5.3 introduced new concepts :
      ■   Usage of namespaces
            namespace JoliCodeConferences;
            use GeneralTalkSession;

            class SymfonyLive extends Session
            {
                public function runPresentation()
                {
                    // do something nice...
                }
            }


      ■   Lambda and closures
      ■   Phar archives
      ■   “goto” WTF ???
Symfony2 components to the rescue of your PHP projects                           7
JoliCode | Xavier Lacot | Symfony Live 2012
Namespaces manipulation

■    Pro
      ■    No more collisions
      ■    Less ambiguity
      ■    Ahah, short class names. No more long classnames
■    Cons
      ■    Don't forget the use statement

       use OneFullClassname as Something;

       $object = new Something;



Symfony2 components to the rescue of your PHP projects                             8
JoliCode | Xavier Lacot | Symfony Live 2012
And it still evolves
■    PHP 5.4
      ■    Some deprecated features removed
      ■    Performance improvements
      ■    Instance Method Calls
          $post = (new Post)->setTitle('Hello poneys')->save();

      ■    Closures inside objects
      ■    Traits, aka. assisted copy/paste
      ■    Arrays manipulation
          function fruits() {
            return ['apple', 'banana', 'orange'];
          }

          echo fruits()[0]; // Outputs: apple

Symfony2 components to the rescue of your PHP projects                          9
JoliCode | Xavier Lacot | Symfony Live 2012
The ecosystem improves

■    Last years = bunch of new things
      ■    New (versions of) frameworks
      ■    New tools
            ■   Dependancies resolution
            ■   Code analysis
            ■   Continuous integration
      ■    Structuration of the projects
            ■   Standards
            ■   Discussions
            ■   More and more conferences


Symfony2 components to the rescue of your PHP projects                        10
JoliCode | Xavier Lacot | Symfony Live 2012
New frameworks




Symfony2 components to the rescue of your PHP projects                    11
JoliCode | Xavier Lacot | Symfony Live 2012
New frameworks




Symfony2 components to the rescue of your PHP projects                12
JoliCode | Xavier Lacot | Symfony Live 2012
ClassLoader and PSR-0

■    PSR-0 :
      ■    A standardization agreement
      ■    Scope: classes naming and organization

     class: SymfonyComponentHttpFoundationRequest
     path: vendor/src/Symfony/Component/HttpFoundation/Request.php


     class: Twig_Extension_Core
     path: vendor/twig/lib/Twig/Extension/Core.php




■    Idea : match the path of the file containg a class to
     this full class name
Symfony2 components to the rescue of your PHP projects                       13
JoliCode | Xavier Lacot | Symfony Live 2012
ClassLoader and PSR-0


                                                                 Namespaced classes style
 autoloading path prefix




     class: SymfonyComponentHttpFoundationRequest
     path: vendor/src/Symfony/Component/HttpFoundation/Request.php


     class: Twig_Extension_Core
     path: vendor/twig/lib/Twig/Extension/Core.php




                                                         PEAR naming style


Symfony2 components to the rescue of your PHP projects                                      14
JoliCode | Xavier Lacot | Symfony Live 2012
Composer

■    A packages management tool
■    Launched in 2012
      ■    Composer : a tool for managing
           dependancies
      ■    Packagist.org : a repository of
           packages



■    See the talk of Jordi Boggiano
     and Nils Adermann

Symfony2 components to the rescue of your PHP projects          15
JoliCode | Xavier Lacot | Symfony Live 2012
Dependancies resolution using Composer
                                                                 composer.json
    {
            "name": "joli/demo-project",
            "description": "A simple demo project",
            "require": {
                "php": ">=5.3.3",
                "symfony/symfony": "2.1.*",
                "seld/jsonlint": "1.0.0"
            }
    }



    $ php composer.phar install
    Installing dependencies from lock file
      - Updating twig/twig (dev-master)


■   And more:
        ■   Post install commands
        ■   Configuration variables
        ■   etc.
Symfony2 components to the rescue of your PHP projects                           16
JoliCode | Xavier Lacot | Symfony Live 2012
Packagist

■   The packages repository behind packagist
      ■   A great resource for finding high quality contributions
      ■   Definitively forget about PEAR or distro packages




■   Fear that packagist might break? Build your own
    repository with satis - https://github.com/composer/satis
Symfony2 components to the rescue of your PHP projects                      17
JoliCode | Xavier Lacot | Symfony Live 2012
Symfony2 components to the rescue of your PHP projects   18
JoliCode | Xavier Lacot | Symfony Live 2012
PHP gets is a professional language

■    PHP is not anymore an amateur language
      ■    Continuous integration (hi Jenkins, Sismo and Travis)
      ■    Unit tests (hi PHPUnit, SimpleTest, Atoum)
      ■    Code quality analysis and metrics
      ■    Code improvement tools (Hi PHP-CS-Fixer)
      ■    etc.
■    PHP developers have grew up since 2002
      ■    The language is more mature
      ■    The community too

Symfony2 components to the rescue of your PHP projects                                 19
JoliCode | Xavier Lacot | Symfony Live 2012
Symfony2 components to the rescue of your PHP projects   20
JoliCode | Xavier Lacot | Symfony Live 2012
Cheers GitHub




Symfony2 components to the rescue of your PHP projects               21
JoliCode | Xavier Lacot | Symfony Live 2012
GitHub

■    Social coding
      ■   Gathers many Open Source contributions
      ■   Watch, fork, comment, request pulls
      ■   Fun and nice
■    2,500,000 projects,
          ~ 150,000 PHP projects
■    A great market for the developer!


     PHP switched from SVN to Git

Symfony2 components to the rescue of your PHP projects        22
JoliCode | Xavier Lacot | Symfony Live 2012
Symfony2 components to the rescue of your PHP projects   23
JoliCode | Xavier Lacot | Symfony Live 2012
Summary


   1. PHP in 2012, a living ecosystem
   2. 2005's PHP is now just pain
   3. Migration strategies
        ■   The slow path
        ■   Switch progressively
   4. Symfony components for your pleasure
        ■   Your prefered migration toolkit
        ■   Case study


Symfony2 components to the rescue of your PHP projects         24
JoliCode | Xavier Lacot | Symfony Live 2012
2005's PHP is now just pain
Oh yes we did it...
                                                                  somewhere in 2002...
   <html>
     <body>
       <?php
       include("includes/menu.inc.php");
       $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php";

        if ( !file_exists($file) )
        {
          @include("pages/404.php");
        }
        else
        {
          $allowed = realpath('./pages');

           if ( !@ereg($allowed."*", realpath($file)) )
           {
             @include("pages/404.php");
           }
           else
           {
             @include($file);
           }
       }
       ?>
     </body>
   </html>




Symfony2 components to the rescue of your PHP projects                                      26
JoliCode | Xavier Lacot | Symfony Live 2012
Oh yes we did it...
                                                                  somewhere in 2002...
   <html>
     <body>
       <?php
       include("includes/menu.inc.php");
                                                             ■ HTML and PHP mix
       $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php";

        if ( !file_exists($file) )
        {
          @include("pages/404.php");
        }
        else
        {
          $allowed = realpath('./pages');

           if ( !@ereg($allowed."*", realpath($file)) )
           {
             @include("pages/404.php");
           }
           else
           {
             @include($file);
           }
       }
       ?>
     </body>
   </html>




Symfony2 components to the rescue of your PHP projects                                      27
JoliCode | Xavier Lacot | Symfony Live 2012
Oh yes we did it...
                                                                  somewhere in 2002...
   <html>
     <body>
       <?php
       include("includes/menu.inc.php");
                                                             ■  HTML and PHP mix
       $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php";

        if ( !file_exists($file) )
        {
                                                            ■   Direct access to
        }
          @include("pages/404.php");                            superglobals
        else
        {
          $allowed = realpath('./pages');

           if ( !@ereg($allowed."*", realpath($file)) )
           {
             @include("pages/404.php");
           }
           else
           {
             @include($file);
           }
       }
       ?>
     </body>
   </html>




Symfony2 components to the rescue of your PHP projects                                      28
JoliCode | Xavier Lacot | Symfony Live 2012
Oh yes we did it...
                                                                  somewhere in 2002...
   <html>
     <body>
       <?php
       include("includes/menu.inc.php");
                                                             ■  HTML and PHP mix
       $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php";

        if ( !file_exists($file) )
        {
                                                            ■   Direct access to
        }
          @include("pages/404.php");                            superglobals
        else
        {                                                   ■   Use of the @ operator
          $allowed = realpath('./pages');

           if ( !@ereg($allowed."*", realpath($file)) )
           {
             @include("pages/404.php");
           }
           else
           {
             @include($file);
           }
       }
       ?>
     </body>
   </html>




Symfony2 components to the rescue of your PHP projects                                      29
JoliCode | Xavier Lacot | Symfony Live 2012
Oh yes we did it...
                                                                  somewhere in 2002...
   <html>
     <body>
       <?php
       include("includes/menu.inc.php");
                                                             ■  HTML and PHP mix
       $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php";

        if ( !file_exists($file) )                          ■   Direct access to
        {
          @include("pages/404.php");                            superglobals
        }
        else
        {                                                   ■   Use of the @ operator
          $allowed = realpath('./pages');

           if ( !@ereg($allowed."*", realpath($file)) )
                                                            ■   Urls tied to code
           {                                                    structure
             @include("pages/404.php");
           }
           else
           {
             @include($file);
           }
       }
       ?>
     </body>
   </html>




Symfony2 components to the rescue of your PHP projects                                      30
JoliCode | Xavier Lacot | Symfony Live 2012
Oh yes we did it...
                                                                   somewhere in 2002...
   <html>
     <body>
       <?php
       include("includes/menu.inc.php");
                                                              ■  HTML and PHP mix
       $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php";

        if ( !file_exists($file) )                           ■   Direct access to
        {
          @include("pages/404.php");                             superglobals
        }
        else
        {
                                                             ■   Use of the @ operator
          $allowed = realpath('./pages');
                                                             ■   Urls tied to code
           if ( !@ereg($allowed."*", realpath($file)) )
           {                                                     structure
             @include("pages/404.php");
           }
           else
                                                             ■   Duplicate code
           {
             @include($file);
           }
       }
       ?>
     </body>
   </html>




Symfony2 components to the rescue of your PHP projects                                      31
JoliCode | Xavier Lacot | Symfony Live 2012
Symfony2 components to the rescue of your PHP projects   32
JoliCode | Xavier Lacot | Symfony Live 2012
Not bad at all




■    That was 10 years ago!
      ■    No PHP5 at that time
■    That was still flexible
■    Just missed some concepts




Symfony2 components to the rescue of your PHP projects                33
JoliCode | Xavier Lacot | Symfony Live 2012
The shit of today was great yesterday


                            So how did we improve things?




Symfony2 components to the rescue of your PHP projects       34
JoliCode | Xavier Lacot | Symfony Live 2012
2004 → 2007

■   First professional PHP frameworks
      ■   Zend Framework
      ■   Code Igniter
      ■   Seagull PHP
      ■   Cake PHP
      ■   symfony 1
      ■   Jelix
      ■   Pluf
      ■   Yii
      ■   etc.

Symfony2 components to the rescue of your PHP projects             35
JoliCode | Xavier Lacot | Symfony Live 2012
symfony 1

■    End 2005 : first public version (release 0.4)
      ■    Developers say “hurra”


                              ORM                        Functionnal and Unit tests
                               Ajax                         Internationalisation
                              Plugins                           Community
                             Console                              Helpers
                         Conventions                              Routing
                       Debug toolbar                              Cache
                       Documentation                               MVC
Symfony2 components to the rescue of your PHP projects                                     36
JoliCode | Xavier Lacot | Symfony Live 2012
Still not sufficient

■   Several limits:
      ■   Very monolithic
      ■   Not very flexible
            ■   Almost no components - use it all or don't use it
            ■   Some things were a pain to achieve
      ■   Extensive use of Singleton
      ■   Hard (impossible) to write complete test suites
      ■   Developers only
      ■   Performances... !
      ■   Lots of bad contribs
            ■   Low average community level
Symfony2 components to the rescue of your PHP projects                            37
JoliCode | Xavier Lacot | Symfony Live 2012
Symfony2 components to the rescue of your PHP projects   38
JoliCode | Xavier Lacot | Symfony Live 2012
Migration strategies
Summary


   1. PHP in 2012, a living ecosystem
   2. 2005's PHP is now just pain
   3. Migration strategies
        ■   The slow path
        ■   Switch progressively
   4. Symfony components for your pleasure
        ■   Your prefered migration toolkit
        ■   Case study


Symfony2 components to the rescue of your PHP projects         40
JoliCode | Xavier Lacot | Symfony Live 2012
Pre-conditions

■    You work since more than 5 years on your project
      ■   A bunch of functionnalities
      ■   The app is in production
      ■   Lots of users and data
      ■   A competent team
■    But
      ■   New developments are slow
      ■   Infrastructure problems
      ■   Hard to improve things
■    You want to trash it all, and code like in 2012
Symfony2 components to the rescue of your PHP projects                41
JoliCode | Xavier Lacot | Symfony Live 2012
Pre-conditions




                                            Your reality

Symfony2 components to the rescue of your PHP projects                  42
JoliCode | Xavier Lacot | Symfony Live 2012
Pre-conditions




                                      Your expectations

Symfony2 components to the rescue of your PHP projects                 43
JoliCode | Xavier Lacot | Symfony Live 2012
Strategy #1 – big bang

■   Most natural approach : rewrite everything
■   Pro:
      ■   A new solid and modern framework
      ■   Leave away from the old crappy codebase
      ■   Feel more happy
■   Cons:
      ■   Stop the company's business
      ■   Spend 1y+ re-developing everything
      ■   Have client cry
      ■   Complex migration scripts
      ■   Very risky
Symfony2 components to the rescue of your PHP projects                        44
JoliCode | Xavier Lacot | Symfony Live 2012
Strategy #1 – big bang


                                                   ■     Don't do that
                                                         ■   Too risky
                                                         ■   Lot of pressure
                                                         ■   Might lead to a disaster
                                                         ■   Your boss won't be happy


                                                   ■     Prefer a gradual approach



Symfony2 components to the rescue of your PHP projects                                   45
JoliCode | Xavier Lacot | Symfony Live 2012
Strategy #2 – Be progressive

■    Being progressive :
      ■    Re-write step by step
      ■    Control the way you build things
      ■    Use Framework parts, not the complete framework
            ■   Choose which parts to use
      ■    Gradually raise the level of your team


■    Less risky
      ■    And your boss will love you


Symfony2 components to the rescue of your PHP projects                              46
JoliCode | Xavier Lacot | Symfony Live 2012
Step #1

                              Switch to PHP 5.3 or PHP 5.4
                                                     NOW.

                                                                                           *

                 Historical                                                 Historical
                 codebase                                                   codebase


                   PHP x.x                                                   PHP 5.3



Symfony2 components to the rescue of your PHP projects                                         47
JoliCode | Xavier Lacot | Symfony Live 2012          thanks   w3techs.com
Step #1

■    Debian users :
      ■   Update your distribution version (eventually)
      ■   Update your packages (5 seconds)


■    Mac Users :
      ■   Please trash wamp and go grab http://php-osx.liip.ch/
          (kudos Liip)


■    Windows users
          Doh!
Symfony2 components to the rescue of your PHP projects            48
JoliCode | Xavier Lacot | Symfony Live 2012
Step #2

■    Create a solid foundation for your future new
     developments
      ■    Put new things in your project
      ■    Symfony components are up! Start with:
            ■   ClassLoader
            ■   DependencyInjection
            ■   HTTPFoundation


                                                                        ClassLoader
           Historical                                    Historical
                                                         codebase          DIC
           codebase
                                                                      HTTPFoundation

Symfony2 components to the rescue of your PHP projects                                 49
JoliCode | Xavier Lacot | Symfony Live 2012
Step #2 – install the components

■    Use composer
    {
           "autoload": {
               "psr-0": {}
           },
           "name": "xavierlacot/blog",
           "description": "My old blog on steroids",
           "require": {
               "php": ">=5.3.3",
               "symfony/class-loader": "2.1.*",
               "symfony/dependency-injection": "2.1.*",
               "symfony/http-foundation": "2.1.*"
           }
    }


    $ php composer.phar install
    Installing dependencies from lock file
      - Updating symfony/class-loader (dev-master)

Symfony2 components to the rescue of your PHP projects                                  50
JoliCode | Xavier Lacot | Symfony Live 2012
Step #2 – install the components

■    What did we install while doing this?
      ■    ClassLoader allows to load classes automagically, when
           required, if they follow a naming convention defined by
           PSR-0;
      ■    DependancyInjection provides a set of tools for building
           object and classes in a standardized way, and reduce the
           BC breaks;
      ■    HTTPFoundation is the basic toolkit when working with
           HTTP requests (all web pages, for example).


■    We'll see all three later un the presentation
Symfony2 components to the rescue of your PHP projects                                  51
JoliCode | Xavier Lacot | Symfony Live 2012
Step #2 – install the components


■    Composer is great
      ■    It comes with an autoloader
      ■    Using the classes is simple :
                                                                              index.php
     <?php
     require 'vendor/autoload.php';




      ■    And we're ready to start using the component classes!




Symfony2 components to the rescue of your PHP projects                                    52
JoliCode | Xavier Lacot | Symfony Live 2012
Step #3 – start using the components


■     HTTPFoundation is the easiest component to start
      with – the one you can immediately use without
      breaking things
                                                                             index.php
          use SymfonyComponentHttpFoundationRequest;
          $request = Request::createFromGlobals();




                                      CreateFromGlobals()
                                      analyses the superglobals
                                      and populates the Request
                                      object




    Symfony2 components to the rescue of your PHP projects                               53
    JoliCode | Xavier Lacot | Symfony Live 2012
Step #3 – use HTTPFoundation


                       Time to change your historical code...

        $pagename = (isset($_GET['page'])) ? $_GET['page'] : "404";
        $file = sprintf('pages/%s.php', $pagename);




                                                     becomes

         $pagename = $request->query->get('page', '404');
         $file = sprintf('pages/%s.php', $pagename);




Symfony2 components to the rescue of your PHP projects                              54
JoliCode | Xavier Lacot | Symfony Live 2012
Step #4

■    There's no step #4
■    The rest of the process is very similar
      ■    Integrate the component
      ■    Use it
      ■    Refactor your code
      ■    Simplify
■    Iterate – don't break everything at once. Use
     components gradually



Symfony2 components to the rescue of your PHP projects         55
JoliCode | Xavier Lacot | Symfony Live 2012
Symfony components for your pleasure
Summary


   1. PHP in 2012, a living ecosystem
   2. 2005's PHP is now just pain
   3. Migration strategies
        ■   The slow path
        ■   Switch progressively
   4. Symfony components for your pleasure
        ■   Your prefered migration toolkit
        ■   Case study


Symfony2 components to the rescue of your PHP projects         57
JoliCode | Xavier Lacot | Symfony Live 2012
So what are the Symfony Components ?

■    Symfony components are :
      ■    A set of independent libraries
            ■   You can use them separately
      ■    High quality code components, tested and documented
■    Symfony components are not :
      ■    A bootstrap
      ■    They do not provide end user fonctionnalities
■    They are the bricks of your new platform, but you
     will have to glue them together


Symfony2 components to the rescue of your PHP projects                      58
JoliCode | Xavier Lacot | Symfony Live 2012
Symfony components

■   The complete list is available at
    http://symfony.com/components
■   Symfony2 is built with the Symfony components
      ■   You will often use the symfony standard distribution, which
          contains all the components plus some bundles
      ■   Components do not depend on any third party library
■   All kind of stuff:
      ■   HTTP management                                ■   Internationalization process
      ■   Cache                                          ■   Templating
      ■   Files finder                                   ■   Forms management
      ■   Routing management                             ■   etc.
Symfony2 components to the rescue of your PHP projects                                      59
JoliCode | Xavier Lacot | Symfony Live 2012
Symfony components

■   Here is the list of what you can get :
     ■   BrowserKit
     ■   ClassLoader                                     ■   HttpKernel
     ■   Config                                          ■   Locale
     ■   Console                                         ■   Process
     ■   CssSelector                                     ■   Routing
     ■   DependencyInjection                             ■   Security
     ■   DomCrawler                                      ■   Serializer
     ■   EventDispatcher                                 ■   Templating
     ■   Finder                                          ■   Translation
     ■   Form                                            ■   Validator
     ■   HttpFoundation                                  ■   Yaml
Symfony2 components to the rescue of your PHP projects                          60
JoliCode | Xavier Lacot | Symfony Live 2012
Your prefered migration toolkit

■   I won't detail all the components
■   Here are (AMHA) the most useful (and straightforward) when
    migrating an old application:
     ■   ClassLoader
     ■   Console
     ■   DependencyInjection
     ■   Finder
     ■   HttpFoundation
     ■   Routing
     ■   Templating
     ■   Validator


■   If you want to use more, consider using Symfony2 at some point
Symfony2 components to the rescue of your PHP projects                                 61
JoliCode | Xavier Lacot | Symfony Live 2012
ClassLoader

■    loads classes automatically if they follow PSR-0;
■    Migration process:
            1. have your classes organization follow PSR-0 (renaming
            stuff)
                                 ldap.php                             src/Ldap/Client.php
    <?php                                                <?php
                                                         namespace Prefix/Ldap/Client;
    class prefixedLdapConnector
    {                                                    class Client
      public function __construct()                      {
        {                                                    public function __construct()
             // stuff                                        {
        }                                                        // stuff
    }                                                        }
                                                         }




            2. Configure the ClassLoader
Symfony2 components to the rescue of your PHP projects                                       62
JoliCode | Xavier Lacot | Symfony Live 2012
ClassLoader

■    loads classes automatically if they follow PSR-0;
■    Migration process:
            1. have your classes organization follow PSR-0 (renaming
            stuff)
                                 ldap.php                         src/Prefix/Ldap/Client.php
    <?php                                                <?php
                                                         namespace Prefix/Ldap;
    class prefixedLdapConnector
    {                                                    class Client
      public function __construct()                      {
        {                                                    public function __construct()
            // stuff                                         {
        }                                                        // stuff
    }                                                        }
                                                         }




            2. Configure the ClassLoader
Symfony2 components to the rescue of your PHP projects                                         63
JoliCode | Xavier Lacot | Symfony Live 2012
ClassLoader

■    Composer's autoloader is taking care of vendors
     installed by composer
■    We must declare “our” classes:
                                                             index.php
 use SymfonyComponentClassLoaderUniversalClassLoader;

 $loader = new UniversalClassLoader();
 $loader->registerNamespace('Prefix', __DIR__.'/src/');
 $loader->register();




■    Possible to declare several namespaces at once:
     registerNamespaces(array(...))


Symfony2 components to the rescue of your PHP projects                   64
JoliCode | Xavier Lacot | Symfony Live 2012
Console

■    Your best friend for writing:
      ■    Command line tasks
      ■    Cron jobs
      ■    Repetitive asynchron tasks
■    Pros:
      ■    Input / Output management
      ■    Colorization
      ■    Well written
      ■    Extensible

Symfony2 components to the rescue of your PHP projects         65
JoliCode | Xavier Lacot | Symfony Live 2012
Console

■    Add the Console component to composer.json
      "require": {
          "php": ">=5.3.3",
          "symfony/class-loader": "2.1.*",
          "symfony/console": "2.1.*",
          "symfony/dependency-injection": "2.1.*",
          "symfony/http-foundation": "2.1.*"
      }



■    Update the dependencies :
      $ php composer.phar update
      Updating dependencies
        - Installing symfony/console (dev-master)

      Writing lock file
      Generating autoload files


Symfony2 components to the rescue of your PHP projects         66
JoliCode | Xavier Lacot | Symfony Live 2012
Console
■   Write a new command:
                                                         src/Prefix/Command/TwitterCommand.php
<?php
namespace PrefixCommand;

class TwitterCommand extends Command
{
    protected function configure()
    {
                                                                               Hint: I did
        $this
                                                                               remove some
            ->setName('joli:twitter')
                                                                               “use”
            ->setDescription('Gets updates from twitter')
                                                                               statements
        ;
    }

     protected function execute(InputInterface $input, OutputInterface $output)
     {
         $puller = $this->getContainer()->get('joli.twitter.puller');
         $output->writeln("Contacting Twitter...");
         $data = $puller->pull();

           // do stuff with $data

           $output->writeln(sprintf('Tweets fetched. %s new tweets', count($tweets)));
     }
}

Symfony2 components to the rescue of your PHP projects                                       67
JoliCode | Xavier Lacot | Symfony Live 2012
Console

■   Then create the executable file itself:
                                                         console.php
       #!/usr/bin/env php
       <?php
       require 'autoload.php';

       use PrefixCommandTwitterCommand;
       use SymfonyComponentConsoleApplication;

       $application = new Application();
       $application->add(new TwitterCommand);
       $application->run();




■   Fix this file's permissions:
       $ chmod 755 console.php



Symfony2 components to the rescue of your PHP projects                 68
JoliCode | Xavier Lacot | Symfony Live 2012
Console

■    And finally run the command:
     $ ./console joli:twitter
     Contacting Twitter...
     Tweets successfuly fetched. 0 new tweets

     $ ./console
     Console Tool

     Usage:
       [options] command [arguments]

     Options:
       --help                 -h Display this help message.
       --quiet                -q Do not output any message.
       --verbose              -v Increase verbosity of messages.
       --version              -V Display this application version.
       --ansi                    Force ANSI output.
       --no-ansi                 Disable ANSI output.
       --no-interaction       -n Do not ask any interactive question.

     Available commands:
       help           Displays help for a command
       list           Lists commands
     joli
       joli:twitter   Gets updates from twitter

Symfony2 components to the rescue of your PHP projects                        69
JoliCode | Xavier Lacot | Symfony Live 2012
Dependency Injection

■   “Dependency Injection” is a rather cryptic name
     ■   No drugs here, promise
■   Here is an “old school” function prototype:

     function makeMenu($sqlConnection, $menu, $nbItems = null, $level =
     0, $startingWith = null)
                                                                                                *
■   It is bad, because:
     ■   The prototype will change when you will have new
         requirements
     ■   The order of the parameters is a hard constraint
     ■   Maybe one day you'll store menu items in a NoSQL database,
         and not in a relational one anymore
                                                 Copyright
Symfony2 components to the rescue of your PHP projects       me a long long long time ago   70
JoliCode | Xavier Lacot | Symfony Live 2012
Symfony2 components to the rescue of your PHP projects   71
JoliCode | Xavier Lacot | Symfony Live 2012
Your existing app

■    Your existing app does a lot of things
      ■    Sending emails
      ■    Parsing data
      ■    Writing logs
      ■    Storing data in databases




Symfony2 components to the rescue of your PHP projects                   72
JoliCode | Xavier Lacot | Symfony Live 2012
Dependency Injection

■    The Dependency Injection component provides a
     dependency injection container
      ■   Imagine a large array of resources widely used in the
          whole application
■    This “DIC” has some capacities:
      ■   Resources are instantiated only when required;
      ■   It is extensible;
      ■   Each item of this DIC is called a “service”
            ■   The SQL connection is a service
      ■   Passing the DIC to a class automatically gives access to a
          large collection of services...!
Symfony2 components to the rescue of your PHP projects                      73
JoliCode | Xavier Lacot | Symfony Live 2012
Dependency Injection




                      Initialization                                           Execution
                                                               Call the
                                                               service


                  Create services                        DIC
                                                         DIC                         $container->get('mailer')
 bootstrap


                                                               Instantiate a
                                                               non-existing
                                                                  service




Symfony2 components to the rescue of your PHP projects                                                  74
JoliCode | Xavier Lacot | Symfony Live 2012
Implement your own services

■    In the migration plan:
      ■    convert the “service” functionnalities into real Symfony2
           services,
      ■    Create binding to the existing calls
      ■    use them like before
      ■    In the future, put all your services in the container.
            ■   And use them from there




Symfony2 components to the rescue of your PHP projects                             75
JoliCode | Xavier Lacot | Symfony Live 2012
DIC migration
■   Imagine we have a “Mailer” class:
     <?php
     namespace PrefixMailer;

     class Mailer
     {
         $prefix = '';

          public function send($to, $subject, $body)
          {
              // etc.
          }
     }




■   A mail is sent in our code with:
     function saveUser($name, $email)
     {
         // stuff here

           $mailer = new Mailer;
           $mailer->send($user->getEmail(), 'Welcome '.$user->getName(), 'A test');
     }


Symfony2 components to the rescue of your PHP projects                                76
JoliCode | Xavier Lacot | Symfony Live 2012
DIC migration
■    Create the service container:
     use SymfonyComponentDependencyInjectionContainerBuilder;

     $container = new ContainerBuilder();
     $container->register('mailer', 'Mailer');




■    Pass it to our users management class
■    Use it:
     function saveUser($name, $email)
     {
         // stuff here

           $mailer = $this->container->get('mailer');
           $mailer->send($user->getEmail(), 'Welcome '.$user->getName(), 'A test');

     }


Symfony2 components to the rescue of your PHP projects                                77
JoliCode | Xavier Lacot | Symfony Live 2012
DIC migration

■    Benefits:
      ■    The Mailer object is now only created in one place
      ■    Its configuration is centralized
      ■    It is easy to override in the user management class




Symfony2 components to the rescue of your PHP projects               78
JoliCode | Xavier Lacot | Symfony Live 2012
HttpFoundation

■    We have already used a little the HTTP Foundation
     component
■    One core concept of Symfony2 is the coverage of
     the framework
      ■    It handles Requests
      ■    And returns Responses
                                                         Request


          User                                           HTTP            Application


                                                         Response


Symfony2 components to the rescue of your PHP projects                                 79
JoliCode | Xavier Lacot | Symfony Live 2012
HttpFoundation

■    HttpFoundation provides concepts for Request and Responses
      ■    Every input from the user, or output to the user should
           pass through this component
■    Request:
       use SymfonyComponentHttpFoundationRequest;
       $request = Request::createFromGlobals();


      ■    $request→request represents $_POST
      ■    $request→query represents $_GET
      ■    $request→cookies represents $_COOKIE
      ■    etc.

Symfony2 components to the rescue of your PHP projects                80
JoliCode | Xavier Lacot | Symfony Live 2012
HttpFoundation

■    Response:
      ■    Represents the stuff returned to the user through HTTP
       use SymfonyComponentHttpFoundationResponse;
       $response = new Response();




      ■    It implements HTTP 1.1, the response is customizable:
       $response->setContent('This will be the response content');
       $response->headers->set('Content-Type', 'text/html');
       $response->setStatusCode(200);

       // send the Response
       $response->prepare($request);
       $response->send();


Symfony2 components to the rescue of your PHP projects                81
JoliCode | Xavier Lacot | Symfony Live 2012
Migration plan for using HttpFoundation

■    HTTPFoundation will help:
      ■    Making your application more secure
      ■    Enforce a normalization of the way the output is sent ot
           the user
■    Migration plan:
      ■    Start with systematically using the Request ibject in place
           of the superglobals
      ■    Use Response objects whenever possible
            ■   ob_* may help you
            ■   Use a templating system to move view content in
                separate files
Symfony2 components to the rescue of your PHP projects                         82
JoliCode | Xavier Lacot | Symfony Live 2012
Routing Component – what we did before...

■    Didn't you find nasty the way we manage urls in
     our old app?
        $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php";

        if ( !file_exists($file) )
        {
          @include("pages/404.php");
        }
        else
        {
          $allowed = realpath('./pages');

            if ( !@ereg($allowed."*", realpath($file)) )
            {
              @include("pages/404.php");
            }
            else
            {
              @include($file);
            }
        }




Symfony2 components to the rescue of your PHP projects                                       83
JoliCode | Xavier Lacot | Symfony Live 2012
Routing Component – what we did before...


■    Yes, it is far from perfect:
      ■   Urls enforce code organization
      ■   This system may cause security problems
            ■   What if the “$allowed” check doesn't work?
      ■   It is not extensible
      ■   The url ↔ action matching is hardcoded, which means no
          possible alternative
      ■   Bad for SEO
            ■   http://example.org/index.php?page=news&id=3657
■    The Symfony2 Routing component helps handling urls
     in an abstract way
Symfony2 components to the rescue of your PHP projects                      84
JoliCode | Xavier Lacot | Symfony Live 2012
Routing Component

■    Routing is a mechanism which allows to manage the
     address map of an application
■    Very useful:
      ■    Better SEO
      ■    Better security
      ■    Help reorganize the application internally
      ■    Do not expose the technology you use




Symfony2 components to the rescue of your PHP projects                   85
JoliCode | Xavier Lacot | Symfony Live 2012
Routing

■   There are two types of routing
      ■   “Descending” routing: maps an URI to an action the application
          must complete:
           ■   /blog must display the list of posts
           ■   /blog/2010/05/12/un-message.html must display the right post
           ■   /contact must display the contact form


                                         /blog
                 User
                                   Descending routing



      ■   “ascending” routing helps generate nice, SEO compliant URLs

Symfony2 components to the rescue of your PHP projects                         86
JoliCode | Xavier Lacot | Symfony Live 2012
Routing component – migration plan

■    The migration plan for using this component will
     strongly depend on the way you developed your
     application.
■    Usually:
      ■    Add the component to composer.json, update
      ■    In the front controller, use the routing to match certain
           urls and handle the request in a clean way
            ■   This way, it won't affect other URLs
■    Once installed, always use the Router when
     exposing new URLs

Symfony2 components to the rescue of your PHP projects                             87
JoliCode | Xavier Lacot | Symfony Live 2012
In our example...
■    First, declare the routes                                  Hint: I did
                                                                remove some
       // declare the routes                                    “use”
       $routes = new RouteCollection();                         statements
       $routes->add(
          'blog_show',
          new Route(
            '/blog/{year}/{month}/{slug}',
            array('pagename' => 'display_blog')
          )
       );


■    Then, match the requests to find the page to load
       $context = new RequestContext();
       $context->fromRequest($request);
       $matcher = new UrlMatcher($routes, $context);

      try                                                       $route now
      {                                                         contains the
         $route = $matcher->match($request->getRequestUri());   matched route
         // do things                                           parameters
      }
      catch (ResourceNotFoundException $e)
Symfony2 // handle the rescue of your } projects
      { components to exception PHP                                             88
JoliCode | Xavier Lacot | Symfony Live 2012
Generating URLs with the Routing Component

■    $router::generate() allows to generate a URL with
     parameters:
     $generator = new UrlGenerator($routes, $context);
     $url = $generator->generate('blog_show', array(
         'slug' => 'hello-les-poneys',
         'year' => '2011',
         'month' => '11'
     ));
     $response->setContent('Please go <a href="'.$url.'">here</a>');
     $response->send();




■    Of course, add the Routing as a service to the
     container!
Symfony2 components to the rescue of your PHP projects                 89
JoliCode | Xavier Lacot | Symfony Live 2012
Questions ?
                                                         Contact
                                                         Xavier Lacot
                                                         xlacot@jolicode.com
                                                         06 51 48 59 73
                                                         http://jolicode.com
                                                         Twitter : @JoliCode




Symfony2 components to the rescue of your PHP projects                         90
JoliCode | Xavier Lacot | Symfony Live 2012
Credits

■    Photos – thanks to the photographers:
      ■    http://www.flickr.com/photos/artbandito/67829362/
      ■    http://capsizedatsea.tumblr.com/post/9559345143
      ■    http://memegenerator.net




Symfony2 components to the rescue of your PHP projects             91
JoliCode | Xavier Lacot | Symfony Live 2012

More Related Content

What's hot

Python on Android with Delphi FMX - The Cross Platform GUI Framework
Python on Android with Delphi FMX - The Cross Platform GUI Framework Python on Android with Delphi FMX - The Cross Platform GUI Framework
Python on Android with Delphi FMX - The Cross Platform GUI Framework Embarcadero Technologies
 
Living in a multiligual world: Internationalization for Web 2.0 Applications
Living in a multiligual world: Internationalization for Web 2.0 ApplicationsLiving in a multiligual world: Internationalization for Web 2.0 Applications
Living in a multiligual world: Internationalization for Web 2.0 ApplicationsLars Trieloff
 
#JavaOne What's in an object?
#JavaOne What's in an object?#JavaOne What's in an object?
#JavaOne What's in an object?Charlie Gracie
 
The Whole Platform A Language Workbench for Eclipse
The Whole Platform A Language Workbench for EclipseThe Whole Platform A Language Workbench for Eclipse
The Whole Platform A Language Workbench for EclipseRiccardo Solmi
 
Python for Delphi Developers - Part 1 Introduction
Python for Delphi Developers - Part 1 IntroductionPython for Delphi Developers - Part 1 Introduction
Python for Delphi Developers - Part 1 IntroductionEmbarcadero Technologies
 
Introduction to Python GUI development with Delphi for Python - Part 1: Del...
Introduction to Python GUI development with Delphi for Python - Part 1:   Del...Introduction to Python GUI development with Delphi for Python - Part 1:   Del...
Introduction to Python GUI development with Delphi for Python - Part 1: Del...Embarcadero Technologies
 
Living in a Multi-lingual World: Internationalization in Web and Desktop Appl...
Living in a Multi-lingual World: Internationalization in Web and Desktop Appl...Living in a Multi-lingual World: Internationalization in Web and Desktop Appl...
Living in a Multi-lingual World: Internationalization in Web and Desktop Appl...adunne
 
Android on Windows 11 - A Developer's Perspective (Windows Subsystem For Andr...
Android on Windows 11 - A Developer's Perspective (Windows Subsystem For Andr...Android on Windows 11 - A Developer's Perspective (Windows Subsystem For Andr...
Android on Windows 11 - A Developer's Perspective (Windows Subsystem For Andr...Embarcadero Technologies
 
llvm-py: Writing Compilers In Python
llvm-py: Writing Compilers In Pythonllvm-py: Writing Compilers In Python
llvm-py: Writing Compilers In Pythonmdevan
 
Part II: LLVM Intermediate Representation
Part II: LLVM Intermediate RepresentationPart II: LLVM Intermediate Representation
Part II: LLVM Intermediate RepresentationWei-Ren Chen
 
Eclipse OMR: a modern toolkit for building language runtimes
Eclipse OMR: a modern toolkit for building language runtimesEclipse OMR: a modern toolkit for building language runtimes
Eclipse OMR: a modern toolkit for building language runtimesMark Stoodley
 
PyPy
PyPyPyPy
PyPyESUG
 
Programming With WinRT And Windows8
Programming With WinRT And Windows8Programming With WinRT And Windows8
Programming With WinRT And Windows8Rainer Stropek
 
I Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java BytecodeI Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java BytecodeAlexander Shopov
 
LinkedIn - Disassembling Dalvik Bytecode
LinkedIn - Disassembling Dalvik BytecodeLinkedIn - Disassembling Dalvik Bytecode
LinkedIn - Disassembling Dalvik BytecodeAlain Leon
 
a quick Introduction to PyPy
a quick Introduction to PyPya quick Introduction to PyPy
a quick Introduction to PyPyKai Aras
 
Overview of .Net Framework 4.5
Overview of .Net Framework 4.5Overview of .Net Framework 4.5
Overview of .Net Framework 4.5Bhushan Mulmule
 

What's hot (20)

Python on Android with Delphi FMX - The Cross Platform GUI Framework
Python on Android with Delphi FMX - The Cross Platform GUI Framework Python on Android with Delphi FMX - The Cross Platform GUI Framework
Python on Android with Delphi FMX - The Cross Platform GUI Framework
 
Living in a multiligual world: Internationalization for Web 2.0 Applications
Living in a multiligual world: Internationalization for Web 2.0 ApplicationsLiving in a multiligual world: Internationalization for Web 2.0 Applications
Living in a multiligual world: Internationalization for Web 2.0 Applications
 
#JavaOne What's in an object?
#JavaOne What's in an object?#JavaOne What's in an object?
#JavaOne What's in an object?
 
The Whole Platform A Language Workbench for Eclipse
The Whole Platform A Language Workbench for EclipseThe Whole Platform A Language Workbench for Eclipse
The Whole Platform A Language Workbench for Eclipse
 
Python for Delphi Developers - Part 2
Python for Delphi Developers - Part 2Python for Delphi Developers - Part 2
Python for Delphi Developers - Part 2
 
Python for Delphi Developers - Part 1 Introduction
Python for Delphi Developers - Part 1 IntroductionPython for Delphi Developers - Part 1 Introduction
Python for Delphi Developers - Part 1 Introduction
 
Introduction to Python GUI development with Delphi for Python - Part 1: Del...
Introduction to Python GUI development with Delphi for Python - Part 1:   Del...Introduction to Python GUI development with Delphi for Python - Part 1:   Del...
Introduction to Python GUI development with Delphi for Python - Part 1: Del...
 
Living in a Multi-lingual World: Internationalization in Web and Desktop Appl...
Living in a Multi-lingual World: Internationalization in Web and Desktop Appl...Living in a Multi-lingual World: Internationalization in Web and Desktop Appl...
Living in a Multi-lingual World: Internationalization in Web and Desktop Appl...
 
Android on Windows 11 - A Developer's Perspective (Windows Subsystem For Andr...
Android on Windows 11 - A Developer's Perspective (Windows Subsystem For Andr...Android on Windows 11 - A Developer's Perspective (Windows Subsystem For Andr...
Android on Windows 11 - A Developer's Perspective (Windows Subsystem For Andr...
 
llvm-py: Writing Compilers In Python
llvm-py: Writing Compilers In Pythonllvm-py: Writing Compilers In Python
llvm-py: Writing Compilers In Python
 
Part II: LLVM Intermediate Representation
Part II: LLVM Intermediate RepresentationPart II: LLVM Intermediate Representation
Part II: LLVM Intermediate Representation
 
Eclipse OMR: a modern toolkit for building language runtimes
Eclipse OMR: a modern toolkit for building language runtimesEclipse OMR: a modern toolkit for building language runtimes
Eclipse OMR: a modern toolkit for building language runtimes
 
109842496 jni
109842496 jni109842496 jni
109842496 jni
 
PyPy
PyPyPyPy
PyPy
 
Programming With WinRT And Windows8
Programming With WinRT And Windows8Programming With WinRT And Windows8
Programming With WinRT And Windows8
 
I Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java BytecodeI Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java Bytecode
 
An Introduction to PyPy
An Introduction to PyPyAn Introduction to PyPy
An Introduction to PyPy
 
LinkedIn - Disassembling Dalvik Bytecode
LinkedIn - Disassembling Dalvik BytecodeLinkedIn - Disassembling Dalvik Bytecode
LinkedIn - Disassembling Dalvik Bytecode
 
a quick Introduction to PyPy
a quick Introduction to PyPya quick Introduction to PyPy
a quick Introduction to PyPy
 
Overview of .Net Framework 4.5
Overview of .Net Framework 4.5Overview of .Net Framework 4.5
Overview of .Net Framework 4.5
 

Similar to Symfony2 components to the rescue of your PHP projects

A Glymse of Symfony 2
A Glymse of Symfony 2A Glymse of Symfony 2
A Glymse of Symfony 2shaduli
 
Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2narkoza
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Fabien Potencier
 
Symfony Components in the wild
Symfony Components in the wildSymfony Components in the wild
Symfony Components in the wildPHPLondon
 
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
 
Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Fabien Potencier
 
Symfony Nano Framework
Symfony Nano FrameworkSymfony Nano Framework
Symfony Nano FrameworkLoïc Faugeron
 
Composing Project Dependencies
Composing Project DependenciesComposing Project Dependencies
Composing Project DependenciesDerek Gallo
 
How Symfony changed my life (#SfPot, Paris, 19th November 2015)
How Symfony changed my life (#SfPot, Paris, 19th November 2015)How Symfony changed my life (#SfPot, Paris, 19th November 2015)
How Symfony changed my life (#SfPot, Paris, 19th November 2015)Matthias Noback
 
#1 Backend Meetup - Symfony 2 - wstęp
#1 Backend Meetup - Symfony 2 - wstęp#1 Backend Meetup - Symfony 2 - wstęp
#1 Backend Meetup - Symfony 2 - wstępMaciej Grajcarek
 
How Symfony Changed My Life
How Symfony Changed My LifeHow Symfony Changed My Life
How Symfony Changed My LifeMatthias Noback
 
LoneStarPHP Symfony2, Its Play Time
LoneStarPHP Symfony2, Its Play TimeLoneStarPHP Symfony2, Its Play Time
LoneStarPHP Symfony2, Its Play Timegeoffreytran
 
Learning Symfony2 by practice
Learning Symfony2 by practiceLearning Symfony2 by practice
Learning Symfony2 by practiceVytautas Beliunas
 
Nice performance using Sf2 cache wrapping Sf1 application - Paris
Nice performance using Sf2 cache wrapping Sf1 application - ParisNice performance using Sf2 cache wrapping Sf1 application - Paris
Nice performance using Sf2 cache wrapping Sf1 application - ParisMarc Weistroff
 
Introduction to symfony2
Introduction to symfony2Introduction to symfony2
Introduction to symfony2Pablo Godel
 
25 Intro to Symfony #burningkeyboards
25 Intro to Symfony #burningkeyboards25 Intro to Symfony #burningkeyboards
25 Intro to Symfony #burningkeyboardsDenis Ristic
 
Structure of Chamilo 1.10: a new awakening
Structure of Chamilo 1.10: a new awakeningStructure of Chamilo 1.10: a new awakening
Structure of Chamilo 1.10: a new awakeningChamilo Association
 
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
 

Similar to Symfony2 components to the rescue of your PHP projects (20)

A Glymse of Symfony 2
A Glymse of Symfony 2A Glymse of Symfony 2
A Glymse of Symfony 2
 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
 
Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2Symfony Live 09 Symfony 2
Symfony Live 09 Symfony 2
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
 
Symfony Components in the wild
Symfony Components in the wildSymfony Components in the wild
Symfony Components in the wild
 
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 Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3
 
Symfony Nano Framework
Symfony Nano FrameworkSymfony Nano Framework
Symfony Nano Framework
 
Composing Project Dependencies
Composing Project DependenciesComposing Project Dependencies
Composing Project Dependencies
 
How Symfony changed my life (#SfPot, Paris, 19th November 2015)
How Symfony changed my life (#SfPot, Paris, 19th November 2015)How Symfony changed my life (#SfPot, Paris, 19th November 2015)
How Symfony changed my life (#SfPot, Paris, 19th November 2015)
 
#1 Backend Meetup - Symfony 2 - wstęp
#1 Backend Meetup - Symfony 2 - wstęp#1 Backend Meetup - Symfony 2 - wstęp
#1 Backend Meetup - Symfony 2 - wstęp
 
How Symfony Changed My Life
How Symfony Changed My LifeHow Symfony Changed My Life
How Symfony Changed My Life
 
LoneStarPHP Symfony2, Its Play Time
LoneStarPHP Symfony2, Its Play TimeLoneStarPHP Symfony2, Its Play Time
LoneStarPHP Symfony2, Its Play Time
 
Learning Symfony2 by practice
Learning Symfony2 by practiceLearning Symfony2 by practice
Learning Symfony2 by practice
 
Sf sf v5
Sf sf v5Sf sf v5
Sf sf v5
 
Nice performance using Sf2 cache wrapping Sf1 application - Paris
Nice performance using Sf2 cache wrapping Sf1 application - ParisNice performance using Sf2 cache wrapping Sf1 application - Paris
Nice performance using Sf2 cache wrapping Sf1 application - Paris
 
Introduction to symfony2
Introduction to symfony2Introduction to symfony2
Introduction to symfony2
 
25 Intro to Symfony #burningkeyboards
25 Intro to Symfony #burningkeyboards25 Intro to Symfony #burningkeyboards
25 Intro to Symfony #burningkeyboards
 
Structure of Chamilo 1.10: a new awakening
Structure of Chamilo 1.10: a new awakeningStructure of Chamilo 1.10: a new awakening
Structure of Chamilo 1.10: a new awakening
 
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
 

More from Xavier Lacot

Keynote d'ouverture - Forum PHP 2012
Keynote d'ouverture - Forum PHP 2012Keynote d'ouverture - Forum PHP 2012
Keynote d'ouverture - Forum PHP 2012Xavier Lacot
 
Développement Cross-Platform avec Titanium Mobile
Développement Cross-Platform avec Titanium MobileDéveloppement Cross-Platform avec Titanium Mobile
Développement Cross-Platform avec Titanium MobileXavier Lacot
 
Keynote de clôture - PHP Tour 2011
Keynote de clôture - PHP Tour 2011Keynote de clôture - PHP Tour 2011
Keynote de clôture - PHP Tour 2011Xavier Lacot
 
Abstracting databases access in Titanium Mobile
Abstracting databases access in Titanium MobileAbstracting databases access in Titanium Mobile
Abstracting databases access in Titanium MobileXavier Lacot
 
RESTful avec symfony 1 et Symfony2
RESTful avec symfony 1 et Symfony2RESTful avec symfony 1 et Symfony2
RESTful avec symfony 1 et Symfony2Xavier Lacot
 
Forum PHP 2010 - Les frameworks, essentiels dans-l-ecosysteme-php-xavier-laco...
Forum PHP 2010 - Les frameworks, essentiels dans-l-ecosysteme-php-xavier-laco...Forum PHP 2010 - Les frameworks, essentiels dans-l-ecosysteme-php-xavier-laco...
Forum PHP 2010 - Les frameworks, essentiels dans-l-ecosysteme-php-xavier-laco...Xavier Lacot
 
Symfony Day 2009 - Symfony vs Integrating products
Symfony Day 2009 - Symfony vs Integrating productsSymfony Day 2009 - Symfony vs Integrating products
Symfony Day 2009 - Symfony vs Integrating productsXavier Lacot
 

More from Xavier Lacot (7)

Keynote d'ouverture - Forum PHP 2012
Keynote d'ouverture - Forum PHP 2012Keynote d'ouverture - Forum PHP 2012
Keynote d'ouverture - Forum PHP 2012
 
Développement Cross-Platform avec Titanium Mobile
Développement Cross-Platform avec Titanium MobileDéveloppement Cross-Platform avec Titanium Mobile
Développement Cross-Platform avec Titanium Mobile
 
Keynote de clôture - PHP Tour 2011
Keynote de clôture - PHP Tour 2011Keynote de clôture - PHP Tour 2011
Keynote de clôture - PHP Tour 2011
 
Abstracting databases access in Titanium Mobile
Abstracting databases access in Titanium MobileAbstracting databases access in Titanium Mobile
Abstracting databases access in Titanium Mobile
 
RESTful avec symfony 1 et Symfony2
RESTful avec symfony 1 et Symfony2RESTful avec symfony 1 et Symfony2
RESTful avec symfony 1 et Symfony2
 
Forum PHP 2010 - Les frameworks, essentiels dans-l-ecosysteme-php-xavier-laco...
Forum PHP 2010 - Les frameworks, essentiels dans-l-ecosysteme-php-xavier-laco...Forum PHP 2010 - Les frameworks, essentiels dans-l-ecosysteme-php-xavier-laco...
Forum PHP 2010 - Les frameworks, essentiels dans-l-ecosysteme-php-xavier-laco...
 
Symfony Day 2009 - Symfony vs Integrating products
Symfony Day 2009 - Symfony vs Integrating productsSymfony Day 2009 - Symfony vs Integrating products
Symfony Day 2009 - Symfony vs Integrating products
 

Recently uploaded

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 

Recently uploaded (20)

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 

Symfony2 components to the rescue of your PHP projects

  • 1. Symfony2 components to the rescue of your PHP projects Xavier Lacot – June 2012
  • 2. Hello My name is Xavier Lacot ■ Web and Mobile at http://jolicode.com ■ Formerly PHP technical leader at Clever Age ■ Open Source convinced and contributor ■ In PHP, mainly Symfony ■ In javascript, etc. ■ Président of AFUP – the French PHP Users Association (afup.org) ■ Forum PHP ■ PHP Tour ■ http://twitter.com/xavierlacot Symfony2 components to the rescue of your PHP projects 2 JoliCode | Xavier Lacot | Symfony Live 2012
  • 3. Summary 1. PHP in 2012, a living ecosystem 2. 2005's PHP is now just pain 3. Migration strategies ■ The slow path ■ Switch progressively 4. Symfony components for your pleasure ■ Your prefered migration toolkit ■ Case Study Symfony2 components to the rescue of your PHP projects 3 JoliCode | Xavier Lacot | Symfony Live 2012
  • 4. Before we start How many of you use a framework on a regular basis? How many of you must deal with no-framework applications? Symfony2 components to the rescue of your PHP projects 4 JoliCode | Xavier Lacot | Symfony Live 2012
  • 5. PHP in 2012, a living ecosystem
  • 6. A few things about PHP ■ A pragmatic language built for the Web ■ PHP5 since 2005 ■ One of the most used languages on the Web PHP – solves problems since 1995 Symfony2 components to the rescue of your PHP projects 6 JoliCode | Xavier Lacot | Symfony Live 2012
  • 7. The language improves ■ PHP 5.3 introduced new concepts : ■ Usage of namespaces namespace JoliCodeConferences; use GeneralTalkSession; class SymfonyLive extends Session { public function runPresentation() { // do something nice... } } ■ Lambda and closures ■ Phar archives ■ “goto” WTF ??? Symfony2 components to the rescue of your PHP projects 7 JoliCode | Xavier Lacot | Symfony Live 2012
  • 8. Namespaces manipulation ■ Pro ■ No more collisions ■ Less ambiguity ■ Ahah, short class names. No more long classnames ■ Cons ■ Don't forget the use statement use OneFullClassname as Something; $object = new Something; Symfony2 components to the rescue of your PHP projects 8 JoliCode | Xavier Lacot | Symfony Live 2012
  • 9. And it still evolves ■ PHP 5.4 ■ Some deprecated features removed ■ Performance improvements ■ Instance Method Calls $post = (new Post)->setTitle('Hello poneys')->save(); ■ Closures inside objects ■ Traits, aka. assisted copy/paste ■ Arrays manipulation function fruits() { return ['apple', 'banana', 'orange']; } echo fruits()[0]; // Outputs: apple Symfony2 components to the rescue of your PHP projects 9 JoliCode | Xavier Lacot | Symfony Live 2012
  • 10. The ecosystem improves ■ Last years = bunch of new things ■ New (versions of) frameworks ■ New tools ■ Dependancies resolution ■ Code analysis ■ Continuous integration ■ Structuration of the projects ■ Standards ■ Discussions ■ More and more conferences Symfony2 components to the rescue of your PHP projects 10 JoliCode | Xavier Lacot | Symfony Live 2012
  • 11. New frameworks Symfony2 components to the rescue of your PHP projects 11 JoliCode | Xavier Lacot | Symfony Live 2012
  • 12. New frameworks Symfony2 components to the rescue of your PHP projects 12 JoliCode | Xavier Lacot | Symfony Live 2012
  • 13. ClassLoader and PSR-0 ■ PSR-0 : ■ A standardization agreement ■ Scope: classes naming and organization class: SymfonyComponentHttpFoundationRequest path: vendor/src/Symfony/Component/HttpFoundation/Request.php class: Twig_Extension_Core path: vendor/twig/lib/Twig/Extension/Core.php ■ Idea : match the path of the file containg a class to this full class name Symfony2 components to the rescue of your PHP projects 13 JoliCode | Xavier Lacot | Symfony Live 2012
  • 14. ClassLoader and PSR-0 Namespaced classes style autoloading path prefix class: SymfonyComponentHttpFoundationRequest path: vendor/src/Symfony/Component/HttpFoundation/Request.php class: Twig_Extension_Core path: vendor/twig/lib/Twig/Extension/Core.php PEAR naming style Symfony2 components to the rescue of your PHP projects 14 JoliCode | Xavier Lacot | Symfony Live 2012
  • 15. Composer ■ A packages management tool ■ Launched in 2012 ■ Composer : a tool for managing dependancies ■ Packagist.org : a repository of packages ■ See the talk of Jordi Boggiano and Nils Adermann Symfony2 components to the rescue of your PHP projects 15 JoliCode | Xavier Lacot | Symfony Live 2012
  • 16. Dependancies resolution using Composer composer.json { "name": "joli/demo-project", "description": "A simple demo project", "require": { "php": ">=5.3.3", "symfony/symfony": "2.1.*", "seld/jsonlint": "1.0.0" } } $ php composer.phar install Installing dependencies from lock file - Updating twig/twig (dev-master) ■ And more: ■ Post install commands ■ Configuration variables ■ etc. Symfony2 components to the rescue of your PHP projects 16 JoliCode | Xavier Lacot | Symfony Live 2012
  • 17. Packagist ■ The packages repository behind packagist ■ A great resource for finding high quality contributions ■ Definitively forget about PEAR or distro packages ■ Fear that packagist might break? Build your own repository with satis - https://github.com/composer/satis Symfony2 components to the rescue of your PHP projects 17 JoliCode | Xavier Lacot | Symfony Live 2012
  • 18. Symfony2 components to the rescue of your PHP projects 18 JoliCode | Xavier Lacot | Symfony Live 2012
  • 19. PHP gets is a professional language ■ PHP is not anymore an amateur language ■ Continuous integration (hi Jenkins, Sismo and Travis) ■ Unit tests (hi PHPUnit, SimpleTest, Atoum) ■ Code quality analysis and metrics ■ Code improvement tools (Hi PHP-CS-Fixer) ■ etc. ■ PHP developers have grew up since 2002 ■ The language is more mature ■ The community too Symfony2 components to the rescue of your PHP projects 19 JoliCode | Xavier Lacot | Symfony Live 2012
  • 20. Symfony2 components to the rescue of your PHP projects 20 JoliCode | Xavier Lacot | Symfony Live 2012
  • 21. Cheers GitHub Symfony2 components to the rescue of your PHP projects 21 JoliCode | Xavier Lacot | Symfony Live 2012
  • 22. GitHub ■ Social coding ■ Gathers many Open Source contributions ■ Watch, fork, comment, request pulls ■ Fun and nice ■ 2,500,000 projects, ~ 150,000 PHP projects ■ A great market for the developer! PHP switched from SVN to Git Symfony2 components to the rescue of your PHP projects 22 JoliCode | Xavier Lacot | Symfony Live 2012
  • 23. Symfony2 components to the rescue of your PHP projects 23 JoliCode | Xavier Lacot | Symfony Live 2012
  • 24. Summary 1. PHP in 2012, a living ecosystem 2. 2005's PHP is now just pain 3. Migration strategies ■ The slow path ■ Switch progressively 4. Symfony components for your pleasure ■ Your prefered migration toolkit ■ Case study Symfony2 components to the rescue of your PHP projects 24 JoliCode | Xavier Lacot | Symfony Live 2012
  • 25. 2005's PHP is now just pain
  • 26. Oh yes we did it... somewhere in 2002... <html> <body> <?php include("includes/menu.inc.php"); $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php"; if ( !file_exists($file) ) { @include("pages/404.php"); } else { $allowed = realpath('./pages'); if ( !@ereg($allowed."*", realpath($file)) ) { @include("pages/404.php"); } else { @include($file); } } ?> </body> </html> Symfony2 components to the rescue of your PHP projects 26 JoliCode | Xavier Lacot | Symfony Live 2012
  • 27. Oh yes we did it... somewhere in 2002... <html> <body> <?php include("includes/menu.inc.php"); ■ HTML and PHP mix $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php"; if ( !file_exists($file) ) { @include("pages/404.php"); } else { $allowed = realpath('./pages'); if ( !@ereg($allowed."*", realpath($file)) ) { @include("pages/404.php"); } else { @include($file); } } ?> </body> </html> Symfony2 components to the rescue of your PHP projects 27 JoliCode | Xavier Lacot | Symfony Live 2012
  • 28. Oh yes we did it... somewhere in 2002... <html> <body> <?php include("includes/menu.inc.php"); ■ HTML and PHP mix $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php"; if ( !file_exists($file) ) { ■ Direct access to } @include("pages/404.php"); superglobals else { $allowed = realpath('./pages'); if ( !@ereg($allowed."*", realpath($file)) ) { @include("pages/404.php"); } else { @include($file); } } ?> </body> </html> Symfony2 components to the rescue of your PHP projects 28 JoliCode | Xavier Lacot | Symfony Live 2012
  • 29. Oh yes we did it... somewhere in 2002... <html> <body> <?php include("includes/menu.inc.php"); ■ HTML and PHP mix $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php"; if ( !file_exists($file) ) { ■ Direct access to } @include("pages/404.php"); superglobals else { ■ Use of the @ operator $allowed = realpath('./pages'); if ( !@ereg($allowed."*", realpath($file)) ) { @include("pages/404.php"); } else { @include($file); } } ?> </body> </html> Symfony2 components to the rescue of your PHP projects 29 JoliCode | Xavier Lacot | Symfony Live 2012
  • 30. Oh yes we did it... somewhere in 2002... <html> <body> <?php include("includes/menu.inc.php"); ■ HTML and PHP mix $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php"; if ( !file_exists($file) ) ■ Direct access to { @include("pages/404.php"); superglobals } else { ■ Use of the @ operator $allowed = realpath('./pages'); if ( !@ereg($allowed."*", realpath($file)) ) ■ Urls tied to code { structure @include("pages/404.php"); } else { @include($file); } } ?> </body> </html> Symfony2 components to the rescue of your PHP projects 30 JoliCode | Xavier Lacot | Symfony Live 2012
  • 31. Oh yes we did it... somewhere in 2002... <html> <body> <?php include("includes/menu.inc.php"); ■ HTML and PHP mix $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php"; if ( !file_exists($file) ) ■ Direct access to { @include("pages/404.php"); superglobals } else { ■ Use of the @ operator $allowed = realpath('./pages'); ■ Urls tied to code if ( !@ereg($allowed."*", realpath($file)) ) { structure @include("pages/404.php"); } else ■ Duplicate code { @include($file); } } ?> </body> </html> Symfony2 components to the rescue of your PHP projects 31 JoliCode | Xavier Lacot | Symfony Live 2012
  • 32. Symfony2 components to the rescue of your PHP projects 32 JoliCode | Xavier Lacot | Symfony Live 2012
  • 33. Not bad at all ■ That was 10 years ago! ■ No PHP5 at that time ■ That was still flexible ■ Just missed some concepts Symfony2 components to the rescue of your PHP projects 33 JoliCode | Xavier Lacot | Symfony Live 2012
  • 34. The shit of today was great yesterday So how did we improve things? Symfony2 components to the rescue of your PHP projects 34 JoliCode | Xavier Lacot | Symfony Live 2012
  • 35. 2004 → 2007 ■ First professional PHP frameworks ■ Zend Framework ■ Code Igniter ■ Seagull PHP ■ Cake PHP ■ symfony 1 ■ Jelix ■ Pluf ■ Yii ■ etc. Symfony2 components to the rescue of your PHP projects 35 JoliCode | Xavier Lacot | Symfony Live 2012
  • 36. symfony 1 ■ End 2005 : first public version (release 0.4) ■ Developers say “hurra” ORM Functionnal and Unit tests Ajax Internationalisation Plugins Community Console Helpers Conventions Routing Debug toolbar Cache Documentation MVC Symfony2 components to the rescue of your PHP projects 36 JoliCode | Xavier Lacot | Symfony Live 2012
  • 37. Still not sufficient ■ Several limits: ■ Very monolithic ■ Not very flexible ■ Almost no components - use it all or don't use it ■ Some things were a pain to achieve ■ Extensive use of Singleton ■ Hard (impossible) to write complete test suites ■ Developers only ■ Performances... ! ■ Lots of bad contribs ■ Low average community level Symfony2 components to the rescue of your PHP projects 37 JoliCode | Xavier Lacot | Symfony Live 2012
  • 38. Symfony2 components to the rescue of your PHP projects 38 JoliCode | Xavier Lacot | Symfony Live 2012
  • 40. Summary 1. PHP in 2012, a living ecosystem 2. 2005's PHP is now just pain 3. Migration strategies ■ The slow path ■ Switch progressively 4. Symfony components for your pleasure ■ Your prefered migration toolkit ■ Case study Symfony2 components to the rescue of your PHP projects 40 JoliCode | Xavier Lacot | Symfony Live 2012
  • 41. Pre-conditions ■ You work since more than 5 years on your project ■ A bunch of functionnalities ■ The app is in production ■ Lots of users and data ■ A competent team ■ But ■ New developments are slow ■ Infrastructure problems ■ Hard to improve things ■ You want to trash it all, and code like in 2012 Symfony2 components to the rescue of your PHP projects 41 JoliCode | Xavier Lacot | Symfony Live 2012
  • 42. Pre-conditions Your reality Symfony2 components to the rescue of your PHP projects 42 JoliCode | Xavier Lacot | Symfony Live 2012
  • 43. Pre-conditions Your expectations Symfony2 components to the rescue of your PHP projects 43 JoliCode | Xavier Lacot | Symfony Live 2012
  • 44. Strategy #1 – big bang ■ Most natural approach : rewrite everything ■ Pro: ■ A new solid and modern framework ■ Leave away from the old crappy codebase ■ Feel more happy ■ Cons: ■ Stop the company's business ■ Spend 1y+ re-developing everything ■ Have client cry ■ Complex migration scripts ■ Very risky Symfony2 components to the rescue of your PHP projects 44 JoliCode | Xavier Lacot | Symfony Live 2012
  • 45. Strategy #1 – big bang ■ Don't do that ■ Too risky ■ Lot of pressure ■ Might lead to a disaster ■ Your boss won't be happy ■ Prefer a gradual approach Symfony2 components to the rescue of your PHP projects 45 JoliCode | Xavier Lacot | Symfony Live 2012
  • 46. Strategy #2 – Be progressive ■ Being progressive : ■ Re-write step by step ■ Control the way you build things ■ Use Framework parts, not the complete framework ■ Choose which parts to use ■ Gradually raise the level of your team ■ Less risky ■ And your boss will love you Symfony2 components to the rescue of your PHP projects 46 JoliCode | Xavier Lacot | Symfony Live 2012
  • 47. Step #1 Switch to PHP 5.3 or PHP 5.4 NOW. * Historical Historical codebase codebase PHP x.x PHP 5.3 Symfony2 components to the rescue of your PHP projects 47 JoliCode | Xavier Lacot | Symfony Live 2012 thanks w3techs.com
  • 48. Step #1 ■ Debian users : ■ Update your distribution version (eventually) ■ Update your packages (5 seconds) ■ Mac Users : ■ Please trash wamp and go grab http://php-osx.liip.ch/ (kudos Liip) ■ Windows users Doh! Symfony2 components to the rescue of your PHP projects 48 JoliCode | Xavier Lacot | Symfony Live 2012
  • 49. Step #2 ■ Create a solid foundation for your future new developments ■ Put new things in your project ■ Symfony components are up! Start with: ■ ClassLoader ■ DependencyInjection ■ HTTPFoundation ClassLoader Historical Historical codebase DIC codebase HTTPFoundation Symfony2 components to the rescue of your PHP projects 49 JoliCode | Xavier Lacot | Symfony Live 2012
  • 50. Step #2 – install the components ■ Use composer { "autoload": { "psr-0": {} }, "name": "xavierlacot/blog", "description": "My old blog on steroids", "require": { "php": ">=5.3.3", "symfony/class-loader": "2.1.*", "symfony/dependency-injection": "2.1.*", "symfony/http-foundation": "2.1.*" } } $ php composer.phar install Installing dependencies from lock file - Updating symfony/class-loader (dev-master) Symfony2 components to the rescue of your PHP projects 50 JoliCode | Xavier Lacot | Symfony Live 2012
  • 51. Step #2 – install the components ■ What did we install while doing this? ■ ClassLoader allows to load classes automagically, when required, if they follow a naming convention defined by PSR-0; ■ DependancyInjection provides a set of tools for building object and classes in a standardized way, and reduce the BC breaks; ■ HTTPFoundation is the basic toolkit when working with HTTP requests (all web pages, for example). ■ We'll see all three later un the presentation Symfony2 components to the rescue of your PHP projects 51 JoliCode | Xavier Lacot | Symfony Live 2012
  • 52. Step #2 – install the components ■ Composer is great ■ It comes with an autoloader ■ Using the classes is simple : index.php <?php require 'vendor/autoload.php'; ■ And we're ready to start using the component classes! Symfony2 components to the rescue of your PHP projects 52 JoliCode | Xavier Lacot | Symfony Live 2012
  • 53. Step #3 – start using the components ■ HTTPFoundation is the easiest component to start with – the one you can immediately use without breaking things index.php use SymfonyComponentHttpFoundationRequest; $request = Request::createFromGlobals(); CreateFromGlobals() analyses the superglobals and populates the Request object Symfony2 components to the rescue of your PHP projects 53 JoliCode | Xavier Lacot | Symfony Live 2012
  • 54. Step #3 – use HTTPFoundation Time to change your historical code... $pagename = (isset($_GET['page'])) ? $_GET['page'] : "404"; $file = sprintf('pages/%s.php', $pagename); becomes $pagename = $request->query->get('page', '404'); $file = sprintf('pages/%s.php', $pagename); Symfony2 components to the rescue of your PHP projects 54 JoliCode | Xavier Lacot | Symfony Live 2012
  • 55. Step #4 ■ There's no step #4 ■ The rest of the process is very similar ■ Integrate the component ■ Use it ■ Refactor your code ■ Simplify ■ Iterate – don't break everything at once. Use components gradually Symfony2 components to the rescue of your PHP projects 55 JoliCode | Xavier Lacot | Symfony Live 2012
  • 56. Symfony components for your pleasure
  • 57. Summary 1. PHP in 2012, a living ecosystem 2. 2005's PHP is now just pain 3. Migration strategies ■ The slow path ■ Switch progressively 4. Symfony components for your pleasure ■ Your prefered migration toolkit ■ Case study Symfony2 components to the rescue of your PHP projects 57 JoliCode | Xavier Lacot | Symfony Live 2012
  • 58. So what are the Symfony Components ? ■ Symfony components are : ■ A set of independent libraries ■ You can use them separately ■ High quality code components, tested and documented ■ Symfony components are not : ■ A bootstrap ■ They do not provide end user fonctionnalities ■ They are the bricks of your new platform, but you will have to glue them together Symfony2 components to the rescue of your PHP projects 58 JoliCode | Xavier Lacot | Symfony Live 2012
  • 59. Symfony components ■ The complete list is available at http://symfony.com/components ■ Symfony2 is built with the Symfony components ■ You will often use the symfony standard distribution, which contains all the components plus some bundles ■ Components do not depend on any third party library ■ All kind of stuff: ■ HTTP management ■ Internationalization process ■ Cache ■ Templating ■ Files finder ■ Forms management ■ Routing management ■ etc. Symfony2 components to the rescue of your PHP projects 59 JoliCode | Xavier Lacot | Symfony Live 2012
  • 60. Symfony components ■ Here is the list of what you can get : ■ BrowserKit ■ ClassLoader ■ HttpKernel ■ Config ■ Locale ■ Console ■ Process ■ CssSelector ■ Routing ■ DependencyInjection ■ Security ■ DomCrawler ■ Serializer ■ EventDispatcher ■ Templating ■ Finder ■ Translation ■ Form ■ Validator ■ HttpFoundation ■ Yaml Symfony2 components to the rescue of your PHP projects 60 JoliCode | Xavier Lacot | Symfony Live 2012
  • 61. Your prefered migration toolkit ■ I won't detail all the components ■ Here are (AMHA) the most useful (and straightforward) when migrating an old application: ■ ClassLoader ■ Console ■ DependencyInjection ■ Finder ■ HttpFoundation ■ Routing ■ Templating ■ Validator ■ If you want to use more, consider using Symfony2 at some point Symfony2 components to the rescue of your PHP projects 61 JoliCode | Xavier Lacot | Symfony Live 2012
  • 62. ClassLoader ■ loads classes automatically if they follow PSR-0; ■ Migration process: 1. have your classes organization follow PSR-0 (renaming stuff) ldap.php src/Ldap/Client.php <?php <?php namespace Prefix/Ldap/Client; class prefixedLdapConnector { class Client public function __construct() { { public function __construct() // stuff { } // stuff } } } 2. Configure the ClassLoader Symfony2 components to the rescue of your PHP projects 62 JoliCode | Xavier Lacot | Symfony Live 2012
  • 63. ClassLoader ■ loads classes automatically if they follow PSR-0; ■ Migration process: 1. have your classes organization follow PSR-0 (renaming stuff) ldap.php src/Prefix/Ldap/Client.php <?php <?php namespace Prefix/Ldap; class prefixedLdapConnector { class Client public function __construct() { { public function __construct() // stuff { } // stuff } } } 2. Configure the ClassLoader Symfony2 components to the rescue of your PHP projects 63 JoliCode | Xavier Lacot | Symfony Live 2012
  • 64. ClassLoader ■ Composer's autoloader is taking care of vendors installed by composer ■ We must declare “our” classes: index.php use SymfonyComponentClassLoaderUniversalClassLoader; $loader = new UniversalClassLoader(); $loader->registerNamespace('Prefix', __DIR__.'/src/'); $loader->register(); ■ Possible to declare several namespaces at once: registerNamespaces(array(...)) Symfony2 components to the rescue of your PHP projects 64 JoliCode | Xavier Lacot | Symfony Live 2012
  • 65. Console ■ Your best friend for writing: ■ Command line tasks ■ Cron jobs ■ Repetitive asynchron tasks ■ Pros: ■ Input / Output management ■ Colorization ■ Well written ■ Extensible Symfony2 components to the rescue of your PHP projects 65 JoliCode | Xavier Lacot | Symfony Live 2012
  • 66. Console ■ Add the Console component to composer.json "require": { "php": ">=5.3.3", "symfony/class-loader": "2.1.*", "symfony/console": "2.1.*", "symfony/dependency-injection": "2.1.*", "symfony/http-foundation": "2.1.*" } ■ Update the dependencies : $ php composer.phar update Updating dependencies - Installing symfony/console (dev-master) Writing lock file Generating autoload files Symfony2 components to the rescue of your PHP projects 66 JoliCode | Xavier Lacot | Symfony Live 2012
  • 67. Console ■ Write a new command: src/Prefix/Command/TwitterCommand.php <?php namespace PrefixCommand; class TwitterCommand extends Command { protected function configure() { Hint: I did $this remove some ->setName('joli:twitter') “use” ->setDescription('Gets updates from twitter') statements ; } protected function execute(InputInterface $input, OutputInterface $output) { $puller = $this->getContainer()->get('joli.twitter.puller'); $output->writeln("Contacting Twitter..."); $data = $puller->pull(); // do stuff with $data $output->writeln(sprintf('Tweets fetched. %s new tweets', count($tweets))); } } Symfony2 components to the rescue of your PHP projects 67 JoliCode | Xavier Lacot | Symfony Live 2012
  • 68. Console ■ Then create the executable file itself: console.php #!/usr/bin/env php <?php require 'autoload.php'; use PrefixCommandTwitterCommand; use SymfonyComponentConsoleApplication; $application = new Application(); $application->add(new TwitterCommand); $application->run(); ■ Fix this file's permissions: $ chmod 755 console.php Symfony2 components to the rescue of your PHP projects 68 JoliCode | Xavier Lacot | Symfony Live 2012
  • 69. Console ■ And finally run the command: $ ./console joli:twitter Contacting Twitter... Tweets successfuly fetched. 0 new tweets $ ./console Console Tool Usage: [options] command [arguments] Options: --help -h Display this help message. --quiet -q Do not output any message. --verbose -v Increase verbosity of messages. --version -V Display this application version. --ansi Force ANSI output. --no-ansi Disable ANSI output. --no-interaction -n Do not ask any interactive question. Available commands: help Displays help for a command list Lists commands joli joli:twitter Gets updates from twitter Symfony2 components to the rescue of your PHP projects 69 JoliCode | Xavier Lacot | Symfony Live 2012
  • 70. Dependency Injection ■ “Dependency Injection” is a rather cryptic name ■ No drugs here, promise ■ Here is an “old school” function prototype: function makeMenu($sqlConnection, $menu, $nbItems = null, $level = 0, $startingWith = null) * ■ It is bad, because: ■ The prototype will change when you will have new requirements ■ The order of the parameters is a hard constraint ■ Maybe one day you'll store menu items in a NoSQL database, and not in a relational one anymore Copyright Symfony2 components to the rescue of your PHP projects me a long long long time ago 70 JoliCode | Xavier Lacot | Symfony Live 2012
  • 71. Symfony2 components to the rescue of your PHP projects 71 JoliCode | Xavier Lacot | Symfony Live 2012
  • 72. Your existing app ■ Your existing app does a lot of things ■ Sending emails ■ Parsing data ■ Writing logs ■ Storing data in databases Symfony2 components to the rescue of your PHP projects 72 JoliCode | Xavier Lacot | Symfony Live 2012
  • 73. Dependency Injection ■ The Dependency Injection component provides a dependency injection container ■ Imagine a large array of resources widely used in the whole application ■ This “DIC” has some capacities: ■ Resources are instantiated only when required; ■ It is extensible; ■ Each item of this DIC is called a “service” ■ The SQL connection is a service ■ Passing the DIC to a class automatically gives access to a large collection of services...! Symfony2 components to the rescue of your PHP projects 73 JoliCode | Xavier Lacot | Symfony Live 2012
  • 74. Dependency Injection Initialization Execution Call the service Create services DIC DIC $container->get('mailer') bootstrap Instantiate a non-existing service Symfony2 components to the rescue of your PHP projects 74 JoliCode | Xavier Lacot | Symfony Live 2012
  • 75. Implement your own services ■ In the migration plan: ■ convert the “service” functionnalities into real Symfony2 services, ■ Create binding to the existing calls ■ use them like before ■ In the future, put all your services in the container. ■ And use them from there Symfony2 components to the rescue of your PHP projects 75 JoliCode | Xavier Lacot | Symfony Live 2012
  • 76. DIC migration ■ Imagine we have a “Mailer” class: <?php namespace PrefixMailer; class Mailer { $prefix = ''; public function send($to, $subject, $body) { // etc. } } ■ A mail is sent in our code with: function saveUser($name, $email) { // stuff here $mailer = new Mailer; $mailer->send($user->getEmail(), 'Welcome '.$user->getName(), 'A test'); } Symfony2 components to the rescue of your PHP projects 76 JoliCode | Xavier Lacot | Symfony Live 2012
  • 77. DIC migration ■ Create the service container: use SymfonyComponentDependencyInjectionContainerBuilder; $container = new ContainerBuilder(); $container->register('mailer', 'Mailer'); ■ Pass it to our users management class ■ Use it: function saveUser($name, $email) { // stuff here $mailer = $this->container->get('mailer'); $mailer->send($user->getEmail(), 'Welcome '.$user->getName(), 'A test'); } Symfony2 components to the rescue of your PHP projects 77 JoliCode | Xavier Lacot | Symfony Live 2012
  • 78. DIC migration ■ Benefits: ■ The Mailer object is now only created in one place ■ Its configuration is centralized ■ It is easy to override in the user management class Symfony2 components to the rescue of your PHP projects 78 JoliCode | Xavier Lacot | Symfony Live 2012
  • 79. HttpFoundation ■ We have already used a little the HTTP Foundation component ■ One core concept of Symfony2 is the coverage of the framework ■ It handles Requests ■ And returns Responses Request User HTTP Application Response Symfony2 components to the rescue of your PHP projects 79 JoliCode | Xavier Lacot | Symfony Live 2012
  • 80. HttpFoundation ■ HttpFoundation provides concepts for Request and Responses ■ Every input from the user, or output to the user should pass through this component ■ Request: use SymfonyComponentHttpFoundationRequest; $request = Request::createFromGlobals(); ■ $request→request represents $_POST ■ $request→query represents $_GET ■ $request→cookies represents $_COOKIE ■ etc. Symfony2 components to the rescue of your PHP projects 80 JoliCode | Xavier Lacot | Symfony Live 2012
  • 81. HttpFoundation ■ Response: ■ Represents the stuff returned to the user through HTTP use SymfonyComponentHttpFoundationResponse; $response = new Response(); ■ It implements HTTP 1.1, the response is customizable: $response->setContent('This will be the response content'); $response->headers->set('Content-Type', 'text/html'); $response->setStatusCode(200); // send the Response $response->prepare($request); $response->send(); Symfony2 components to the rescue of your PHP projects 81 JoliCode | Xavier Lacot | Symfony Live 2012
  • 82. Migration plan for using HttpFoundation ■ HTTPFoundation will help: ■ Making your application more secure ■ Enforce a normalization of the way the output is sent ot the user ■ Migration plan: ■ Start with systematically using the Request ibject in place of the superglobals ■ Use Response objects whenever possible ■ ob_* may help you ■ Use a templating system to move view content in separate files Symfony2 components to the rescue of your PHP projects 82 JoliCode | Xavier Lacot | Symfony Live 2012
  • 83. Routing Component – what we did before... ■ Didn't you find nasty the way we manage urls in our old app? $file = (isset($_GET['pages'])) ? "pages/".$_GET['page'].".php" : "pages/404.php"; if ( !file_exists($file) ) { @include("pages/404.php"); } else { $allowed = realpath('./pages'); if ( !@ereg($allowed."*", realpath($file)) ) { @include("pages/404.php"); } else { @include($file); } } Symfony2 components to the rescue of your PHP projects 83 JoliCode | Xavier Lacot | Symfony Live 2012
  • 84. Routing Component – what we did before... ■ Yes, it is far from perfect: ■ Urls enforce code organization ■ This system may cause security problems ■ What if the “$allowed” check doesn't work? ■ It is not extensible ■ The url ↔ action matching is hardcoded, which means no possible alternative ■ Bad for SEO ■ http://example.org/index.php?page=news&id=3657 ■ The Symfony2 Routing component helps handling urls in an abstract way Symfony2 components to the rescue of your PHP projects 84 JoliCode | Xavier Lacot | Symfony Live 2012
  • 85. Routing Component ■ Routing is a mechanism which allows to manage the address map of an application ■ Very useful: ■ Better SEO ■ Better security ■ Help reorganize the application internally ■ Do not expose the technology you use Symfony2 components to the rescue of your PHP projects 85 JoliCode | Xavier Lacot | Symfony Live 2012
  • 86. Routing ■ There are two types of routing ■ “Descending” routing: maps an URI to an action the application must complete: ■ /blog must display the list of posts ■ /blog/2010/05/12/un-message.html must display the right post ■ /contact must display the contact form /blog User Descending routing ■ “ascending” routing helps generate nice, SEO compliant URLs Symfony2 components to the rescue of your PHP projects 86 JoliCode | Xavier Lacot | Symfony Live 2012
  • 87. Routing component – migration plan ■ The migration plan for using this component will strongly depend on the way you developed your application. ■ Usually: ■ Add the component to composer.json, update ■ In the front controller, use the routing to match certain urls and handle the request in a clean way ■ This way, it won't affect other URLs ■ Once installed, always use the Router when exposing new URLs Symfony2 components to the rescue of your PHP projects 87 JoliCode | Xavier Lacot | Symfony Live 2012
  • 88. In our example... ■ First, declare the routes Hint: I did remove some // declare the routes “use” $routes = new RouteCollection(); statements $routes->add( 'blog_show', new Route( '/blog/{year}/{month}/{slug}', array('pagename' => 'display_blog') ) ); ■ Then, match the requests to find the page to load $context = new RequestContext(); $context->fromRequest($request); $matcher = new UrlMatcher($routes, $context); try $route now { contains the $route = $matcher->match($request->getRequestUri()); matched route // do things parameters } catch (ResourceNotFoundException $e) Symfony2 // handle the rescue of your } projects { components to exception PHP 88 JoliCode | Xavier Lacot | Symfony Live 2012
  • 89. Generating URLs with the Routing Component ■ $router::generate() allows to generate a URL with parameters: $generator = new UrlGenerator($routes, $context); $url = $generator->generate('blog_show', array( 'slug' => 'hello-les-poneys', 'year' => '2011', 'month' => '11' )); $response->setContent('Please go <a href="'.$url.'">here</a>'); $response->send(); ■ Of course, add the Routing as a service to the container! Symfony2 components to the rescue of your PHP projects 89 JoliCode | Xavier Lacot | Symfony Live 2012
  • 90. Questions ? Contact Xavier Lacot xlacot@jolicode.com 06 51 48 59 73 http://jolicode.com Twitter : @JoliCode Symfony2 components to the rescue of your PHP projects 90 JoliCode | Xavier Lacot | Symfony Live 2012
  • 91. Credits ■ Photos – thanks to the photographers: ■ http://www.flickr.com/photos/artbandito/67829362/ ■ http://capsizedatsea.tumblr.com/post/9559345143 ■ http://memegenerator.net Symfony2 components to the rescue of your PHP projects 91 JoliCode | Xavier Lacot | Symfony Live 2012