Upload
damien-seguy-
View
439
Download
1
Tags:
Embed Size (px)
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.
Citation preview
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