Upload
damien-seguy-
View
415
Download
3
Embed Size (px)
Citation preview
MIGRATING TO NEW PHP VERSIONS
Washington DC, USA
TOWARDS PHP 70
Changing version is always a big challenge
Backward incompatibilities
New features
How to spot them ?
SPEAKER
Damien Seguy
CTO at exakat
Static code analysis for PHP
PHP LINTING
command line : php -l filename.php
Will only parse the code,
not execution
Will spot compilation problems
PHP -L WILL FIND
Short array syntax
Function subscripting
Code that won’t compile anyway
PHP 7 LINTING
Methods with the same name as their class will not be constructors in a future version of PHP
Cannot use a\b\c\Int as Int because 'Int' is a special class name
Switch statements may only contain one default clause
Redefinition of parameter $%s
syntax error, unexpected 'new' (T_NEW)
WHERE ELSE CODE WILL BREAK?
PHP running has 3 stages
parsed
compiled
executed
Checked with lint
Checked with data and UT
Checked code review
GETTING READY
http://php.net/manual/en/migration70.php
UPGRADING TO PHP 7, Davey Shafik
https://github.com/php/php-src/blob/master/UPGRADING
https://github.com/php/php-src/blob/master/NEWS
get_headers() has an extra parameter in 7.1
WHAT WILL CHANGE?
Incompatible changes
Deprecated changes
Changed features
New features
INCOMPATIBILITIES
Features that were dropped
Features that were added
ADDED STRUCTURES
Functions Classes Constants
5.3 40 2 80
5.4 0 9 78
5.5 12 11 57
5.6 1 10 10
7.0 10 10 41
Total 1293 153 1149
NAME IMPACT
get_resources(), intdiv()
PREG_JIT_STACKLIMIT_ERROR
Error, Date
REMOVED FEATURES
$HTTP_RAW_POST_DATA
Replace it by php://input
php://input is now reusable
REMOVED FEATURES
ext/mysql
Look for mysql_* functions
Probably in Db/Adapter
ext/ereg
ereg, ereg_replace, split, sql_regcase
USORT<?php
$array = array( 'foo', 'bar', 'php' );
usort($array, function($a, $b) { return 0; } );
print_r($array);
Array ( [0] => php [1] => bar [2] => foo )
Array ( [0] => foo [1] => bar [2] => php )
PHP 5
PHP 7
WHERE TO LOOK FOR ?
Find the name of the structure (function name…)
Grep, or IDE’s search function will help you
$HTTP_RAW_POST_DATA
Look for mysql_*
Look ereg, split, usort
PREG_REPLACE AND /E
preg_replace(‘/ /e’, ‘evaled code’, $haystack)
replaced preg_replace_callback(‘/ /‘, closure, $haystack)
preg_replace_callback_array()
PREG_REPLACE_CALLBACK_ARRAY<?php
$code = "abbbb";
$spec = 'c';
echo preg_replace_callback_array( array( "/a/" => function($matches) { return strtoupper($matches[0]); }, "/b/" => function($matches) use ($spec) { static $i = 0; $i++;
return "B$i$spec"; } ), $code);
AB1cB2cB3cB4c
DEFAULT_CHARSET
iconv.input_encoding
iconv.output_encoding
iconv.internal_encoding
mbstring.http_input
mbstring.http_output
mbstring.internal_encoding
default_charset
DEFAULT_CHARSET
htmlentities()
PHP 5.3 : ISO-8859-1
PHP 5.4 : UTF-8
PHP 5.6 : default_charset (also UTF 8)
WHERE TO LOOK FOR ?
preg_replace
Search for preg_replace function calls
Refine with /e, multiples calls
default_charset
Search for ini_set, ini_get, ini_get_all, ini_restore, get_cfg_var
Seach in php.ini, .htaccess
Search for htmlentities(), html_entity_decode() and htmlspecialchars()
DEPRECATED FEATURES
Methods with the same name as their class will not be constructors in a future version of PHP; foo has a deprecated constructor
Not happening if a parent case has a __constructor()
Not happening if the class is in a namespace
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP;
foo has a deprecated constructor
PHP 4 CONSTRUCTORS
Use the E_DEPRECATED error level while in DEV Check the logs
CALL-TIME PASS-BY-REFERENCE
References are in the function signature
Deprecated warnings until PHP 7
A nice Parse error in PHP 7
<?php
$a = 3;
function f($b) { $b++; }
f(&$a); print $a; ?>
PHP Parse error: syntax error, unexpected '&' in
WHERE TO LOOK FOR ?
Use error level
Set error_level to maximum
Spot errors in the log
Refine
Great to reduce log size
INCOMPATIBLE CONTEXT
<?php class A { function f() { echo get_class($this); } } A::f(); ?>
Notice: Undefined variable: this in A
Deprecated: Non-static method A::f() should not be called statically in Notice: Undefined variable: this in A
EASY TO SPOT
Use the E_DEPRECATED or strict while in DEV
Strict Standards: Non-static method A::f() should not be called statically in test.php on line 6
Deprecated: Non-static method A::f() should not be called statically in test.php on line 6
CHANGED BEHAVIOR
Indirect expressions
SEARCH FOR SITUATIONS
Search for :: operator
Get the class
then the method
then the static keyword
Needs a automated auditing tool
Exakat, Code sniffer, IDE
STATIC ANALYZIS
PHP 5, PHP 7 Psr-4 ClearPHP Performance
SUMMARY
PHP lint is your friend
Search in the code
With Grep
Directly, or indirectly
With the logs
Use static analysis tools
NEW FEATURES
They require willpower
Breaks backward compatibility
FUD
Search for places to apply them like for incompatibilities
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
5.5
<?php function myFunction() { return -2 ; }
if (empty(myFunction() + 2)) { echo "This means 0!\n"; } ?>
MODERNIZATION
SPACESHIP OPERATOR
Replaces a lot of code
Mainly useful for usort and co
Very Cute
<?php
// PHP 5.6 if ($a > $b) { echo 1; } elseif ($a < $b) { echo -1; } else { echo 0; }
// PHP 7.0 echo $a <=> $b; // 0
NULL-COALESCE
Shorter way to give a test for NULL and failover
<?php
// PHP 5.6 $x = $_GET['x'] === null ? 'default' : $_GET['x'];
// PHP 7.0 $x = $_GET['x'] ?? 'default';
?>
DIRNAME() SECOND ARG
<?php $path = '/a/b/c/d/e/f';
// PHP 5.6 $root = dirname(dirname(dirname($x)));
// PHP 7 $root = dirname($path, 3); ?>
… VARIADIC
replaces func_get_args()
Easier to read
<?php
// PHP 5.5 function array_power($pow) { $integers = func_get_args(); array_unshift($integers);
foreach($integers as $i) { print "$i ^ $pow = ". pow($i, $pow)."\n"; } } // PHP 7.0 function array_power($pow, ...$integers) { foreach($integers as $i) { print "$i ^ $pow = ". ($i ** $pow)."\n"; } }
5.6
VARIADIC …
<?php
// Avoid! foreach($source as $x) { if (is_array($x)) $final = array_merge($final, $x); } }
VARIADIC …<?php
$collection = []; foreach($source as $x) { if (is_array($x)) $collection[] = $x; } }
// PHP 5.5 $final = call_user_func_array('array_merge', $collection); // PHP 7.0 $final = array_merge(...$collection);
REALLY NEW
SCALAR TYPE TYPEHINT
Whenever type is tested
<?php
function foo(string $x) { if (!is_string($x)) { throw new Exception('Type error while calling '.__FUNCTION__); } }
GENERATORS<?php function factors($limit) { yield 2; yield 3;
yield from prime_database();
for ($i = 1001; $i <= $limit; $i += 2) { yield $i; } }
$prime = 1357; foreach (factors(sqrt($prime)) as $n) { echo "$n ". ($prime % $n ? ' not ' : '') . " factor\n"; }
GENERATORS
New yield keyword
Save memory from
n down to 1 value
Good for long or infinite loops
Search for range(), for() or loops
literals, database result sets, file lines
<?php class 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; const AN_ARRAY = [1,2,3,4];
public function f($a = (MAJOR == 2) ? 3 : Version::MINOR ** 3) { return $a; } }
CONSTANT SCALAR EXPRESSIONS
Code automation
Keep it simple
Won’t accept functioncalls
Won't accept variables
CONSTANT SCALAR EXPRESSIONS
Lots of properties should be constants
<?php class Version { const SUPPORTED = ['1.0', '1.1', '2.0', '2.1']; private $an_array = [1,2,3,4];
public function isSupported($x) { return isset(Version::SUPPORTED[$x]); } }
SUMMARY
Check the manuals
PHP lint is your friend
Search in the code
Use static analysis tools