SlideShare a Scribd company logo
PHP traits,
   treat or threat?
Nick Belhomme
January 28th, PHPBenelux Conference 2012, Belgium
Software Architect / Project Lead

Author of the
Zend Framework 2.0 Cookbook

International Conference Speaker

Contributor to various Open Source Projects

Freelance PHP Consultant
Market positions




                   http://w3techs.com/
Market positions




●   Python 0.3%
Market positions




●   Ruby 0.6%
●   Python 0.3%
Market positions




●   Perl 1.0%
●   Ruby 0.6%
●   Python 0.3%
Market positions




●   ColdFusion 1.2%
●   Perl 1.0%
●   Ruby 0.6%
●   Python 0.3%
Market positions




●   Java 1.2%
●   ColdFusion 1.2%
●   Perl 1.0%
●   Ruby 0.6%
●   Python 0.3%
Market positions




●   ASP.NET 21.6%
●   Java 1.2%
●   ColdFusion 1.2%
●   Perl 1.0%
●   Ruby 0.6%
●   Python 0.3%
Market positions



●   PHP 77.4%
●   ASP.NET 21.6%
●   Java 1.2%
●   ColdFusion 1.2%
●   Perl 1.0%
●   Ruby 0.6%
●   Python 0.3%
PHP Market Position, 11 Jan 2012
Used by high traffic sites




                                              Java


                                    ColdFusion

                                   Perl
                                                     ASP.NET
                                                                           PHP
Used by low traffic sites




                             Used by fewer sites               Used by many sites
PHP Version Adoption

    ●   PHP 5 93.9%
    ●   PHP 4 6.1%
    ●   PHP 3 < 0.1%
    ●   PHP 6 < 0.1%
PHP 5 usage
     ●   Version 5.2 73.8%
     ●   Version 5.3 20.2%
     ●   Version 5.1 5.8%
     ●   Version 5.0 0.2%
     ●   Version 5.4 < 0.1%
Slow 5.3 Adoption?
●   Shared hosting
●   Companies refrain from updating stable
    systems / distributions
●   You
Adopt now
●   More stability
●   Security
●   Better engine (ie garbage collection)
●   New language features
●   Cleaner code because of more elegant ways of
    solving problems
PHP 5.4

●   Array short syntax (javascript notation)
●   Array dereferencing
●   Class access on instantiation
●   Indirect method call by array variable
●   Engine processes OO code faster
●   <?=
●   JSONSerializable interface
●   ...
Traits
ZF Use Case
ZF Code base used is for illustration purposes only and do
     –not-- express future possible implementations.

ZF2.0 is not yet released so giving ZF3.0 implementations
           illustrates only my own assumptions.


      PHP5.4 stable is not yet released so no real world projects are
      and should be running this version.

      Because of this no real best practices have been defined.
namespace ZendView;
class TemplatePathStack implements TemplateResolver {
    public function setOptions($options = array()) {
        if (!is_array($options) && !$options instanceof Traversable) {
            throw new ExceptionInvalidArgumentException(
                __METHOD__ . ' expects an array or Traversable'
            );
        }

        foreach ($options as $key => $value) { $this->setOption($key, $value); }
        return $this;
    }

    public function setOption($key, $value) {
        switch (strtolower($key)) {
            case 'lfi_protection': $this->setLfiProtection($value);
                break;
            case 'script_paths': $this->addPaths($value);
                break;
            default: break;
        }
    }
}
namespace ZendMvcRouter;
class RouteBroker implements Broker
{
    public function setOptions($options) {
       if (!is_array($options)
           && !$options instanceof Traversable) {
            throw new ExceptionInvalidArgumentException(sprintf(
                'Expected an array or Traversable; received "%s"',
                (is_object($options) ? get_class($options) :
                     gettype($options))
            ));
        }

        foreach ($options as $key => $value) {
            switch (strtolower($key)) {
                case 'class_loader': // handle this case
                Default: break;// ignore unknown options
            }
        }
        return $this;
    }
}
Problem: Code Duplication

if (!is_array($options) && !$options instanceof Traversable) {
    throw new ExceptionInvalidArgumentException(sprintf(
        'Expected an array or Traversable; received "%s"',
        (is_object($options) ? get_class($options) : gettype($options))
    ));
}

foreach ($options as $key => $value) {
  //handle each case
}

return $this;
Solution in PHP5.4?
             Multiple Inheritance


●   Would provide the setOptions in all child
    classes needed
●   Introduces the diamond problem
NOT an Option!
     A better solution called Traits


●   Would provide the setOptions in all classes that
    use the trait
●   Eliminates the diamond problem
trait Options
{
      public function setOptions($options)
      {
           if (!is_array($options) && !$options instanceof Traversable)
      {
               throw new ExceptionInvalidArgumentException(sprintf(
                   'Expected an array or Traversable; received "%s"',
                   (is_object($options) ? get_class($options) : gettype($options))
               ));
           }

         foreach ($options as $key => $value) {
           $this->setOption($key, $value);
         }

         return $this;
    }
}
namespace ZendView;
class TemplatePathStack implements TemplateResolver
{
   use Options;

  public function setOption($key, $value) {
    switch (strtolower($key)) {
      case 'lfi_protection':
         $this->setLfiProtection($value);
         break;
      case 'script_paths':
         $this->addPaths($value);
         break;
      default:
         break;
    }
  }
}
$templateStack = new TemplatePathStack();
$templateStack->setOptions(['lfi_protection' => true]);
namespace ZendMvcRouter;
class RouteBroker implements Broker
{
    use Options;


    public function setOption($key, $value) {
        switch (strtolower($key)) {
            case 'class_loader':
              // handle this case
            default:
              // ignore unknown options
              break;
        }
    }
}


$routeBroker = (new RouteBroker)->setOptions(['class_loader'=>'SomeLoader']);
You have just seen traits
Lets dive deeper

get your chest wet
namespace ZendLoader {
use RuntimeException;
   trait SplRegister {
          public function register()
          { spl_autoload_register(array($this, 'autoload')); }

        public function unregister() {
            spl_autoload_unregister(array($this, 'autoload'));
        }
   }

   class StandardAutoloader {
        use SplRegister;

        public function unregister() {
            throw new RuntimeException(
                'you should not unregister the standard autoloader once registered'
            );
        }
   }
}
namespace {
    $loader = new ZendLoaderStandardAutoloader();
    $loader->register();
    $loader->unregister(); // will throw the exception
}
Precedence Order


 The precedence order is that
members from the current class
   override Trait methods.
namespace ZendLoader {
use RuntimeException;
     class StandardAutoloader {
        public function unregister() {
          throw new RuntimeException(
             'you should not unregister the standard autoloader once registered'
          );
        }
    }
}
namespace NbeZfLoader {
use ZendLoader as ZendLoader;
     class StandardAutoloader extends ZendLoaderStandardAutoloader
     {
        use ZendLoaderSplRegister;
     }
}
namespace {
  $loader = new NbeZfLoaderStandardAutoloader();
  $loader->register(); //will register (trait)
  $loader->unregister(); // will unregister (trait)
}
Precedence Order


An inherited member from a
base class is overridden by a
 member inserted by a Trait
Distil Methods!
namespace ZendLoader {
use RuntimeException;
  class StandardAutoloader {
     public function unregister() {
       throw new RuntimeException(
          'you should not unregister the standard autoloader once registered'
       );
     }
  }
}
namespace NbeZfLoader {
use ZendLoader as ZendLoader;
  class StandardAutoloader extends ZendLoaderStandardAutoloader {
     use ZendLoaderSplRegister {
       ZendLoaderStandardAutoloader::unregister insteadof ZendLoaderSplRegister;
     }
  }
}
namespace {
  $loader = new NbeZfLoaderStandardAutoloader();
  $loader->register(); //will register (trait)
  $loader->unregister(); // will throw RuntimeException (base class)
}
insteadof



Can be used to say which method
to use instead of the trait method.
Multiple Traits
namespace ZendFilter {
  trait Locale {
          protected $locale;

            public function getLocale() { return $this->locale; }

            public function setLocale($locale = null) {
                $this->locale = ZendLocale::findLocale($locale);
                return $this;
            }
    }

    trait WhiteSpace {
            protected $allowWhiteSpace;

            public function getAllowWhiteSpace() { return $this->allowWhiteSpace; }

            public function setAllowWhiteSpace($allowWhiteSpace) {
                $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
                return $this;
            }
    }

        class Alpha extends AbstractFilter { use Locale, WhiteSpace; }
}
Multiple Conflicting Traits

     The Diamond Problem

(Not yours or a girls best friend!)
namespace ZendFilter {
    trait Locale {
          protected $locale;
          public function getLocale() { return $this->locale; }
          public function setLocale($locale = null) {
               $this->locale = ZendLocale::findLocale($locale);
               return $this;
          }
    }

    trait SecondLocale {
          protected $locale;
          public function setLocale($locale = null) {
              if (is_string($locale)) {
                  $locale = array($locale);
              } elseif ($locale instanceof Locale) {
                  $locale = array($locale->toString());
              } elseif (!is_array($locale)) {
                  throw new ExceptionInvalidArgumentException(
                       'Locale has to be string, array or an instance of Zend_Locale'
                  );
              }
              foreach ($locale as $single) {
                  if (!Locale::isLocale($single)) {
                       throw new ExceptionInvalidArgumentException("Unknown locale '$single'");
                  }
              }
              $this->_locale = $locale;
              return $this;
          }
    }
    class Alpha { use Locale, SecondLocale; }
}
namespace {
    (new ZendFilterAlpha)->setLocale('nl_be');
}
Fatal error: Trait method getLocale
has not been applied, because there
    are collisions with other trait
               methods
Insteadof

to the rescue
namespace ZendFilter {
  trait Locale {
          protected $locale;

        public function getLocale()

        public function setLocale($locale = null)
  }

  trait SecondLocale {
          protected $locale;

        public function setLocale($locale = null)
  }

  class Alpha {
        use Locale, SecondLocale {
          SecondLocale::setLocale insteadof Locale;
        }
  }
}
namespace {
    $alpha = new ZendFilterAlpha();
    $alpha->setLocale('nl_be');
}
WIN!
BUT
Strict Standards: ZendFilterLocale
   and ZendFilterSecondLocale
define the same property ($locale)
         in the composition of
 ZendFilterAlpha. This might be
       incompatible, to improve
   maintainability consider using
accessor methods in traits instead.
namespace ZendFilter {
  trait Locale {
           protected $locale = 'nl_BE';
           public function getLocale()
           public function setLocale($locale = null)
  }

  trait SecondLocale {
          protected $locale = 'en_US';
          public function setLocale($locale = null)
  }

  class Alpha {
        use Locale, SecondLocale {
          SecondLocale::setLocale insteadof Locale;
        }
  }
}
namespace {
    $alpha = new ZendFilterAlpha();
    $alpha->setLocale('nl_BE');
}
Fatal error: ZendFilterLocale and
ZendFilterSecondLocale define the
   same property ($locale) in the
 composition of ZendFilterAlpha.
However, the definition differs and is
     considered incompatible.
namespace ZendFilter {
  trait Locale {
          static public $locale = 'en_US';
          public function getLocale() { return self::$locale; }
          public function setLocale($locale = null)
          { self::$locale = $locale; }
  }

  class Alpha {
        use Locale;
        public function get() { return self::$locale; }
  }
}
namespace {
    $alpha = new ZendFilterAlpha();
    echo $alpha->getLocale(); // en_US
    echo $alpha->get(); // en_US
    $alpha->setLocale('nl_be');
    echo $alpha->getLocale(); // nl_be
    echo $alpha->get(); // nl_be
}
namespace ZendFilter {
  trait Locale {
          static public $locale = 'en_US';
          public function getLocale() { return self::$locale; }
          public function setLocale($locale = null)
          { self::$locale = $locale; }
  }

  class Alpha {
        use Locale;
        public function get() { return self::$locale; }
  }
  class Beta { use Locale; }
}
namespace {
    $alpha = new ZendFilterAlpha();
    echo $alpha->getLocale(); // en_US
    $alpha->setLocale('nl_be');
    echo $alpha->getLocale(); // nl_be
    $beta = new ZendFilterBeta(); echo $beta->getLocale(); //en_US
}
Aliassing, useful to replace the
       parent:: construct
namespace ZendMvcController {
Use ...
    trait StdlibDispatch {
             public function dispatch(Request $request, Response $response = null) {
                $this->request = $request;
                if (!$response) { $response = new HttpResponse(); }
                $this->response = $response;
                ...
                if ($result->stopped()) { return $result->last(); }
                return $e->getResult();
            }
    }

        abstract class ActionController implements Dispatchable, InjectApplicationEvent, LocatorAware {
            use StdlibDispatch;
        }

        abstract class RestfulController implementsDispatchable, InjectApplicationEvent, LocatorAware {
            use StdlibDispatch {StdlibDispatch::dispatch as dispatchTrait};


            public function dispatch(Request $request, Response $response = null) {
                if (!$request instanceof HttpRequest) {
                    throw new InvalidArgumentException('Expected an HTTP request');
                }
                return $this->dispatchTrait($request, $response);
            }
        }
}
Aliasing could potentially be a
    refactoring nightmare
namespace ZendView;
class TemplatePathStack implements
TemplateResolver
{
    use Options {
        Options::setOptions as setConfig
    }
}
$templateStack = (new TemplatePathStack)
->setConfig(['lfi_protection' => true]);

//$templateStack = (new TemplatePathStack)
->setOptions(['lfi_protection' => true]);
Visibility
namespace ZendView;
class TemplatePathStack implements
TemplateResolver
{
    use Options {Options::setOptions as protected}


    public function __construct($options = array())
    { $this->setOptions($options); }


}
new TemplatePathStack(['lfi_protection' => true]);
Interface compliance
namespace ZendView;
trait Options {
    public function setOptions($options) {
         //set the options
    }
}
interface TemplateResolver {
    public function setConfig($options);
}


class TemplatePathStack implements TemplateResolver {
    use Options {Options::setOptions as setConfig;}
}
(new TemplatePathStack)->setConfig(['lfi_protection' => true]);
namespace ZendView;
trait Options {
    public function setOptions($options) { }
}

class TemplatePathStack {
    use Options {
         Options::setOptions as setConfig;
    }
}
$templateStack = (new TemplatePathStack)
->setConfig(['lfi_protection' => true]);
var_dump($templateStack instanceof Options);
// false
namespace ZendView;
trait Options {
    abstract public function setOptions($options);
}

class TemplatePathStack {
    use Options;
    public function setOptions($options)
    { echo 'implementation enforced by trait'; }
}
$templateStack = (new TemplatePathStack)
->setOptions(['lfi_protection' => true]);
var_dump($templateStack instanceof Options); // false
namespace ZendView;
trait Options {
    abstract public function setOptions($options);
}

class TemplatePathStack {
    use Options {Options::setOptions as setConfig;}

    public function setConfig($options)
    { echo 'implementation enforced by trait'; }
}
// Fatal error: Class ZendViewTemplatePathStack
contains 1 abstract method and must therefore be
declared abstract or implement the remaining methods
(ZendViewTemplatePathStack::setOptions)
Magic Constants
<?php
trait Id {
     public function getClass() {
         echo __CLASS__;
     }
     public function getTrait() {
         echo __TRAIT__;
     }
 }

class Foo {
     use Id;
 }

(new Foo)->getClass(); //Foo
(new Foo)->getTrait(); //Id
Autoloading
<?php
namespace NbeZfLoader{
    class foo {
        use Id;
    }
}
namespace {
    function __autoload($class) {
        var_dump($class);
        die();
    }
}
// string(15) "NbeZfLoaderId"
Good things about
                 traits

●   Removes code duplication
●   Helps keeping your code cleaner
●   Maintainability
●   Aliassing works for interfaces
●   Property handling
●   Easy Autoloading
Bad things
    about traits
●   Adds code complexity /
    understandability with the
    insteadof operator.
●   Duck typing
●   Aliassing Fails for Abstract
    Classes
●   Property handling
Benchmarks 5.3 vs 5.4
●   ZF project: http://nickbelhomme.com
●   Benchmark / Profiling tool: xhprof
●   How: 2 VirtualBox Machines - debian clones,
    with only PHP upgrade (5.4.0RC3)
5.3.3

●   Total Incl. Wall Time (microsec): 674,842 ms
●   Total Incl. CPU (microsecs): 672,042 ms
●   Total Incl. MemUse (bytes): 13,827,864 bytes
●   Total Incl. PeakMemUse (bytes): 13,865,976
    bytes
●   Number of Function Calls: 14,524
5.4.0RC3
    Total Incl. Wall Time (microsec): 166,813 ms
●   Total Incl. CPU (microsecs): 168,011 ms
●   Total Incl. MemUse (bytes):7,969,928 bytes
●   Total Incl. PeakMemUse (bytes):8,015,944
    bytes
●   Number of Function Calls: 14,520
Who runs PHP5.4 today for testing?
YOU WIN




  6
Please rate my talk
https://joind.in/4774
The End!

                   THANK YOU
          Please rate my talk
          https://joind.in/4774
contact@nickbelhomme.com

Slideshare, Twitter, IRC: NickBelhomme

http://blog.nickbelhomme.com
Flickr Photo Credits
●   Helico
●   donkeyhotey
●   jannem
●   Thomas.constantin
●   SJ photography
●   davidagalvan
●   stev.ie
●   Mosman Council
●   DeaPeaJay

More Related Content

What's hot

Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
James Titcumb
 
Fighting Fear-Driven-Development With PHPUnit
Fighting Fear-Driven-Development With PHPUnitFighting Fear-Driven-Development With PHPUnit
Fighting Fear-Driven-Development With PHPUnit
James Fuller
 
PECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life betterPECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life better
ZendCon
 
PHP 5.3
PHP 5.3PHP 5.3
PHP 5.3
Chris Stone
 
How to deploy node to production
How to deploy node to productionHow to deploy node to production
How to deploy node to production
Sean Hess
 
The why and how of moving to php 5.4
The why and how of moving to php 5.4The why and how of moving to php 5.4
The why and how of moving to php 5.4
Wim Godden
 
PHP7 is coming
PHP7 is comingPHP7 is coming
PHP7 is coming
julien pauli
 
What you need to remember when you upload to CPAN
What you need to remember when you upload to CPANWhat you need to remember when you upload to CPAN
What you need to remember when you upload to CPAN
charsbar
 
CLI, the other SAPI
CLI, the other SAPICLI, the other SAPI
CLI, the other SAPI
Combell NV
 
Modern PHP
Modern PHPModern PHP
Modern PHP
Simon Jones
 
PHP 良好實踐 (Best Practice)
PHP 良好實踐 (Best Practice)PHP 良好實踐 (Best Practice)
PHP 良好實踐 (Best Practice)
Win Yu
 
Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011
Wim Godden
 
Php mysql ppt
Php mysql pptPhp mysql ppt
Doctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHPDoctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHP
Guilherme Blanco
 
Spl in the wild
Spl in the wildSpl in the wild
Spl in the wild
Elizabeth Smith
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
Hisateru Tanaka
 
30 Minutes To CPAN
30 Minutes To CPAN30 Minutes To CPAN
30 Minutes To CPAN
daoswald
 
2021.laravelconf.tw.slides2
2021.laravelconf.tw.slides22021.laravelconf.tw.slides2
2021.laravelconf.tw.slides2
LiviaLiaoFontech
 
DevOps in PHP environment
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment
Evaldo Felipe
 
Preparing for the next PHP version (5.6)
Preparing for the next PHP version (5.6)Preparing for the next PHP version (5.6)
Preparing for the next PHP version (5.6)
Damien Seguy
 

What's hot (20)

Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
 
Fighting Fear-Driven-Development With PHPUnit
Fighting Fear-Driven-Development With PHPUnitFighting Fear-Driven-Development With PHPUnit
Fighting Fear-Driven-Development With PHPUnit
 
PECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life betterPECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life better
 
PHP 5.3
PHP 5.3PHP 5.3
PHP 5.3
 
How to deploy node to production
How to deploy node to productionHow to deploy node to production
How to deploy node to production
 
The why and how of moving to php 5.4
The why and how of moving to php 5.4The why and how of moving to php 5.4
The why and how of moving to php 5.4
 
PHP7 is coming
PHP7 is comingPHP7 is coming
PHP7 is coming
 
What you need to remember when you upload to CPAN
What you need to remember when you upload to CPANWhat you need to remember when you upload to CPAN
What you need to remember when you upload to CPAN
 
CLI, the other SAPI
CLI, the other SAPICLI, the other SAPI
CLI, the other SAPI
 
Modern PHP
Modern PHPModern PHP
Modern PHP
 
PHP 良好實踐 (Best Practice)
PHP 良好實踐 (Best Practice)PHP 良好實踐 (Best Practice)
PHP 良好實踐 (Best Practice)
 
Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011
 
Php mysql ppt
Php mysql pptPhp mysql ppt
Php mysql ppt
 
Doctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHPDoctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHP
 
Spl in the wild
Spl in the wildSpl in the wild
Spl in the wild
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
30 Minutes To CPAN
30 Minutes To CPAN30 Minutes To CPAN
30 Minutes To CPAN
 
2021.laravelconf.tw.slides2
2021.laravelconf.tw.slides22021.laravelconf.tw.slides2
2021.laravelconf.tw.slides2
 
DevOps in PHP environment
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment
 
Preparing for the next PHP version (5.6)
Preparing for the next PHP version (5.6)Preparing for the next PHP version (5.6)
Preparing for the next PHP version (5.6)
 

Viewers also liked

Php basics
Php basicsPhp basics
Php basics
hamfu
 
The why and how of moving to PHP 5.5/5.6
The why and how of moving to PHP 5.5/5.6The why and how of moving to PHP 5.5/5.6
The why and how of moving to PHP 5.5/5.6
Wim Godden
 
Php
PhpPhp
PHP slides
PHP slidesPHP slides
PHP slides
Farzad Wadia
 
Php tutorial
Php tutorialPhp tutorial
Php tutorial
Niit
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHP
Rob Knight
 
Healthcare management powerpoint
Healthcare management powerpointHealthcare management powerpoint
Healthcare management powerpoint
Korrin Wiggins
 
SMS il RE della comunicazione
SMS il RE della comunicazioneSMS il RE della comunicazione
SMS il RE della comunicazione
Davide Ricca
 
Suzuki adferdin god_uppskrift
Suzuki adferdin  god_uppskriftSuzuki adferdin  god_uppskrift
Suzuki adferdin god_uppskrift
Kristinn Örn Kristinsson
 
Kuidas Targad Juhid Tegutsevad 2007
Kuidas Targad Juhid Tegutsevad 2007Kuidas Targad Juhid Tegutsevad 2007
Kuidas Targad Juhid Tegutsevad 2007
Fastleader
 
Presentation 1112 for blog 2
Presentation 1112 for blog 2Presentation 1112 for blog 2
Presentation 1112 for blog 2
katie_higson
 
cv pdf
cv pdfcv pdf
cv pdf
marwan fahmy
 
Tautas ataudzes mērķi NAP2020 un to sasniegšanas gaita
Tautas ataudzes mērķi NAP2020 un to sasniegšanas gaitaTautas ataudzes mērķi NAP2020 un to sasniegšanas gaita
Tautas ataudzes mērķi NAP2020 un to sasniegšanas gaita
Pārresoru kordinācijas centrs (PKC)
 
Personal Branding &amp; You-How to use social Media to create tour own person...
Personal Branding &amp; You-How to use social Media to create tour own person...Personal Branding &amp; You-How to use social Media to create tour own person...
Personal Branding &amp; You-How to use social Media to create tour own person...
David Wesson
 
新浪微博的BigPipe后端实现技术分享——11月26日淘宝aDev技术沙龙
新浪微博的BigPipe后端实现技术分享——11月26日淘宝aDev技术沙龙新浪微博的BigPipe后端实现技术分享——11月26日淘宝aDev技术沙龙
新浪微博的BigPipe后端实现技术分享——11月26日淘宝aDev技术沙龙
slawdan
 
Transformation or Transition
Transformation or TransitionTransformation or Transition
Transformation or Transition
Mike Pounsford
 
صداقت حضرت مسیح موعود علیہ السلام از احادیث
صداقت حضرت مسیح موعود علیہ السلام از احادیثصداقت حضرت مسیح موعود علیہ السلام از احادیث
صداقت حضرت مسیح موعود علیہ السلام از احادیث
muzaffertahir9
 

Viewers also liked (20)

Php basics
Php basicsPhp basics
Php basics
 
The why and how of moving to PHP 5.5/5.6
The why and how of moving to PHP 5.5/5.6The why and how of moving to PHP 5.5/5.6
The why and how of moving to PHP 5.5/5.6
 
Php
PhpPhp
Php
 
PHP slides
PHP slidesPHP slides
PHP slides
 
Php tutorial
Php tutorialPhp tutorial
Php tutorial
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHP
 
Healthcare management powerpoint
Healthcare management powerpointHealthcare management powerpoint
Healthcare management powerpoint
 
ספר וטהר לבנו השלם.
ספר וטהר לבנו השלם.ספר וטהר לבנו השלם.
ספר וטהר לבנו השלם.
 
SMS il RE della comunicazione
SMS il RE della comunicazioneSMS il RE della comunicazione
SMS il RE della comunicazione
 
Suzuki adferdin god_uppskrift
Suzuki adferdin  god_uppskriftSuzuki adferdin  god_uppskrift
Suzuki adferdin god_uppskrift
 
Kuidas Targad Juhid Tegutsevad 2007
Kuidas Targad Juhid Tegutsevad 2007Kuidas Targad Juhid Tegutsevad 2007
Kuidas Targad Juhid Tegutsevad 2007
 
Presentation 1112 for blog 2
Presentation 1112 for blog 2Presentation 1112 for blog 2
Presentation 1112 for blog 2
 
cv pdf
cv pdfcv pdf
cv pdf
 
ΒΑΚΑΛΟΥΔΗ - ΠΡΟΣΚΛΗΣΗ
ΒΑΚΑΛΟΥΔΗ - ΠΡΟΣΚΛΗΣΗΒΑΚΑΛΟΥΔΗ - ΠΡΟΣΚΛΗΣΗ
ΒΑΚΑΛΟΥΔΗ - ΠΡΟΣΚΛΗΣΗ
 
Retallos 2008
Retallos 2008Retallos 2008
Retallos 2008
 
Tautas ataudzes mērķi NAP2020 un to sasniegšanas gaita
Tautas ataudzes mērķi NAP2020 un to sasniegšanas gaitaTautas ataudzes mērķi NAP2020 un to sasniegšanas gaita
Tautas ataudzes mērķi NAP2020 un to sasniegšanas gaita
 
Personal Branding &amp; You-How to use social Media to create tour own person...
Personal Branding &amp; You-How to use social Media to create tour own person...Personal Branding &amp; You-How to use social Media to create tour own person...
Personal Branding &amp; You-How to use social Media to create tour own person...
 
新浪微博的BigPipe后端实现技术分享——11月26日淘宝aDev技术沙龙
新浪微博的BigPipe后端实现技术分享——11月26日淘宝aDev技术沙龙新浪微博的BigPipe后端实现技术分享——11月26日淘宝aDev技术沙龙
新浪微博的BigPipe后端实现技术分享——11月26日淘宝aDev技术沙龙
 
Transformation or Transition
Transformation or TransitionTransformation or Transition
Transformation or Transition
 
صداقت حضرت مسیح موعود علیہ السلام از احادیث
صداقت حضرت مسیح موعود علیہ السلام از احادیثصداقت حضرت مسیح موعود علیہ السلام از احادیث
صداقت حضرت مسیح موعود علیہ السلام از احادیث
 

Similar to PHP traits, treat or threat?

PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
jsmith92
 
Fatc
FatcFatc
PHPSpec BDD Framework
PHPSpec BDD FrameworkPHPSpec BDD Framework
PHPSpec BDD Framework
Marcello Duarte
 
Zend Framework 2 - Basic Components
Zend Framework 2  - Basic ComponentsZend Framework 2  - Basic Components
Zend Framework 2 - Basic Components
Mateusz Tymek
 
Create your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 VeronaCreate your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 Verona
Patrick Allaert
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
Kris Wallsmith
 
Node.js for PHP developers
Node.js for PHP developersNode.js for PHP developers
Node.js for PHP developers
Andrew Eddie
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
patter
 
Slide
SlideSlide
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
Shinya Ohyanagi
 
php AND MYSQL _ppt.pdf
php AND MYSQL _ppt.pdfphp AND MYSQL _ppt.pdf
php AND MYSQL _ppt.pdf
SVN Polytechnic Kalan Sultanpur UP
 
Php Tutorials for Beginners
Php Tutorials for BeginnersPhp Tutorials for Beginners
Php Tutorials for Beginners
Vineet Kumar Saini
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92
 
Solid principles
Solid principlesSolid principles
Solid principles
Bastian Feder
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
Marcello Duarte
 
The why and how of moving to php 5.4/5.5
The why and how of moving to php 5.4/5.5The why and how of moving to php 5.4/5.5
The why and how of moving to php 5.4/5.5
Wim Godden
 
The why and how of moving to PHP 5.4/5.5
The why and how of moving to PHP 5.4/5.5The why and how of moving to PHP 5.4/5.5
The why and how of moving to PHP 5.4/5.5
Wim Godden
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
chartjes
 
Introducing PHP Latest Updates
Introducing PHP Latest UpdatesIntroducing PHP Latest Updates
Introducing PHP Latest Updates
Iftekhar Eather
 
Zend Framework 2 Patterns
Zend Framework 2 PatternsZend Framework 2 Patterns
Zend Framework 2 Patterns
Zend by Rogue Wave Software
 

Similar to PHP traits, treat or threat? (20)

PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
 
Fatc
FatcFatc
Fatc
 
PHPSpec BDD Framework
PHPSpec BDD FrameworkPHPSpec BDD Framework
PHPSpec BDD Framework
 
Zend Framework 2 - Basic Components
Zend Framework 2  - Basic ComponentsZend Framework 2  - Basic Components
Zend Framework 2 - Basic Components
 
Create your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 VeronaCreate your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 Verona
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
Node.js for PHP developers
Node.js for PHP developersNode.js for PHP developers
Node.js for PHP developers
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Slide
SlideSlide
Slide
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
php AND MYSQL _ppt.pdf
php AND MYSQL _ppt.pdfphp AND MYSQL _ppt.pdf
php AND MYSQL _ppt.pdf
 
Php Tutorials for Beginners
Php Tutorials for BeginnersPhp Tutorials for Beginners
Php Tutorials for Beginners
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
Solid principles
Solid principlesSolid principles
Solid principles
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
The why and how of moving to php 5.4/5.5
The why and how of moving to php 5.4/5.5The why and how of moving to php 5.4/5.5
The why and how of moving to php 5.4/5.5
 
The why and how of moving to PHP 5.4/5.5
The why and how of moving to PHP 5.4/5.5The why and how of moving to PHP 5.4/5.5
The why and how of moving to PHP 5.4/5.5
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Introducing PHP Latest Updates
Introducing PHP Latest UpdatesIntroducing PHP Latest Updates
Introducing PHP Latest Updates
 
Zend Framework 2 Patterns
Zend Framework 2 PatternsZend Framework 2 Patterns
Zend Framework 2 Patterns
 

More from Nick Belhomme

Vagrant move over, here is Docker
Vagrant move over, here is DockerVagrant move over, here is Docker
Vagrant move over, here is Docker
Nick Belhomme
 
Mastering selenium for automated acceptance tests
Mastering selenium for automated acceptance testsMastering selenium for automated acceptance tests
Mastering selenium for automated acceptance tests
Nick Belhomme
 
PHP Quality Assurance Workshop PHPBenelux
PHP Quality Assurance Workshop PHPBeneluxPHP Quality Assurance Workshop PHPBenelux
PHP Quality Assurance Workshop PHPBenelux
Nick Belhomme
 
Cursus phpunit
Cursus phpunitCursus phpunit
Cursus phpunit
Nick Belhomme
 
Zend Framework Form: Mastering Decorators
Zend Framework Form: Mastering DecoratorsZend Framework Form: Mastering Decorators
Zend Framework Form: Mastering Decorators
Nick Belhomme
 
Zend Framework 1.8 workshop
Zend Framework 1.8 workshopZend Framework 1.8 workshop
Zend Framework 1.8 workshop
Nick Belhomme
 

More from Nick Belhomme (6)

Vagrant move over, here is Docker
Vagrant move over, here is DockerVagrant move over, here is Docker
Vagrant move over, here is Docker
 
Mastering selenium for automated acceptance tests
Mastering selenium for automated acceptance testsMastering selenium for automated acceptance tests
Mastering selenium for automated acceptance tests
 
PHP Quality Assurance Workshop PHPBenelux
PHP Quality Assurance Workshop PHPBeneluxPHP Quality Assurance Workshop PHPBenelux
PHP Quality Assurance Workshop PHPBenelux
 
Cursus phpunit
Cursus phpunitCursus phpunit
Cursus phpunit
 
Zend Framework Form: Mastering Decorators
Zend Framework Form: Mastering DecoratorsZend Framework Form: Mastering Decorators
Zend Framework Form: Mastering Decorators
 
Zend Framework 1.8 workshop
Zend Framework 1.8 workshopZend Framework 1.8 workshop
Zend Framework 1.8 workshop
 

Recently uploaded

Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
Matthias Neugebauer
 
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Zilliz
 
UX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business GoalsUX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business Goals
FIDO Alliance
 
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
OnBoard
 
Finetuning GenAI For Hacking and Defending
Finetuning GenAI For Hacking and DefendingFinetuning GenAI For Hacking and Defending
Finetuning GenAI For Hacking and Defending
Priyanka Aash
 
Types of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technologyTypes of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technology
ldtexsolbl
 
Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10
ankush9927
 
Acumatica vs. Sage Intacct _Construction_July (1).pptx
Acumatica vs. Sage Intacct _Construction_July (1).pptxAcumatica vs. Sage Intacct _Construction_July (1).pptx
Acumatica vs. Sage Intacct _Construction_July (1).pptx
BrainSell Technologies
 
It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...
Zilliz
 
Discovery Series - Zero to Hero - Task Mining Session 1
Discovery Series - Zero to Hero - Task Mining Session 1Discovery Series - Zero to Hero - Task Mining Session 1
Discovery Series - Zero to Hero - Task Mining Session 1
DianaGray10
 
What's New in Teams Calling, Meetings, Devices June 2024
What's New in Teams Calling, Meetings, Devices June 2024What's New in Teams Calling, Meetings, Devices June 2024
What's New in Teams Calling, Meetings, Devices June 2024
Stephanie Beckett
 
Uncharted Together- Navigating AI's New Frontiers in Libraries
Uncharted Together- Navigating AI's New Frontiers in LibrariesUncharted Together- Navigating AI's New Frontiers in Libraries
Uncharted Together- Navigating AI's New Frontiers in Libraries
Brian Pichman
 
Retrieval Augmented Generation Evaluation with Ragas
Retrieval Augmented Generation Evaluation with RagasRetrieval Augmented Generation Evaluation with Ragas
Retrieval Augmented Generation Evaluation with Ragas
Zilliz
 
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
AimanAthambawa1
 
How UiPath Discovery Suite supports identification of Agentic Process Automat...
How UiPath Discovery Suite supports identification of Agentic Process Automat...How UiPath Discovery Suite supports identification of Agentic Process Automat...
How UiPath Discovery Suite supports identification of Agentic Process Automat...
DianaGray10
 
Intel Unveils Core Ultra 200V Lunar chip .pdf
Intel Unveils Core Ultra 200V Lunar chip .pdfIntel Unveils Core Ultra 200V Lunar chip .pdf
Intel Unveils Core Ultra 200V Lunar chip .pdf
Tech Guru
 
Sonkoloniya documentation - ONEprojukti.pdf
Sonkoloniya documentation - ONEprojukti.pdfSonkoloniya documentation - ONEprojukti.pdf
Sonkoloniya documentation - ONEprojukti.pdf
SubhamMandal40
 
Generative AI Reasoning Tech Talk - July 2024
Generative AI Reasoning Tech Talk - July 2024Generative AI Reasoning Tech Talk - July 2024
Generative AI Reasoning Tech Talk - July 2024
siddu769252
 
Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024
Nicolás Lopéz
 
Google I/O Extended Harare Merged Slides
Google I/O Extended Harare Merged SlidesGoogle I/O Extended Harare Merged Slides
Google I/O Extended Harare Merged Slides
Google Developer Group - Harare
 

Recently uploaded (20)

Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
 
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
 
UX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business GoalsUX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business Goals
 
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
 
Finetuning GenAI For Hacking and Defending
Finetuning GenAI For Hacking and DefendingFinetuning GenAI For Hacking and Defending
Finetuning GenAI For Hacking and Defending
 
Types of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technologyTypes of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technology
 
Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10
 
Acumatica vs. Sage Intacct _Construction_July (1).pptx
Acumatica vs. Sage Intacct _Construction_July (1).pptxAcumatica vs. Sage Intacct _Construction_July (1).pptx
Acumatica vs. Sage Intacct _Construction_July (1).pptx
 
It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...
 
Discovery Series - Zero to Hero - Task Mining Session 1
Discovery Series - Zero to Hero - Task Mining Session 1Discovery Series - Zero to Hero - Task Mining Session 1
Discovery Series - Zero to Hero - Task Mining Session 1
 
What's New in Teams Calling, Meetings, Devices June 2024
What's New in Teams Calling, Meetings, Devices June 2024What's New in Teams Calling, Meetings, Devices June 2024
What's New in Teams Calling, Meetings, Devices June 2024
 
Uncharted Together- Navigating AI's New Frontiers in Libraries
Uncharted Together- Navigating AI's New Frontiers in LibrariesUncharted Together- Navigating AI's New Frontiers in Libraries
Uncharted Together- Navigating AI's New Frontiers in Libraries
 
Retrieval Augmented Generation Evaluation with Ragas
Retrieval Augmented Generation Evaluation with RagasRetrieval Augmented Generation Evaluation with Ragas
Retrieval Augmented Generation Evaluation with Ragas
 
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
 
How UiPath Discovery Suite supports identification of Agentic Process Automat...
How UiPath Discovery Suite supports identification of Agentic Process Automat...How UiPath Discovery Suite supports identification of Agentic Process Automat...
How UiPath Discovery Suite supports identification of Agentic Process Automat...
 
Intel Unveils Core Ultra 200V Lunar chip .pdf
Intel Unveils Core Ultra 200V Lunar chip .pdfIntel Unveils Core Ultra 200V Lunar chip .pdf
Intel Unveils Core Ultra 200V Lunar chip .pdf
 
Sonkoloniya documentation - ONEprojukti.pdf
Sonkoloniya documentation - ONEprojukti.pdfSonkoloniya documentation - ONEprojukti.pdf
Sonkoloniya documentation - ONEprojukti.pdf
 
Generative AI Reasoning Tech Talk - July 2024
Generative AI Reasoning Tech Talk - July 2024Generative AI Reasoning Tech Talk - July 2024
Generative AI Reasoning Tech Talk - July 2024
 
Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024
 
Google I/O Extended Harare Merged Slides
Google I/O Extended Harare Merged SlidesGoogle I/O Extended Harare Merged Slides
Google I/O Extended Harare Merged Slides
 

PHP traits, treat or threat?

  • 1. PHP traits, treat or threat? Nick Belhomme January 28th, PHPBenelux Conference 2012, Belgium
  • 2. Software Architect / Project Lead Author of the Zend Framework 2.0 Cookbook International Conference Speaker Contributor to various Open Source Projects Freelance PHP Consultant
  • 3. Market positions http://w3techs.com/
  • 4. Market positions ● Python 0.3%
  • 5. Market positions ● Ruby 0.6% ● Python 0.3%
  • 6. Market positions ● Perl 1.0% ● Ruby 0.6% ● Python 0.3%
  • 7. Market positions ● ColdFusion 1.2% ● Perl 1.0% ● Ruby 0.6% ● Python 0.3%
  • 8. Market positions ● Java 1.2% ● ColdFusion 1.2% ● Perl 1.0% ● Ruby 0.6% ● Python 0.3%
  • 9. Market positions ● ASP.NET 21.6% ● Java 1.2% ● ColdFusion 1.2% ● Perl 1.0% ● Ruby 0.6% ● Python 0.3%
  • 10. Market positions ● PHP 77.4% ● ASP.NET 21.6% ● Java 1.2% ● ColdFusion 1.2% ● Perl 1.0% ● Ruby 0.6% ● Python 0.3%
  • 11. PHP Market Position, 11 Jan 2012 Used by high traffic sites Java ColdFusion Perl ASP.NET PHP Used by low traffic sites Used by fewer sites Used by many sites
  • 12. PHP Version Adoption ● PHP 5 93.9% ● PHP 4 6.1% ● PHP 3 < 0.1% ● PHP 6 < 0.1%
  • 13. PHP 5 usage ● Version 5.2 73.8% ● Version 5.3 20.2% ● Version 5.1 5.8% ● Version 5.0 0.2% ● Version 5.4 < 0.1%
  • 14. Slow 5.3 Adoption? ● Shared hosting ● Companies refrain from updating stable systems / distributions ● You
  • 15. Adopt now ● More stability ● Security ● Better engine (ie garbage collection) ● New language features ● Cleaner code because of more elegant ways of solving problems
  • 16. PHP 5.4 ● Array short syntax (javascript notation) ● Array dereferencing ● Class access on instantiation ● Indirect method call by array variable ● Engine processes OO code faster ● <?= ● JSONSerializable interface ● ...
  • 18. ZF Use Case ZF Code base used is for illustration purposes only and do –not-- express future possible implementations. ZF2.0 is not yet released so giving ZF3.0 implementations illustrates only my own assumptions. PHP5.4 stable is not yet released so no real world projects are and should be running this version. Because of this no real best practices have been defined.
  • 19. namespace ZendView; class TemplatePathStack implements TemplateResolver { public function setOptions($options = array()) { if (!is_array($options) && !$options instanceof Traversable) { throw new ExceptionInvalidArgumentException( __METHOD__ . ' expects an array or Traversable' ); } foreach ($options as $key => $value) { $this->setOption($key, $value); } return $this; } public function setOption($key, $value) { switch (strtolower($key)) { case 'lfi_protection': $this->setLfiProtection($value); break; case 'script_paths': $this->addPaths($value); break; default: break; } } }
  • 20. namespace ZendMvcRouter; class RouteBroker implements Broker { public function setOptions($options) { if (!is_array($options) && !$options instanceof Traversable) { throw new ExceptionInvalidArgumentException(sprintf( 'Expected an array or Traversable; received "%s"', (is_object($options) ? get_class($options) : gettype($options)) )); } foreach ($options as $key => $value) { switch (strtolower($key)) { case 'class_loader': // handle this case Default: break;// ignore unknown options } } return $this; } }
  • 21. Problem: Code Duplication if (!is_array($options) && !$options instanceof Traversable) { throw new ExceptionInvalidArgumentException(sprintf( 'Expected an array or Traversable; received "%s"', (is_object($options) ? get_class($options) : gettype($options)) )); } foreach ($options as $key => $value) { //handle each case } return $this;
  • 22. Solution in PHP5.4? Multiple Inheritance ● Would provide the setOptions in all child classes needed ● Introduces the diamond problem
  • 23. NOT an Option! A better solution called Traits ● Would provide the setOptions in all classes that use the trait ● Eliminates the diamond problem
  • 24. trait Options { public function setOptions($options) { if (!is_array($options) && !$options instanceof Traversable) { throw new ExceptionInvalidArgumentException(sprintf( 'Expected an array or Traversable; received "%s"', (is_object($options) ? get_class($options) : gettype($options)) )); } foreach ($options as $key => $value) { $this->setOption($key, $value); } return $this; } }
  • 25. namespace ZendView; class TemplatePathStack implements TemplateResolver { use Options; public function setOption($key, $value) { switch (strtolower($key)) { case 'lfi_protection': $this->setLfiProtection($value); break; case 'script_paths': $this->addPaths($value); break; default: break; } } } $templateStack = new TemplatePathStack(); $templateStack->setOptions(['lfi_protection' => true]);
  • 26. namespace ZendMvcRouter; class RouteBroker implements Broker { use Options; public function setOption($key, $value) { switch (strtolower($key)) { case 'class_loader': // handle this case default: // ignore unknown options break; } } } $routeBroker = (new RouteBroker)->setOptions(['class_loader'=>'SomeLoader']);
  • 27. You have just seen traits
  • 28. Lets dive deeper get your chest wet
  • 29. namespace ZendLoader { use RuntimeException; trait SplRegister { public function register() { spl_autoload_register(array($this, 'autoload')); } public function unregister() { spl_autoload_unregister(array($this, 'autoload')); } } class StandardAutoloader { use SplRegister; public function unregister() { throw new RuntimeException( 'you should not unregister the standard autoloader once registered' ); } } } namespace { $loader = new ZendLoaderStandardAutoloader(); $loader->register(); $loader->unregister(); // will throw the exception }
  • 30. Precedence Order The precedence order is that members from the current class override Trait methods.
  • 31. namespace ZendLoader { use RuntimeException; class StandardAutoloader { public function unregister() { throw new RuntimeException( 'you should not unregister the standard autoloader once registered' ); } } } namespace NbeZfLoader { use ZendLoader as ZendLoader; class StandardAutoloader extends ZendLoaderStandardAutoloader { use ZendLoaderSplRegister; } } namespace { $loader = new NbeZfLoaderStandardAutoloader(); $loader->register(); //will register (trait) $loader->unregister(); // will unregister (trait) }
  • 32. Precedence Order An inherited member from a base class is overridden by a member inserted by a Trait
  • 34. namespace ZendLoader { use RuntimeException; class StandardAutoloader { public function unregister() { throw new RuntimeException( 'you should not unregister the standard autoloader once registered' ); } } } namespace NbeZfLoader { use ZendLoader as ZendLoader; class StandardAutoloader extends ZendLoaderStandardAutoloader { use ZendLoaderSplRegister { ZendLoaderStandardAutoloader::unregister insteadof ZendLoaderSplRegister; } } } namespace { $loader = new NbeZfLoaderStandardAutoloader(); $loader->register(); //will register (trait) $loader->unregister(); // will throw RuntimeException (base class) }
  • 35. insteadof Can be used to say which method to use instead of the trait method.
  • 37. namespace ZendFilter { trait Locale { protected $locale; public function getLocale() { return $this->locale; } public function setLocale($locale = null) { $this->locale = ZendLocale::findLocale($locale); return $this; } } trait WhiteSpace { protected $allowWhiteSpace; public function getAllowWhiteSpace() { return $this->allowWhiteSpace; } public function setAllowWhiteSpace($allowWhiteSpace) { $this->allowWhiteSpace = (boolean) $allowWhiteSpace; return $this; } } class Alpha extends AbstractFilter { use Locale, WhiteSpace; } }
  • 38. Multiple Conflicting Traits The Diamond Problem (Not yours or a girls best friend!)
  • 39. namespace ZendFilter { trait Locale { protected $locale; public function getLocale() { return $this->locale; } public function setLocale($locale = null) { $this->locale = ZendLocale::findLocale($locale); return $this; } } trait SecondLocale { protected $locale; public function setLocale($locale = null) { if (is_string($locale)) { $locale = array($locale); } elseif ($locale instanceof Locale) { $locale = array($locale->toString()); } elseif (!is_array($locale)) { throw new ExceptionInvalidArgumentException( 'Locale has to be string, array or an instance of Zend_Locale' ); } foreach ($locale as $single) { if (!Locale::isLocale($single)) { throw new ExceptionInvalidArgumentException("Unknown locale '$single'"); } } $this->_locale = $locale; return $this; } } class Alpha { use Locale, SecondLocale; } } namespace { (new ZendFilterAlpha)->setLocale('nl_be'); }
  • 40. Fatal error: Trait method getLocale has not been applied, because there are collisions with other trait methods
  • 42. namespace ZendFilter { trait Locale { protected $locale; public function getLocale() public function setLocale($locale = null) } trait SecondLocale { protected $locale; public function setLocale($locale = null) } class Alpha { use Locale, SecondLocale { SecondLocale::setLocale insteadof Locale; } } } namespace { $alpha = new ZendFilterAlpha(); $alpha->setLocale('nl_be'); }
  • 43. WIN!
  • 44. BUT Strict Standards: ZendFilterLocale and ZendFilterSecondLocale define the same property ($locale) in the composition of ZendFilterAlpha. This might be incompatible, to improve maintainability consider using accessor methods in traits instead.
  • 45. namespace ZendFilter { trait Locale { protected $locale = 'nl_BE'; public function getLocale() public function setLocale($locale = null) } trait SecondLocale { protected $locale = 'en_US'; public function setLocale($locale = null) } class Alpha { use Locale, SecondLocale { SecondLocale::setLocale insteadof Locale; } } } namespace { $alpha = new ZendFilterAlpha(); $alpha->setLocale('nl_BE'); }
  • 46. Fatal error: ZendFilterLocale and ZendFilterSecondLocale define the same property ($locale) in the composition of ZendFilterAlpha. However, the definition differs and is considered incompatible.
  • 47. namespace ZendFilter { trait Locale { static public $locale = 'en_US'; public function getLocale() { return self::$locale; } public function setLocale($locale = null) { self::$locale = $locale; } } class Alpha { use Locale; public function get() { return self::$locale; } } } namespace { $alpha = new ZendFilterAlpha(); echo $alpha->getLocale(); // en_US echo $alpha->get(); // en_US $alpha->setLocale('nl_be'); echo $alpha->getLocale(); // nl_be echo $alpha->get(); // nl_be }
  • 48. namespace ZendFilter { trait Locale { static public $locale = 'en_US'; public function getLocale() { return self::$locale; } public function setLocale($locale = null) { self::$locale = $locale; } } class Alpha { use Locale; public function get() { return self::$locale; } } class Beta { use Locale; } } namespace { $alpha = new ZendFilterAlpha(); echo $alpha->getLocale(); // en_US $alpha->setLocale('nl_be'); echo $alpha->getLocale(); // nl_be $beta = new ZendFilterBeta(); echo $beta->getLocale(); //en_US }
  • 49. Aliassing, useful to replace the parent:: construct
  • 50. namespace ZendMvcController { Use ... trait StdlibDispatch { public function dispatch(Request $request, Response $response = null) { $this->request = $request; if (!$response) { $response = new HttpResponse(); } $this->response = $response; ... if ($result->stopped()) { return $result->last(); } return $e->getResult(); } } abstract class ActionController implements Dispatchable, InjectApplicationEvent, LocatorAware { use StdlibDispatch; } abstract class RestfulController implementsDispatchable, InjectApplicationEvent, LocatorAware { use StdlibDispatch {StdlibDispatch::dispatch as dispatchTrait}; public function dispatch(Request $request, Response $response = null) { if (!$request instanceof HttpRequest) { throw new InvalidArgumentException('Expected an HTTP request'); } return $this->dispatchTrait($request, $response); } } }
  • 51. Aliasing could potentially be a refactoring nightmare
  • 52. namespace ZendView; class TemplatePathStack implements TemplateResolver { use Options { Options::setOptions as setConfig } } $templateStack = (new TemplatePathStack) ->setConfig(['lfi_protection' => true]); //$templateStack = (new TemplatePathStack) ->setOptions(['lfi_protection' => true]);
  • 54. namespace ZendView; class TemplatePathStack implements TemplateResolver { use Options {Options::setOptions as protected} public function __construct($options = array()) { $this->setOptions($options); } } new TemplatePathStack(['lfi_protection' => true]);
  • 56. namespace ZendView; trait Options { public function setOptions($options) { //set the options } } interface TemplateResolver { public function setConfig($options); } class TemplatePathStack implements TemplateResolver { use Options {Options::setOptions as setConfig;} } (new TemplatePathStack)->setConfig(['lfi_protection' => true]);
  • 57. namespace ZendView; trait Options { public function setOptions($options) { } } class TemplatePathStack { use Options { Options::setOptions as setConfig; } } $templateStack = (new TemplatePathStack) ->setConfig(['lfi_protection' => true]); var_dump($templateStack instanceof Options); // false
  • 58. namespace ZendView; trait Options { abstract public function setOptions($options); } class TemplatePathStack { use Options; public function setOptions($options) { echo 'implementation enforced by trait'; } } $templateStack = (new TemplatePathStack) ->setOptions(['lfi_protection' => true]); var_dump($templateStack instanceof Options); // false
  • 59. namespace ZendView; trait Options { abstract public function setOptions($options); } class TemplatePathStack { use Options {Options::setOptions as setConfig;} public function setConfig($options) { echo 'implementation enforced by trait'; } } // Fatal error: Class ZendViewTemplatePathStack contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (ZendViewTemplatePathStack::setOptions)
  • 60. Magic Constants <?php trait Id { public function getClass() { echo __CLASS__; } public function getTrait() { echo __TRAIT__; } } class Foo { use Id; } (new Foo)->getClass(); //Foo (new Foo)->getTrait(); //Id
  • 61. Autoloading <?php namespace NbeZfLoader{ class foo { use Id; } } namespace { function __autoload($class) { var_dump($class); die(); } } // string(15) "NbeZfLoaderId"
  • 62. Good things about traits ● Removes code duplication ● Helps keeping your code cleaner ● Maintainability ● Aliassing works for interfaces ● Property handling ● Easy Autoloading
  • 63. Bad things about traits ● Adds code complexity / understandability with the insteadof operator. ● Duck typing ● Aliassing Fails for Abstract Classes ● Property handling
  • 64. Benchmarks 5.3 vs 5.4 ● ZF project: http://nickbelhomme.com ● Benchmark / Profiling tool: xhprof ● How: 2 VirtualBox Machines - debian clones, with only PHP upgrade (5.4.0RC3)
  • 65. 5.3.3 ● Total Incl. Wall Time (microsec): 674,842 ms ● Total Incl. CPU (microsecs): 672,042 ms ● Total Incl. MemUse (bytes): 13,827,864 bytes ● Total Incl. PeakMemUse (bytes): 13,865,976 bytes ● Number of Function Calls: 14,524
  • 66. 5.4.0RC3 Total Incl. Wall Time (microsec): 166,813 ms ● Total Incl. CPU (microsecs): 168,011 ms ● Total Incl. MemUse (bytes):7,969,928 bytes ● Total Incl. PeakMemUse (bytes):8,015,944 bytes ● Number of Function Calls: 14,520
  • 67. Who runs PHP5.4 today for testing?
  • 68. YOU WIN 6
  • 69. Please rate my talk https://joind.in/4774
  • 70. The End! THANK YOU Please rate my talk https://joind.in/4774 contact@nickbelhomme.com Slideshare, Twitter, IRC: NickBelhomme http://blog.nickbelhomme.com
  • 71. Flickr Photo Credits ● Helico ● donkeyhotey ● jannem ● Thomas.constantin ● SJ photography ● davidagalvan ● stev.ie ● Mosman Council ● DeaPeaJay