last train to php 7

137
Last Train to PHP 7.1 Damien Seguy @exakat London, United Kingdom, February 2017

Upload: damien-seguy-

Post on 11-Apr-2017

211 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Last train to php 7

Last Train to PHP 7.1Damien Seguy @exakat

London, United Kingdom, February 2017

Page 2: Last train to php 7

Full ahead to PHP 7. 2

Changing version is always a big challenge

Backward incompatibilities

New features

Learn, spot, fix, repeat

01

Page 3: Last train to php 7

Speaker

Damien Seguy

CTO at exakat

Static code analysis for PHP

Retiring house for oldest elephpant

Page 4: Last train to php 7

Synopsis

What is in the next version ?

Where in my code ?

How to replace this ?

Get documentation

Find issue

Fix code

Page 5: Last train to php 7

Migration to PHP 7.2

Migration to PHP 7.0, 7.1 and 7.2 / 8.0

From PHP 5.6

No framework, no libraries

Tools, experience, discipline

Page 6: Last train to php 7

Destination

Page 7: Last train to php 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

Page 8: Last train to php 7

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/

Page 9: Last train to php 7
Page 10: Last train to php 7
Page 11: Last train to php 7
Page 12: Last train to php 7

62 opened discussions

3 opened votes

Page 13: Last train to php 7
Page 14: Last train to php 7

Which to believe

Books

PHP manual Migration, blogs

Wiki (Implemented)

NEWS

Bugs

Wiki (Future)

Yearly

Monthly

Weekly

As possible

As needed

Page 15: Last train to php 7

Where does code break?

Checked with phplint

Checked with tests

Checked code review

PHP has 3 phases

syntax

definitions

execution

Page 16: Last train to php 7

<?php

function splitNames($fullname, $fullname) {   list($first, $last) = split($fullname, ' '); } echo splitNames('John Doe');?>

Where will code break?

SyntaxDefinitionsExecution

Page 17: Last train to php 7

Tools for migration

• Your own experience with your code

• Lint

• Search

• Static analysis

• Logs

Page 18: Last train to php 7

Linting PHP 7

Page 19: Last train to php 7

PHP linting

• command line : php -l filename.php

• Spot parse errors

• Works on files only :

• For directories, see composer phplint/phplint

Page 20: Last train to php 7

PHP linting

Error messagesin PHP

0

550

1100

1650

2200

5.0 5.1 5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2

Total Distinct

Page 21: Last train to php 7

Backward unlintable code

0

1

2

3

4

5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2

Page 22: Last train to php 7

Current versions code

0

1.25

2.5

3.75

5

5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2

Page 23: Last train to php 7

Backward unlintable code

0

0.25

0.5

0.75

1

5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2

Page 24: Last train to php 7

0

1.25

2.5

3.75

5

5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2

0

1

2

3

4

5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2

0

0.75

1.5

2.25

3

5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2

0

1.75

3.5

5.25

7

5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2

0

0.25

0.5

0.75

1

5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2

Page 25: Last train to php 7

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();

Page 26: Last train to php 7

Redefinition of parameter

<?php

function foo($a, $a, $a) {   print $a."\n"; }

foo('x', 'y', 'z');

?>

Page 27: Last train to php 7

Switch statements may only contain one default clause

<?php   

switch($x) {        case '1' :             break;        default :             break;        default :             break;        case '2' :             break;    }   

Page 28: Last train to php 7

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;    }   

Page 29: Last train to php 7

Deprecated features

Not happening if a parent case has a __construct()

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

Page 30: Last train to php 7

Migration to PHP 7.2

Lint with

PHP 7.1

PHP 7.2 (or src)

PHP 5.6 (current), PHP 7.0

PHP 5.5, 5.4,… (manual)

Page 31: Last train to php 7

PHP 7 linting

Pre-commit

Use different versions

Be ruthless with unlintable files

Page 32: Last train to php 7

Where does code break?

Checked with phplint

Checked with tests

Checked code review

PHP has 3 phases

syntax

definitions

execution

Page 33: Last train to php 7

Static analysis

Page 34: Last train to php 7

Definition

Review code without executing it

Audit code by reading it

Common in C/C++, Java, Javascript

Hot subject to PHP

Page 35: Last train to php 7

GREP/SEARCH

Any searching facility

Pro : High speed, great for keyword search, universal

Cons : Little repeat value, no PHP semantics

Page 36: Last train to php 7

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(text.join("\n")), origin: "paste"}; po/zh_CN.po:"example: address can be split into street, city, country and zip."

libraries/Advisor.php: public static function splitJustification($rule) libraries/plugins/ImportCsv.php: $tmp = preg_split('/,( ?)/', $csv_columns); libraries/Config.php: // split file to lines

Page 37: Last train to php 7

Static analysis

PHP 5 / 7 Calisthenics ClearPHP

Performance

Page 38: Last train to php 7

Static analysis tools

PHP7mar

PHP7cc

Phan

Exakat

PHP inspections

Page 39: Last train to php 7

PHP7mar

PHP 7 Migration Assistant Report (MAR)

Alexia : https://github.com/Alexia/php7mar

Works with regex

Produces a .md file

Page 40: Last train to php 7

12 results

Page 41: Last train to php 7

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

Page 42: Last train to php 7

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

Page 43: Last train to php 7

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

Page 44: Last train to php 7
Page 45: Last train to php 7

11.244s 333 results

PhanUndeclaredProperty Reference to undeclared property processedPhanUndeclaredProperty Reference to undeclared property \stdclass->results

PhanNonClassMethodCall Call to method relateTo on non-class type null

PhanStaticCallToNonStatic Static call to non-static method \loader\cypher::saveTokenCounts() defined at library//Loader/Cypher.php:179PhanAccessPropertyProtected Cannot access protected property \tokenizer\token::$alternativeEnding

PhanTypeMismatchArgument Argument 1 (atom) is string but \analyzer\structures\useconstant::atomfunctionis() takes array defined at library//Analyzer/Analyzer.php:415

PhanUndeclaredClassMethod Call to method __construct from undeclared class \reports\xmlwriterPhanUndeclaredVariable Variable $r is undeclared

84 analysis

Page 46: Last train to php 7

Exakat

Static analysis engine for PHP

https://github.com/exakat/exakat

PHP 5.2 to 7.2;

php exakat.phar project -p name

Page 47: Last train to php 7

20 mins6798 results290 analysis

Page 48: Last train to php 7

Exakat

Page 49: Last train to php 7

PHP inspections

Static analysis engine for within the IDE

Vladimir Reznichenko

https://bitbucket.org/kalessil/phpinspectionsea

Written in Java

Runs from within PHPstorm

Page 50: Last train to php 7
Page 51: Last train to php 7

Write your own?

https://github.com/exakat/php-static-analysis-tools.git

PHP 7 : use ext/ast

PHP 5 :"nikic/php-parser"

Better Reflexion

Avoid regex (but it does work)

Page 52: Last train to php 7

PHP 7.2 : what changes?

Incompatible changes

New features

Features/Incompatibilities from PHP 5.6 => 7.2

Page 53: Last train to php 7

How to spot issues?

Code knowledge

lint

Grep / Search

Static analysis

Logs / error_reporting

Unit Tests

Page 54: Last train to php 7

Incompatibilities

Page 55: Last train to php 7

Incompatibilities

Removed features

Added features

Collateral damages

Page 56: Last train to php 7

Removed features

Page 57: Last train to php 7

Removed extensions

Extensions

ereg

mssql

mysql

sybase_ct

mcrypt 7.2

Page 58: Last train to php 7

Removed extensions

ext/ereg

ereg

ereg_replace

split

sql_regcase

Moved utf8_encode() and utf8_decode() to the Standard extension7.2

Page 59: Last train to php 7

Removed functions

call_user_method()

call_user_method_array()

Repleacable by $funcname

Replaced by call_user_func() and call_user_func_array()

Partially replaced by variadic

png2wbmp() and jpeg2wbmp()

Deprecated

7.2

Page 60: Last train to php 7

Removed variables

$HTTP_RAW_POST_DATA

Replace it by php://input

php://input is now reusable

Since PHP 5.5

Page 61: Last train to php 7

Removed INI

sql.safe_mode (PHP 7.2)

mbstring.internal_encoding

mbstring.http_output

mbstring.http_input

iconv.internal_encoding

iconv.input_encoding

iconv.output_encoding

default_charset}

Page 62: Last train to php 7

default_charset

htmlentities()

PHP 5.3 : ISO-8859-1

PHP 5.4 : UTF-8

PHP 5.6 : default_charset (also UTF 8)

Page 63: Last train to php 7

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()

Page 64: Last train to php 7

Preg_replace and /e

preg_replace(‘/ /e’, ‘evaled code’, $haystack)

replaced by

preg_replace_callback_array()

preg_replace(‘/  /e’, ‘evaled code’, $haystack)

preg_replace_callback_array([‘/  /’ => $closure],  $haystack) 

preg_replace_callback(‘/  /’, $closure], 

$haystack) 

Page 65: Last train to php 7

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

Page 66: Last train to php 7

preg_replace()

<?php  

$code = "abcde"; 

echo preg_replace(      array( '/a/', '/b/'),      array( 'f' , 'g'),     $code);

fgcde

Page 67: Last train to php 7

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

Page 68: Last train to php 7

Added features

Page 69: Last train to php 7

Added definitions

Functions Classes Constants5.3 40 2 805.4 0 9 785.5 12 11 575.6 1 10 107.0 10 10 417.1 9 3 307.2 4 0 15

Total 766 92 1163

Page 70: Last train to php 7

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)

Page 71: Last train to php 7

New functions

intdiv()

get_resources()

random_bytes(), random_int()

error_clear_last()

gc_mem_caches()

preg_replace_callback_array()

socket_getaddrinfo()

mb_ord, mb_scrub,

Page 72: Last train to php 7

Collaterals

Page 73: Last train to php 7

Invalid octals are invalid

Upgraded from silent to Fatal error

PHP Parse error: Invalid numeric literal in test.php

<?php 

$x = 0890;

Page 74: Last train to php 7

More invalid octals in strings

<?php  

var_dump("\000" === "\400");

https://wiki.php.net/rfc/octal.overload-checking

Page 75: Last train to php 7

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

Page 76: Last train to php 7

More relaxed keywords

<?php     class foo {    const instanceof = 1;    function use() {        $this->while(4) + foo::instanceof;    } }

Page 77: Last train to php 7

Strings may be invalid

<?php 

echo "\u{1F418}\n";

> php56 test.php \u{1F418}

> php70 test.php

🐘

<?php 

echo "\u{65B0}\u{52A0}\u{5761}\n"; //

Page 78: Last train to php 7

Strings may be invalid

<?php 

echo "\u{Yes}\n";

PHP Parse error: Invalid UTF-8 codepoint escape sequence in test.php on line 3

\u{

Page 79: Last train to php 7

Hexadecimal numeric strings

Also, -0 !!

<?php  

var_dump(1 + 0xf); var_dump(1 + "0xf");

$ php56 test.php int(16) int(16)

$ php70 test.php int(16) int(1)

Page 80: Last train to php 7

Warning for strings (7.1)

<?php  

print "2" + "4"; print "3 elephpants" + "4 dolphins"; print "2" + "d4 d";

6 7 2

Warning: A non-numeric value encountered

Page 81: Last train to php 7

Exceptions

Throwable

Exception

LogicException RuntimeException

BadFunctionCallException

BadMethodCallException

DomainExceptionInvalidArgumentException

OutOfRangeException

OutOfBoundsException

OverflowException

RangeException

Error

ParseErrorDivisionByZeroError

AssertionError

Page 82: Last train to php 7

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

Page 83: Last train to php 7

More catching exceptions

<?php

try {   eval($somePHPcode); } catch( ParseError $e) {    log($e->getMessage());   // attempt to fix this or error handling }

Page 84: Last train to php 7

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  }

Page 85: Last train to php 7

<?php 

try {    $random = random_bytes($size);   } catch( TypeError $e) {    // invalid parameter } catch( Error $e) {    // invalid length } catch( Exception $e) {    // no source of randomness } 

And more catching exceptions

Page 86: Last train to php 7

Even more catching exceptions

<?php

try {    attemptSomething(); } catch (RuntimeException $e) {   fixSomething(); } catch (InvalidArgumentException $e) {   fixSomething(); } catch (BadFunctioncallException $e) {   fixSomething(); } 

Page 87: Last train to php 7

Even more catching exceptions

Parser errors now throw a ParseError object. Error handling for eval()

<?php

try {    attemptSomething(); } catch (RuntimeException|  InvalidArgumentException|  BadFunctioncallException $e) {   fixSomething(); } 

Page 88: Last train to php 7

Even more catching exceptions

<?php

//try really hardertry {    attemptSomething(); } catch (Exception $e) {    attemptSomething(); } 

Page 89: Last train to php 7

Negative string offset (7.1)

<?php  

$string = "abcde";

print $string[-3];

print "$string[3]";

print "$string[-2]";

c

d

d

Page 90: Last train to php 7

list() with keys

Upgraded to Fatal error

<?php     $array = ['a' => 1, 'b' => 5, 'c' => 3];

// Assigns to $a, $b and $c in the same orderlist($a, $b, $c) = array_values($array); 

// Assigns to $a, $b and $c from the keys  //"a", "b" and "c", respectively  list("a" => $a, "c" => $c, "b" => $b) = $array;list("a" => $a, "b" => $b, "c" => $c) = $array;list("c" => $c, "a" => $a, "b" => $b) = $array;

Page 91: Last train to php 7

list() with keys

<?php       $array = ['b' => 5, 'a' => 1, 'c' => 3];  ksort($array); $array = array_values($array);

// Assigns to $a, $b and $c in the same order list($a, $b, $c) = $array;  

// SELECT id, * FROM users  list($userId, $name, $last) = array_values($row);  

Page 92: Last train to php 7

Short syntax for list()

<?php  

$array = ['a' => 1, 'b' => 5, 'c' => 3]; 

["a" => $b, "c" => $c, "b" => $a] = $array;   

// Works even when nested $array = [['a' => 1, 'b' => 5], ['c' => 3]]; 

[["a" => $a, "b" => $b], ["c" => $c]] = $array;

Page 93: Last train to php 7

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 …

Page 94: Last train to php 7

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 inNotice: Undefined variable: $this in A

Page 95: Last train to php 7

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

Page 96: Last train to php 7

$this is for classes<?php class bar{   function foo($this) {     static $this;     global $this;

  foreach ($a as $this) {      try {       $a = "this";        $$a = 42;      } catch (Exception $this) {}    }   unset($this);   } }

Page 97: Last train to php 7

Changed behavior

Page 98: Last train to php 7

Changed behavior

Indirect expressions

Page 99: Last train to php 7

func_get_arg()

func_get_arg() and func_get_args() now return the current argument values

<?php 

function foo($a, $b, $c) {    print_r(func_get_args());    ++$a;    print_r(func_get_args());  }  foo(1,2,3);

Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 2 [1] => 2 [2] => 3 )

Page 100: Last train to php 7

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

Page 101: Last train to php 7

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.

Page 102: Last train to php 7

New features

Page 103: Last train to php 7

New features

Breaks backward compatibility sometimes

FUD

Search for places to apply them like for incompatibilities

Page 104: Last train to php 7

New features

Fixing

Modernization

New features

Page 105: Last train to php 7

Fixing

Page 106: Last train to php 7

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

Page 107: Last train to php 7

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]);     }  }

Page 108: Last train to php 7

Constant visibility

<?php    class Version {       private const BUILD = 123;      public const VERSION = '1.2.2';  }

echo Version::UNDEFINED; echo Version::BUILD; echo Version::VERSION;

Page 109: Last train to php 7

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]);     }  }

Page 110: Last train to php 7

Modernization

Page 111: Last train to php 7

Foreach update the actual array

<?php

$array = [0]; foreach ($array as $k => &$val) {     print "$k\n";     $array[] = 1; // Only for pushing, not unshifting }

0 1 2 3 4 5 6 7 8 9 10 11

0

Page 112: Last train to php 7

Array/Object casting

<?php

$arr = [0 => 1, 1 => 2, 2 => 3];  $obj = (object)$arr; 

// PHP 7.1 echo $obj->{"0"}; 

// PHP 7.2 echo $obj->{0}; 

7.2

Page 113: Last train to php 7

Warn with COUNT()

<?php function handle_records(iterable $iterable) {     if (count($iterable) === 0) {         return handle_empty();     }       foreach ($iterable as $value) {         handle_value($value);     } }

7.2

Page 114: Last train to php 7

Closure binding

<?php class Hello {   private $hello = "Hello";

  function makeClosure() {    return function() {     echo $this->hello;   }; }

$obj = new Hello(); $closure = $obj->makeClosure(); $closure();

Page 115: Last train to php 7

Closure binding

<?php

class   {

  private $hello = " ";

}

$obj = new Hello(); $closure = $obj->makeClosure();

$nihao = new  ();

$closure2 = $closure->bindTo($nihao); $closure2();

Request the closure from the object

Page 116: Last train to php 7

Closure binding

<?php $closure = function() {     echo $this->hello; };

class   {

  private $hello = " ";

}

$nihao = new  ();

$closure->call($nihao);

Bind the object at the last moment

Page 117: Last train to php 7

session_start($options)

Very Cute <=>

Replaces a lot of code

Mainly useful for usort()

<?php

// PHP 5.6 ini_set('session.name','session'); ini_set('session.gc_probability',1); ini_set('session.gc_divisor',1); session_start();

// PHP 7.0 session_start(['name'  => 'session', 'gc_probability' => 1, 'gc_divisor'  => 1 ] );

Page 118: Last train to php 7

dirname() second argument

<?php   $path = '/a/b/c/d/e/f';

// PHP 5.6 $root = dirname(dirname(dirname($x)));

// PHP 7 $root = dirname($path, 3); ?>

Page 119: Last train to php 7

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

Page 120: Last train to php 7

Really new

Page 121: Last train to php 7

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';

?>

Page 122: Last train to php 7

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

Page 123: Last train to php 7

Generators delegation

New yield keyword

Save memory from

n down to 1 value

Good for long or infinite loops

Search for range(), for() or loops

<?php   function factors($limit) {      yield 2;      yield 3;

    yield from primeTill1000();

    for ($i = 1001; $i <= $limit; $i += 2) {          yield $i;      } } 

$prime = 1357;  foreach (factors(sqrt($prime)) as $n) {      echo "$n ". ($prime % $n ? ' not ' : '') . " factor\n";  }

Page 124: Last train to php 7

Generators returns<?php    function factors($limit) {       return 'first';     yield 2;       return 'second';     yield 3;      return 'third';     yield 5;  }   $gen = factors(sqrt($prime)); foreach ($gen as $n) {       echo "$n\n";     if ($n == 3) {break 1;} } print $gen->getReturn(); // second

Generators returns

The last return is accessible

The generator returns the final state

Page 125: Last train to php 7

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) { ... }

Page 126: Last train to php 7

Scalar typehint back in 5.6

Whenever type is tested =>

<?php   

function foo(string $x) { } foo('that');

Catchable fatal error: Argument 1 passed tofoo() must be an instance of string, string given, called in file..

Page 127: Last train to php 7

Various scalar typehint

int, float

string, bool

true, false, null

void (PHP 7.1)

mixed, object, resource, numeric (RFU)

<?php

function foo(?int $a, float $b, float $c) : ?int {     return $a + $b + $c; }

echo foo(null, 2,   1);    // 4 echo foo(1.2, 2, 1);     // 4 echo foo(1, 2.2, 1);     // 4 echo foo(1, 2.7, 1.4);   // 5

Page 128: Last train to php 7

Option for strict typing

<?php // Enable strict types declare(strict_types=1);

declare(encoding='ISO-8859-1'); declare(ticks=1);

namespace Foo\Bar; foo('that'); 

Page 129: Last train to php 7

Return type hint

<?php

function getData($login) : user {    if (userExists($login)) {      return userDetails($login);    } else {      return null;   } }

Page 130: Last train to php 7

Minimum args in custom functions is Fatal error

<?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

Page 131: Last train to php 7

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

Page 132: Last train to php 7

Helping at migration

Backward incompatibilities

Removed / renamed features

Collaterals

Changed behaviors

Page 133: Last train to php 7

Helping at migration

New features

Fixing

Totally new

Spot previous work-arounds

Page 134: Last train to php 7
Page 135: Last train to php 7

Summary

Check the manuals

PHP lint is your friend

Search in the code

Use static analysis tools

Page 136: Last train to php 7

Thank you!Damien Seguy @exakat [email protected]

https://www.exakat.io/

https://joind.in/event/php-uk-2017/schedule/list

Page 137: Last train to php 7

The end