Migration is one of the most scary migration: it requires sharp tools to find incompatibilities in the code, and even more know-how to adapt it to the future environnement. During this workshop, we'll work on your code, systematically targeting incompatibilities and scouting for opportunities to use the new features. Along the way, we'll get right of dead code, slow routines and instable functions. After querying the code, we'll discuss the various solutions and learn even more about using PHP for the best.
7. Living on the edge
• http://php.net/manual/en/migration70.php
• Online
• UPGRADING TO PHP 7
• 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/
9.
10.
11.
12.
13.
14. • PHP has 3 phases
• syntax
• definitions
• execution
Where does code break?
Checked with phplint
Checked with tests
Checked code review
24. Switch statements only contain one default clause
<?php
switch($x) {
case '1' :
break;
default :
break;
default :
break;
case '2' :
break;
}
25. 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;
}
26. 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
27. 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();
32. Presentation
• Review code without executing it
• Common in C/C++, Java, Javascript
• Hot subject coming to PHP
33. GREP/SEARCH
• Any searching facility
• Pro : High speed, great for keyword search, universal
• Cons : Little repeat value, no PHP semantics
34. Grep on PHP code
1318 reports
doc/_ext/configext.py: parts = text.split("']['")
js/codemirror/lib/codemirror.js: var change = {from: pos, to: pos, text: splitLines(t
po/zh_CN.po:"example: address can be split into street, city, country and
libraries/Advisor.php: public static function splitJustification($rule)
libraries/plugins/ImportCsv.php: $tmp = preg_split('/,( ?)/', $csv_columns);
libraries/Config.php: // split file to lines
39. 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
40. 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
41. 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
42.
43. 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
44. Exakat
• Static analysis engine for PHP
• https://github.com/exakat/exakat
• PHP 5.2 to 7.2; Uses Neo4j 2.3 and Gremlin 3
• php exakat.phar project -p name
46. PHP inspections
Static analysis engine for within the IDE
Vladimir Reznichenko
https://bitbucket.org/kalessil/phpinspectionsea
Written in Java
Runs from within PHPstorm
47.
48. Write your own?
• https://github.com/exakat/php-static-analysis-tools.git
• PHP 7 : use ext/ast
• PHP 5 :"nikic/php-parser"
• Avoid regex (but it does work)
49. PHP 7 : what changes?
• Incompatible changes
• New features
• Features/Incompatibilities from PHP 5.6 => 7.2
50. How to spot issues?
• Code knowledge
• lint
• Grep / Search
• Static analysis
• Logs / error_reporting
• Unit Tests
What to replace
them with ?
60. 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()
68. Name impact
• get_resources(), intdiv(), is_iterable(), mb_scrub()
• PREG_JIT_STACKLIMIT_ERROR
• class Date (from PHP 5.1)
• Error (new class in PHP 7)
71. Invalid octals are invalid
• Upgraded from silent to Fatal error
PHP Parse error: Invalid numeric literal in test.php
<?php
$x = 0890;
72. More invalid octals in strings
<?php
var_dump("000" === "400");
• PHP 7.1
https://wiki.php.net/rfc/octal.overload-checking
73. Invalid numeric are signaled
PHP 7.1
Notice: A non well formed numeric value encountered in
<?php
echo "1 monkey" + "2 bananas";
74. 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
75. 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;
}
}
76. More strict keywords
• $this is not available anymore
• Not as argument
• Not as variable
• Not as global
• Not as static
• Not as property
• Not as reference
• Not via extract()
<?php
function foo($this) {
echo $this;
}
77. Strings may be invalid
• Upgraded to Fatal error
<?php
echo "u{1F418}n";
> php56 test.php
u{1F418}
> php70 test.php
🐘
<?php
echo "niu{119} mu{f3}wiu{119} pu{f3} po
u{142}u{15b}";
//nię mówię pó połśku
78. 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{
82. 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
83. More catching exceptions
• Parser errors now throw a ParseError object. Error
handling for eval()
<?php
try {
eval($somePHPcode);
} catch( ParseError $e) {
log($e->getMessage());
// attempt to fix this or error handling
}
84. More catching exceptions
Parser errors now throw a ParseError object. Error
handling for eval()
<?php
try {
$file = new finfo(FILEINFO_NONE,$magic_file);
} catch( ParseError $e) {
log($e->getMessage());
// attempt to fix this or error handling
}
85. And more catching exceptions
Parser errors now throw a ParseError object. Error
handling for eval()
<?php
try {
$random = random_bytes(10);
} catch( TypeError $e) {
// invalid parameter
} catch( Error $e) {
// invalid length
} catch( Exception $e) {
// no source of randomness
}
94. 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
99. 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.
104. 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
105. Constant arrays
• 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]);
}
}
113. Parameters evolution (7.1)
• get_headers() has an extra parameter
• Passing a custom stream context
• getenv() doesn't need parameter
• all the current environment variables will be returned
115. 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';
?>
116. Spaceship operator
• Very Cute <=>
• Replaces a lot of code
• Mainly useful for usort()
<?php
// PHP 5.6
if ($a > $b) {
echo 1;
} elseif ($a < $b) {
echo -1;
} else {
echo 0;
}
// PHP 7.0
echo $a <=> $b; // 0
119. 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) {
...
}
120. Scalar typehint back in 5.6
• Whenever type is tested =>
<?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..
124. 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