PHP 7 is (almost) here

OMG! PANIC!

Adam Harvey
@LGnome
New Relic

5.0.0 2004-07-13 5.1.0 2005-11-24 5.2.0 2006-11-02 5.3.0 2009-06-30 5.4.0 2012-03-01 5.5.0 2013-06-20 5.6.0 2014-08-28
5.0.0 2004-07-13 5.1.0 2005-11-24 5.2.0 2006-11-02 5.3.0 2009-06-30 5.4.0 2012-03-01 5.5.0 2013-06-20 5.6.0 2014-08-28

45 RFCs

9,685 commits

180 contributors

It's faster: phpdoc

It's faster: typical blog

It's faster: Drupal 8

It's smaller: Drupal 8

It's better

PHP 5.6 is EOL on
August 28, 2017

PHP < 7 is EOL on
August 28, 2017

that's in 1 year, 11 months, 4 days

Distribution packages

Ubuntu 14.04: PHP 5.5.9, supported to April 2019

RHEL 7: PHP 5.4.16, supported to June 2024

BC theory

Old & broken New & shiny Code that supports both

BC theory

Old & broken New & shiny Code that supports both

Module and library authors

Module and library users

(also known as everyone)

Testing

Tooling

php7mar

phan

Try it!

Variable handling

Indirect references


$$foo['bar']['baz']
$foo->$bar['baz']
$foo->$bar['baz']()
Foo::$bar['baz']()
            

Why?


$foo()['bar']()
$foo::$bar::$baz
Foo::bar()()
(function() { ... })()
($obj->closure)()
[$obj, 'method']()
            

$$foo['bar']['baz'];
            

in PHP 5:


${$foo['bar']['baz']};
            

$$foo['bar']['baz'];
            

in PHP 7:


($$foo)['bar']['baz'];
            

$foo->$bar['baz']
            

in PHP 5:


$foo->{$bar['baz']}
            

$foo->$bar['baz']
            

in PHP 7:


($foo->$bar)['baz']
            

Foo::$bar['baz']()
            

in PHP 5:


Foo::{$bar['baz']}()
            

Foo::$bar['baz']()
            

in PHP 7:


(Foo::$bar)['baz']()
            

What do I do?


Foo::$bar['baz']()
            

Foo::$bar['baz']()
            

Using curly braces:


Foo::{$bar['baz']}()
            

Foo::$bar['baz']()
            

Break it down:


$method = $bar['baz'];
Foo::$method();
            

What do I look for?

Tooling


git grep -E '((((::)|(->))\$[a-zA-Z_][a-zA-Z0-9_]*)+\[[^\s]+\]\())|(->\$[a-zA-Z_][a-zA-Z0-9_]*\[)|(\$\$[a-zA-Z_][a-zA-Z0-9_]*\[)'
            

or with GNU grep:


grep -E '((((::)|(->))\$[a-zA-Z_][a-zA-Z0-9_]*)+\[[^\s]+\]\(\))|(->\$[a-zA-Z_][a-zA-Z0-9_]*\[)|(\$\$[a-zA-Z_][a-zA-Z0-9_]*\[)'
            

Engine exceptions

PHP 5

E_ERROR: 182
E_RECOVERABLE_ERROR: 17
E_PARSE: 1

PHP 7

E_ERROR: 54 (-128)
E_RECOVERABLE_ERROR: 3 (-14)
E_PARSE: 0 (-1)


function square(int $n): int {
  return $n * $n;
}

square('foo');
            

Fatal error: Uncaught TypeError:
Argument 1 passed to square() must
be of the type integer, string given
            

try {
  square('foo');
} catch (TypeError $e) {
  // Recover gracefully.
  // (or show a graceful error)
}
            

PHP 5


Exception
  LogicException
  RuntimeException
            

PHP 7


Throwable
  Error
    ParseError
    TypeError
    ...
  Exception
    LogicException
    RuntimeException
            

try {
  ...
} catch (Exception $e) {
  // Catch almost everything?
}
            

try {
  ...
} catch (Throwable $e) {
  // Catch everything, but is
  // that a good idea?
}
            

What do I do?

set_exception_handler

PHP 5

Errors set_error_handler Exceptions catch (Exception $e)

PHP 7

Errors set_error_handler Exceptions Error set_exception_handler Exception catch (Exception $e)

try {
  $code = '<?php echo 01090; ?>';
  highlight_string($code);
} catch (ParseError $e) {
  ...
}
            

Today


function log_exc(Exception $e) {
  ...
}

set_exception_handler('log_exc');
            

PHP 7 only


function log_exc(Throwable $e) {
  ...
}

set_exception_handler('log_exc');
            

PHP 5 and 7


function log_exc($e) {
  ...
}

set_exception_handler('log_exc');
            

What do I look for?

git grep set_exception_handler
git grep -E 'catch\s*\(\\?Exception\s'

foreach

(there are two)


$a = [1];
foreach ($a as &$v) {
  if ($v == 1) $a[] = 2;
  var_dump($v);
}
            

PHP 5:


int(1)
            

$a = [1];
foreach ($a as &$v) {
  if ($v == 1) $a[] = 2;
  var_dump($v);
}
            

PHP 7:


int(1)
int(2)
            

reset()
key()
current()
end()
next()
prev()
pos()


$a = range(1, 3);
foreach ($a as &$v) {
  var_dump(current($a));
}
            

PHP 5:


int(2)
int(3)
bool(false)
            

$a = range(1, 3);
foreach ($a as &$v) {
  var_dump(current($a));
}
            

PHP 7:


int(1)
int(1)
int(1)
            

What do I do?

Don't use the old array iteration functions

Use array_walk or array_map


array_walk($a, function (&$v, $k) {
  ...
});
            

$a = array_map(function ($v) {
  ...
}, $a);
            

Refactor

What do I look for?


git grep -E 'foreach.*\sas\s+&'
            

Hex strings are no longer numeric


function square($n) {
  return $n * $n;
}

echo square("0x10");
            

PHP 5:


  256
            

function square($n) {
  return $n * $n;
}

echo square("0x10");
            

PHP 7:


0
            

What do I do?


$n = sscanf('0x10', '%x')[0];
echo square($n);
            

What do I look for?

¯\_(ツ)_/¯

list() fails silently with string input


$s = 'abc';
list($a, $b, $c) = $s;
var_dump($a, $b, $c);
            

PHP 5:


string(1) "a"
string(1) "b"
string(1) "c"
            

$s = 'abc';
list($a, $b, $c) = $s;
var_dump($a, $b, $c);
            

PHP 7:


NULL
NULL
NULL
            

What do I do?


list($a, $b, $c) = str_split($s);
            

What do I look for?

¯\_(ツ)_/¯

yield


yield $foo or $bar;
            

in PHP 5:


yield ($foo or $bar);
            

yield $foo or $bar;
            

in PHP 7:


(yield $foo) or $bar;
            

What do I do?

What do I look for?

Sorting


$a = ['o', 'O'];
$opt = SORT_STRING|SORT_FLAG_CASE;
sort($a, $opt);

echo json_encode($a);
            

in PHP 5:


["O","o"]
            

$a = ['o', 'O'];
$opt = SORT_STRING|SORT_FLAG_CASE;
sort($a, $opt);

echo json_encode($a);
            

in PHP 7:


["o","O"]
            

What do I do?

What do I look for?

date.timezone

PHP 5


DateTime::__construct(): 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.
...
            

PHP 7


            

bool
int
float
string
null
false
true
resource
object
mixed
numeric


$HTTP_RAW_POST_DATA
            

becomes:


file_get_contents('php://input');
            

ext/mysql is gone

(really)


function f() {
  global $$foo->bar;
}
            

Type declarations

Scalar types


function foo(int $a, string $b) {
  echo gettype($a).' '.gettype($b);
}
            

outputs:


integer string
            

Strict mode


<?php
declare(strict_types=1);
include 'foo.php'; // defines foo()
foo('0', 'foo');
            

outputs:


Fatal error: Uncaught TypeError: Argument
1 passed to foo() must be of the type
integer, string given, called in ...
            

Weak mode


<?php
include 'foo.php'; // defines foo()
foo('0', 'foo');
            

outputs:


integer string
            

Return types


function add(int $a, int $b): int {
  return $a + $b;
}
            

Return types


interface UserInterface {
  function getName(): string;
  function getEmail(): string;
  function login(string $pw): bool;
}
            

Null coalesce

Null coalesce


$a = isset($thing) ? $input : null;
$b = isset($stuff) ? $stuff : null;
$c = isset($brick) ? $brick : null;
            

Null coalesce


$a = $thing ?? null;
$b = $stuff ?? null;
$c = $brick ?? null;
            

<=>

Spaceship


usort($array, function ($a, $b) {
  return $a->id <=> $b->id;
});
            

And much, much more besides

Check the migration guide

SOON

Release candidates

Repositories

brew install php70

Ondřej Surý's DEBs

Remi Collet's RPMs

Questions?

https://lawngnome.github.io/php7-drupalcon/

http://php.net/migration70

@LGnome

Image credits

Floodgates: Doug Wertman (CC-BY 2.0)

PHP7: Vincent Pontier

Panic: wackystuff (CC-BY-SA 2.0)

Don't panic: Jim Linwood (CC-BY-SA 2.0)

Head in sand: Peter (CC-BY-SA 2.0)

Flag day: Magnus Akselvoll (CC-BY 2.0)

Dual wield: Joriel Jimenez (CC-BY 2.0)

What do?: klndonnelly (CC-BY 2.0)

Strategy: Horia Varlan (CC-BY 2.0)

The Scream: Edvard Munch (PD)

Lots: swong95765 (CC-BY 2.0)

Stars: Tom Hall (CC-BY 2.0)

Sun stone: Michael McCarty (CC-BY 2.0)

Soon cat: Guyon Morée (CC-BY 2.0)

Wrenches: LadyDragonflyCC - >;< (CC-BY 2.0)