When migrating, we often need to review old code and target only interesting issues. This session will connect the backward incompatibilities and new features to actual location in the code, relying on static analysis to process a large code base quickly. Based on the accumulated experience of the tools, we will review the issues, diagnose criticality, select the best fixes, and prioritize tasks. All tools used will be open source, and you can try them at home for more validation.
7. LIVING ON THE EDGE
http://php.net/manual/en/migration71.php
Online
UPGRADING TO PHP 7.0
Free Book, PDF
Davey Shafik is RM for PHP 7.1
Lots of blogs and articles
8. LIVING ON THE BLEEDING EDGE
https://github.com/php/php-src/blob/master/
UPGRADING
https://github.com/php/php-src/blob/master/
NEWS
https://wiki.php.net/rfc
http://bugs.php.net/
25. PHP -L WITH OTHER VERSIONS
syntax error, unexpected 'new' (T_NEW)
Assigning the return value of new by reference is
deprecated (PHP 5.6)
PHP 7 -> PHP 5.6
$o =& new Stdclass();
27. SWITCH STATEMENTS MAY ONLY CONTAIN
ONE DEFAULT CLAUSE
<?php
switch($x) {
case '1' :
break;
default :
break;
default :
break;
case '2' :
break;
}
28. SWITCH STATEMENTS MAY ONLY CONTAIN
ONE DEFAULT CLAUSE
switch($x) {
case 1 :
break;
case 0+1 :
break;
case '1' :
break;
case true :
break;
case 1.0 :
break;
case $y :
break;
}
29. DEPRECATED FEATURES
Not happening if a parent case has a __constructor()
Not happening if the class is in a namespace
Use the E_DEPRECATED error level while in DEV
Methods with the same name as their
class will not be constructors in a
future version of PHP; foo has a
deprecated constructor
36. GREP ON PHP CODE
1318 reports
doc/_ext/configext.py: parts = text.split("']['")
js/codemirror/lib/codemirror.js: var change = {from: pos, to: po
po/zh_CN.po:"example: address can be split into stree
libraries/Advisor.php: public static function splitJus
libraries/plugins/ImportCsv.php: $tmp = preg_split('/,( ?)/', $c
libraries/Config.php: // split file to lines
41. PHP7CC
PHP 7 Compatibility Checker
Authored by sstalle
https://github.com/sstalle/php7cc
PHP 5, works with "nikic/php-parser": "~1.4"
Display to stdout
42. 8.506s 3 results 27 analysis
php ~/.composer/vendor/bin/php7cc library/
File: /Users/famille/Desktop/analyze/library/Analyzer/Analyzer.php
> Line 231: Function argument(s) returned by "func_get_args" might have been modified
func_get_args();
File: /Users/famille/Desktop/analyze/library/Analyzer/Functions/MarkCallable.php
> Line 32: Nested by-reference foreach loop, make sure there is no iteration over the same array
foreach ($lists as $id => &$function) {
}
File: /Users/famille/Desktop/analyze/library/Tasks/Analyze.php
> Line 118: Possible adding to array on the last iteration of a by-reference foreach loop
$dependencies[$v] = $dep;
Checked 873 files in 8.506 seconds
43. PHAN
Static analysis for PHP
Inited by Rasmus, under work at Etsy
https://github.com/etsy/phan
PHP 7 only, with ext/ast
php ~/.composer/vendor/bin/phan -f phan.in -3
vendor -o phan.out
44.
45. 11.244s 333 results
PhanUndeclaredProperty Reference to undeclared property processed
PhanUndeclaredProperty Reference to undeclared property stdclass->results
PhanNonClassMethodCall Call to method relateTo on non-class type null
PhanStaticCallToNonStatic Static call to non-static method loadercypher::saveTokenCounts() defined at library//L
PhanAccessPropertyProtected Cannot access protected property tokenizertoken::$alternativeEnding
PhanTypeMismatchArgument Argument 1 (atom) is string but analyzerstructuresuseconstant::atomfunctionis() t
PhanUndeclaredClassMethod Call to method __construct from undeclared class reportsxmlwriter
PhanUndeclaredVariable Variable $r is undeclared
84 analysis
46. EXAKAT
Static analysis engine for PHP
https://github.com/exakat/exakat
PHP 5.2 to 7.2;
php exakat.phar project -p name
49. PHP INSPECTIONS
Static analysis engine for within the IDE
Vladimir Reznichenko
https://bitbucket.org/kalessil/phpinspectionsea
Written in Java
Runs from within PHPstorm
63. WHERE TO LOOK FOR ?
default_charset
Search for ini_set(), ini_get(), ini_get_all(), ini_restore(),
get_cfg_var()
Search in php.ini, .htaccess
Search for htmlentities(), html_entity_decode() and
htmlspecialchars()
67. Can't call dynamically!
• $func()
• call_user_func()
• array_map()
• or similar
assert() with a string
argument
extract()
compact()
get_defined_vars()
func_get_args()
func_get_arg()
func_num_args()
parse_str() with one argument
mb_parse_str() with one argument
73. INVALID OCTALS ARE INVALID
Upgraded from silent to Fatal error
PHP Parse error: Invalid numeric literal in test.php
<?php
$x = 0890;
74. MORE INVALID OCTALS IN STRINGS
<?php
var_dump("000" === "400");
PHP 7.1
https://wiki.php.net/rfc/octal.overload-checking
75. Invalid numeric are signaled
PHP 7.1
Notice: A non well formed numeric value encountered in
<?php
echo "1 monkey" + "2 bananas";
76. MORE RESERVED KEYWORDS
bool, int, float, string, null, true,
false are no more available for class / interface /
traits names
mixed, numeric, object, resource
are reserved for future use
void
is reserved in 7.1
77. MORE RELAXED KEYWORDS
Almost all PHP keywords are now authorized
inside classes
Methods and constants
Except for class, which can't be a class constant
name.
<?php
class foo {
const instanceof = 1;
function use() {
$this->while(4) + foo::instanceof;
}
}
78. STRINGS MAY BE INVALID
Upgraded to Fatal error
<?php
echo "u{1F418}n";
> php56 test.php
u{1F418}
> php70 test.php
🐘
<?php
echo "u{65B0}u{52A0}u{5761}n";
//
79. STRINGS MAY BE INVALID
Upgraded to Fatal error
<?php
echo "u{Yes}n";
PHP Parse error:
Invalid UTF-8 codepoint escape sequence
in test.php on line 3
u{
83. EXCEPTIONS
Exception is not the top exception type anymore
It is now the 'throwable' interface
Impact on Exception handler
Avoid type hinting until moved to PHP 7
Impact on Error handler
Impact on catch() clauses
93. CALL-TIME PASS-BY-REFERENCE
References are in the function signature
Deprecated warnings until PHP 7
Upgraded to Parse error in PHP 7
<?php
$a = 3;
function f($b) {
$b++;
}
f(&$a);
print $a;
?>
PHP Parse error: syntax error, unexpected '&' in …
95. EASY TO SPOT
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
100. AUTOMATICALLY FIXED
It is not safe to rely on the system's timezone
settings. You are required to use the
date.timezone setting or the
date_default_timezone_set() function. In case
you used any of those methods and you are
still getting this warning, you most likely
misspelled the timezone identifier.
105. DON'T HIDE IN PARENTHESES
<?php
function getArray() {
return [1, 2, 3];
}
function squareArray(array &$a) {
foreach ($a as &$v) {
$v **= 2;
}
}
// Generates a warning in PHP 7.
squareArray((getArray()));
?>
Parenthesis in
arguments won't
mask error
anymore
106. CONSTANT ARRAYS
Lots of properties could be turned to 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]);
}
}
116. PARAMETERS EVOLUTION
get_headers() has an extra parameter
Passing a custom stream context
getenv() doesn't need parameter
all the current environment variables will be returned
get_class() doesn't allow null anymore
122. SCALAR TYPEHINT
Whenever type is tested =>
<?php
function foo($x) {
if (!is_string($x)) {
throw new Exception('Type error while calling ' .
__FUNCTION__);
} ...
}
<?php
function foo(string $x) {
...
}
123. SCALAR TYPEHINT BACK IN 5.6
<?php
function foo(string $x) { }
foo('that');
Catchable fatal error: Argument 1 passed to
foo() must be an instance of string,
string given, called in file..
127. Minimum args in custom functions is Fatal error
scalar, array, callable, class or interfaces
void (PHP 7.1)
<?php
function foo(?int $a, float $b, float $c) {
return $a + $b + $c;
}
echo foo(2, 1);
Minimum args number Fatal error: Uncaught Error:
Too few arguments to function foo(), 2 passed in
128. HELPING AT MIGRATION
Document the evolutions between two versions
Identify anchors in the code
Link the migration to the actual code
Keywords, syntax, code structures
Suggest fallback, work-around, detection tools