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.
2. Towards PHP 5.5 and 5.6
• Changing version is often a big challenge
• Backward incompatibilities
• New features
• How to spot them ?
3. Speaker
• Damien Seguy
• CTO at exakat
• Phather of the plush toy
elePHPant
• Will talk on automated
code audit later
4. PHP linting
• command line : php -l filename.php
• Will only parse the code,
• not execution
• Will spot compilation problems
5.
6. PHP lint will find
• Short array syntax
• Function subscripting
• break/continue with variables
• Rare other situations
• Code that won’t compile anyway
7. Where else code will break?
• PHP running has 3 stages
• parsed
• compiled
• executed
Checked with lint
Checked code review
Checked with data and UT
8. What will change?
• Removed features
• Deprecated features
• Changed features
• New features
9. Deprecated features
• PHP 5.6
• $HTTP_RAW_POST_DATA
5.6
• Call From Incompatible Context
• iconv and mbstring directives go to default_charset
• PHP 5.5
• /e in preg_replace
• ext/mysql
5.5
• mcrypt arguments
10. 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
11. Search is your friend
• Grep, or IDE’s search function will help you
• Look for mysql_*
• $HTTP_RAW_POST_DATA
12. Error_level to E_STRICT
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
13. /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
14. 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
15. Incompatible context
$ php53 test.php
Notice: Undefined variable: this in test.php on line 3
A
<?php
class A {
function f() { echo get_class($this); }
}
A::f();
?>
5.6
$ 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
16. Search for situations
• Search for :: operator
• Get the class
• then the method
• then the static keyword
• Needs a automated auditing tool
• Code sniffer, IDE
18. 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
23. empty() upgrade
• No need
anymore to
expressions in a
variable for
empty()!
function myFunction() {
return -2 ;
}
if (empty(myFunction() + 2)) {
echo "This means 0!n";
}
Fatal error: Can't use function return value in write context in test.php on line 6
5.5
24. 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
31. 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}
32. function x() {
$r = new resource();
Finally 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
33. 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;
}
35. Class name resolution
<?php
namespace NameSpace;
class ClassName {}
echo ClassName::class;
echo "n";
?>
• Get the full name of
a class with ::class
5.5
36. class somePasswordSa_fe {_ debugInfo()
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
37. use const / functions
namespace NameSpace {
const FOO = 42;
function f() { echo __FUNCTION__."n"; }
}
namespace {
use const NameSpaceFOO;
use function NameSpacef;
echo FOO."n";
f();
}
• Importing constants
or functions from
another namespace
• Keep things
separated
• Avoid polluting
global namespace
• Avoid static only
classes
5.6
38. Constant scalar expressions
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;
public function f($a = (MAJOR == 2) ? 3 : Version::MINOR ** 3) {
return $a;
}
}
• Code automation
• Won’t accept functioncalls
• Keep it simple
5.6
39. Foreach supports list
• And any type
<?php
of keys
• Good with
Iterator
classes
• Not possible
with Arrays
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
40. Context changes
• PHP 5.6
• Windows XP and 2003 dropped
• Support for Zend Optimiser
• PHP 5.5
• phpdbg
• Large File Upload 5.5
5.6