Preparing for the next PHP version (5.6)

Post on 28-Jun-2015

436 views 1 download

Tags:

description

With versions stretching from 5.3 to 5.6, PHP has several major published versions, that require special attention when migrating. Beyond checking for compilation, the code must be reviewed to avoid pitfalls like obsoletes functions, new features, change in default parameters or behavior. We'll set up a checklist of such traps, and ways to find them in the code and be reading for PHP 5.6.

Transcript of Preparing for the next PHP version (5.6)

Preparing for the next PHP version

Towards PHP 5.5 and 5.6

• Changing version is often a big challenge

• Backward incompatibilities

• New features

• How to spot them ?

Speaker

• Damien Seguy

• CTO at exakat

• Phather of the plush toy elePHPant

• Will talk on automated code audit later

PHP linting

• command line : php -l filename.php

• Will only parse the code,

• not execution

• Will spot compilation problems

PHP lint will find

• Short array syntax

• Function subscripting

• break/continue with variables

• Rare other situations

• Code that won’t compile anyway

Where else code will break?

• PHP running has 3 stages

• parsed

• compiled

• executed

Checked with lint

Checked with data and UT

Checked code review

What will change?

• Removed features

• Deprecated features

• Changed features

• New features

Deprecated features• PHP 5.6

• $HTTP_RAW_POST_DATA

• Call From Incompatible Context

• iconv and mbstring directives go to default_charset

• PHP 5.5

• /e in preg_replace

• ext/mysql

• mcrypt arguments

5.6

5.5

Deprecated features• $HTTP_RAW_POST_DATA

• Replace it by php://input

• php://input is now reusable

• ext/mysql

• Look for mysql_* functions

• Probably in Db/Adapter

5.6

5.5

Search is your friend

• Grep, or IDE’s search function will help you

• Look for mysql_*

• $HTTP_RAW_POST_DATA

Deprecated: The mysql extension is deprecated and will be removed in

the future: use mysqli or PDO instead in /path/to/filename.php on

line 11

Error_level to E_STRICT

/e and charset directives

• preg_replace(‘/ /e’, ‘evaled code’, $haystack)

• replaced preg_replace_callback(‘/ /‘, closure, $haystack)

• in php.ini, check for mbstring, iconv and default_charset

5.5

5.6

Where to look for• preg_replace

• Search for preg_replace function calls

• defaut_charset

• Search for ini_set, ini_get, ini_get_all, ini_restore, get_cfg_var

• Seach in php.ini, .htaccess

Incompatible context

<?php  class A {       function f() { echo get_class($this); }  }  A::f();  ?>

$ php53 test.php

Notice: Undefined variable: this in test.php on line 3 A

$ php56 test.php

Strict Standards: Non-static method A::f() should not be called statically in /Users/famille/Desktop/test.php on line 6

Notice: Undefined variable: this in test.php on line 3 A

5.6

Search for situations• Search for :: operator

• Get the class

• then the method

• then the static keyword

• Needs a automated auditing tool

• Code sniffer, IDE

Strict Standards: Non-static method A::f() should not be called statically in test.php on line 6

Changed behavior• json_decode is stricter

• it was more tolerant before with TRUE or False values

• gmp resources are object

• and not resources

• search for is_resource()

• mcrypt requires valid keys and vectors

• check correct size and vector presence

• pack and unpack

• More compatible with Perl

• Z and a format code must be checked

5.6

5.5

Added structures• PHP adds

• constants

• functions

• extensions

• traits

• interfaces

Added structuresFunctions Classes Constants

5.3 25 18 80

5.4 0 9 78

5.5 113 9 37

5.6 19 0 24

Total 157 36 219

New features

• Fixing

• Modernization

• New feature

Fixing

empty() upgrade

• No need anymore to expressions in a variable for empty()!

Fatal error: Can't use function return value in write context in test.php on line 6

function myFunction() {     return -2 ; }

if (empty(myFunction() + 2)) {     echo "This means 0!\n"; }

5.5

SELF::const != self::const<?php

class object {     const x = 1;          function x() { print SELF::x."\n"; } }

$object = new object(); $object->x(); ?>

Fatal error: Class 'SELF' not found in test.php on line 6

5.5

Modernization

Dereferencing

• Direct access to element in a string or an array.

<?php  /// Function dereferencingecho str_split("123", 1 )[2];  echo "\n"; 

/// Array dereferencingecho [5, 5, 3][0];  echo "\n"; 

/// String dereferencingecho 'PHP'[0];  echo "\n";  ?>5.5

Power operator

• Replaces pow()

• Be aware of precedence

echo pow(2, 3); 

$a=2;  $a **= 3; 

$a = 2 ** 3; 

5.6

… Variadic

• replaces func_get_args()

• Easier to read

function array_power($pow, ...$integers) {     foreach($integers as $i) {        print "$i ^ $pow  = ". ($i ** $pow)."\n";     }  }     array_power(3, 1, 2, 3, 4, 5); 

1 ^ 3 = 12 ^ 3 = 83 ^ 3 = 274 ^ 3 = 645 ^ 3 = 125

5.6

Variadic …• replaces

call_user_func_array

• Easier to read

• Works on functions

• Works with typehint

• Doesn’t work with references

function array_power($pow, ...$integers) {     foreach($integers as $i) {        print "$i ^ $pow  = ". ($i ** $pow)."\n";     }  }     array_power(3, ...range(1, 5));  array_power(3, ...[1, 2, 3, 4, 5]);  array_power(3, ...[1, 2, 3], ...[4, 5]); 

1 ^ 3 = 12 ^ 3 = 83 ^ 3 = 274 ^ 3 = 645 ^ 3 = 125

Generatorsfunction factors($limit) {     $r = array(2);     for ($i = 3; $i <= $limit; $i += 2) {         $r[] = $i;     }     return $r; }

$prime = 135; foreach (factors(sqrt($prime)) as $n) {     echo "$n ". ($prime % $n ? ' not ' : '') . " factor\n"; }

• $step big => huge memory usage

5.5

Generators• New yield keyword

• Save memory from n down to 1 value

• Good for long or infinite loops

• Search for range(), for() or loops

function factors($limit) {     yield 2;     for ($i = 3; $i <= $limit; $i += 2) {         yield $i;     } }

$prime = 135; foreach (factors(sqrt($prime)) as $n) {     echo "$n ". ($prime % $n ? ' not ' : '') . " factor\n"; }

Finallyfunction x() {        $r = new resource();         try {             $result = $r->do();         }         catch (NetworkException $e) {             unset ($r);             throw $e;         }         catch (UnexpectedException $e) {             unset ($r);             throw $e;         }         catch (DaylightSavingException $e) {             unset ($r);             throw $e;         }                  unset ($r);         return $result; }

• Clean up after exception

• What if return in try?

• Move cleaning to __destruct()?

5.5

Finally

• Clean up after exception or not

• Clean up even when return too early

function x() {        $r = new resource();         try {             $result = $r->do();         }         catch (NetworkException $e) {

       throw $e;}

        catch (UnexpectedException $e) {             throw $e;         }         catch (DaylightSavingException $e) {

// just ignore this one} finally { unset ($r) ;}

                return $result; }

Really new

Class name resolution

<?php namespace Name\Space; class ClassName {}

echo ClassName::class;

echo "\n"; ?>

• Get the full name of a class with ::class

5.5

__debugInfo()class somePasswordSafe {     private $user;     private $password;

    public function __construct($user, $password) {         $this->user = $user;         $this->password = $password;     }

    public function __debugInfo() {         return [             'user' => $this->password,             'password' => '**********',         ];     } }

print_r(new somePasswordSafe('root', 'secret'));

somePasswordSafe Object( [user] => secret [password] => **********)

5.6

use const / functionsnamespace Name\Space {     const FOO = 42;     function f() { echo __FUNCTION__."\n"; } }

namespace {     use const Name\Space\FOO;     use function Name\Space\f;

    echo FOO."\n";     f(); }

• Importing constants or functions from another namespace

• Keep things separated

• Avoid polluting global namespace

• Avoid static only classes

5.6

Constant scalar expressionsclass Version {     const MAJOR = 2;     const MIDDLE = ONE;     const MINOR = 1;     const FULL = Version::MAJOR.'.'.Version::MIDDLE.'.'.Version::MINOR.'-'.PHP_VERSION;     const SHORT = Version::MAJOR.'.'.Version::MIDDLE;     const COMPACT = Version::MAJOR.Version::MIDDLE.Version::MINOR;

    public function f($a = (MAJOR == 2) ? 3 : Version::MINOR ** 3) {         return $a;     } }

• Code automation

• Won’t accept functioncalls

• Keep it simple5.6

Foreach supports list• And any type

of keys

• Good with Iterator classes

• Not possible with Arrays

<?php

class object implements Iterator {     /.../     function key() { return array(1,2); }     function current() { return 3; }     /.../ }

$object = new object(); foreach($object as list($a, $b) = $c) {     print "$a + $b + $c = ".($a + $b + $c)."\n"; } ?>

5.5

Context changes• PHP 5.6

• Windows XP and 2003 dropped

• Support for Zend Optimiser

• PHP 5.5

• phpdbg

• Large File Upload5.5

5.6

www.slideshare.net/dseguy

damien.seguy@gmail.com