preparing code for php 7 workshop

128
Preparing for PHP 7.1 workshop Damien Seguy @exakat Warsaw, Poland, October 2016

Upload: damien-seguy-

Post on 14-Apr-2017

311 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Preparing code for Php 7 workshop

Preparing for PHP 7.1 workshop

Damien Seguy @exakat Warsaw, Poland, October 2016

Page 2: Preparing code for Php 7 workshop

Full ahead to PHP 7. 1

• Changing version is always a big challenge

• Backward incompatibilities

• New features

• Learn, spot, fix, repeat

0

Page 3: Preparing code for Php 7 workshop

Speaker

• Damien Seguy

• CTO at exakat

• Static code analysis for PHP

Page 4: Preparing code for Php 7 workshop

Synopsis

• What is in the next version ?

• Where in my code ?

• How to replace this ?

• Get documentation

• Find issue

• Fix code

Page 5: Preparing code for Php 7 workshop

Migration to PHP 7.1

• 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: Preparing code for Php 7 workshop

Destination

Page 7: Preparing code for Php 7 workshop

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

Page 8: Preparing code for Php 7 workshop

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: Preparing code for Php 7 workshop
Page 10: Preparing code for Php 7 workshop
Page 11: Preparing code for Php 7 workshop
Page 12: Preparing code for Php 7 workshop
Page 13: Preparing code for Php 7 workshop
Page 14: Preparing code for Php 7 workshop

• PHP has 3 phases

• syntax

• definitions

• execution

Where does code break?

Checked with phplint

Checked with tests

Checked code review

Page 15: Preparing code for Php 7 workshop

<?php

function splitNames($fullname, $fullname) {    list($first, $last) = split($fullname, ' '); }

?>

Where will code break?

SyntaxDefinitionsExecution

Page 16: Preparing code for Php 7 workshop

Tools for migration

• Your own experience with your code

• Lint

• Search

• Static analysis

• Logs

Page 17: Preparing code for Php 7 workshop

Linting PHP 7

Page 18: Preparing code for Php 7 workshop

PHP linting

• command line : php -l filename.php

• Spot parse errors

• Works on files only :

• For directories, see composer phplint/phplint

Page 19: Preparing code for Php 7 workshop

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 20: Preparing code for Php 7 workshop

Backward unlintable code

Page 21: Preparing code for Php 7 workshop

Code focused on current versions

Page 22: Preparing code for Php 7 workshop

Backward unlintable code

Page 23: Preparing code for Php 7 workshop

Redefinition of parameter

<?php

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

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

?>

Page 24: Preparing code for Php 7 workshop

Switch statements only contain one default clause

<?php   

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

Page 25: Preparing code for Php 7 workshop

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 26: Preparing code for Php 7 workshop

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

Page 27: Preparing code for Php 7 workshop

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 28: Preparing code for Php 7 workshop

Migration to PHP 7.1

• Lint with

• PHP 7.1

• PHP 7.2 (or src)

• PHP 5.6 (current), PHP 7.0

• PHP 5.5, 5.4,… (manual)

Page 29: Preparing code for Php 7 workshop

PHP 7 linting

• Pre-commit

• Use different versions

• Be ruthless with unlintable files

Page 30: Preparing code for Php 7 workshop

• PHP has 3 phases

• syntax

• definitions

• execution

Where does code break?

Checked with phplint

Checked with tests

Checked code review

Page 31: Preparing code for Php 7 workshop

Static analysis

Page 32: Preparing code for Php 7 workshop

Presentation

• Review code without executing it

• Common in C/C++, Java, Javascript

• Hot subject coming to PHP

Page 33: Preparing code for Php 7 workshop

GREP/SEARCH

• Any searching facility

• Pro : High speed, great for keyword search, universal

• Cons : Little repeat value, no PHP semantics

Page 34: Preparing code for Php 7 workshop

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 35: Preparing code for Php 7 workshop

Static analysis

PHP 5 / 7 Calisthenics ClearPHP

Performance

Page 36: Preparing code for Php 7 workshop

Static analysis tools

PHP7mar

PHP7cc

Phan

Exakat

PHP inspections

Page 37: Preparing code for Php 7 workshop

PHP7mar

• PHP 7 Migration Assistant Report (MAR)

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

• Works with regex

• Produces a .md file

Page 38: Preparing code for Php 7 workshop

12 results

Page 39: Preparing code for Php 7 workshop

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 40: Preparing code for Php 7 workshop

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 41: Preparing code for Php 7 workshop

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 42: Preparing code for Php 7 workshop
Page 43: Preparing code for Php 7 workshop

11.244s 333 resultsPhanUndeclaredProperty 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 44: Preparing code for Php 7 workshop

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

Page 45: Preparing code for Php 7 workshop

20 mins6798 results260 analysis

Page 46: Preparing code for Php 7 workshop

PHP inspections

Static analysis engine for within the IDE

Vladimir Reznichenko

https://bitbucket.org/kalessil/phpinspectionsea

Written in Java

Runs from within PHPstorm

Page 47: Preparing code for Php 7 workshop
Page 48: Preparing code for Php 7 workshop

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)

Page 49: Preparing code for Php 7 workshop

PHP 7 : what changes?

• Incompatible changes

• New features

• Features/Incompatibilities from PHP 5.6 => 7.2

Page 50: Preparing code for Php 7 workshop

How to spot issues?

• Code knowledge

• lint

• Grep / Search

• Static analysis

• Logs / error_reporting

• Unit Tests

What to replace them with ?

Page 51: Preparing code for Php 7 workshop

Incompatibilities

Page 52: Preparing code for Php 7 workshop

Incompatibilities

• Removed features

• Added features

• Collateral damages

Page 53: Preparing code for Php 7 workshop

Removed features

Page 54: Preparing code for Php 7 workshop

Removed extensions

• Extensions

• ereg

• mssql

• mysql

• sybase_ct

• mcrypt (7.1)

Page 55: Preparing code for Php 7 workshop

Removed extensions

• ext/ereg

• ereg

• ereg_replace

• split

• sql_regcase

Page 56: Preparing code for Php 7 workshop

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

Page 57: Preparing code for Php 7 workshop

Removed variables

• $HTTP_RAW_POST_DATA

• Replace it by php://input

• php://input is now reusable

• Since PHP 5.5

Page 58: Preparing code for Php 7 workshop

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 59: Preparing code for Php 7 workshop

default_charset

• htmlentities()

• PHP 5.3 : ISO-8859-1

• PHP 5.4 : UTF-8

• PHP 5.6 : default_charset (also UTF 8)

Page 60: Preparing code for Php 7 workshop

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 61: Preparing code for Php 7 workshop

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 62: Preparing code for Php 7 workshop

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 63: Preparing code for Php 7 workshop

preg_replace()

<?php  

$code = "abcde"; 

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

fgcde

Page 64: Preparing code for Php 7 workshop

mb_eregi?_replace also drops /e in 7.2

<?php  

$code = "abcde"; 

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

fgcde

Page 65: Preparing code for Php 7 workshop

Can't call dynamically!

• $func() • call_user_func() • array_map() • or similar

• 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 • assert() with a string argument

Page 66: Preparing code for Php 7 workshop

Added features

Page 67: Preparing code for Php 7 workshop

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 7 2 157.2 0 0 0

Total 766 92 1163

Page 68: Preparing code for Php 7 workshop

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 69: Preparing code for Php 7 workshop

New functions

• intdiv()

• get_resources()

• random_bytes(), random_int()

• error_clear_last()

• gc_mem_caches()

• preg_replace_callback_array()

Page 70: Preparing code for Php 7 workshop

Collaterals

Page 71: Preparing code for Php 7 workshop

Invalid octals are invalid

• Upgraded from silent to Fatal error

PHP Parse error: Invalid numeric literal in test.php

<?php 

$x = 0890;

Page 72: Preparing code for Php 7 workshop

More invalid octals in strings

<?php  

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

• PHP 7.1

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

Page 73: Preparing code for Php 7 workshop

Invalid numeric are signaledPHP 7.1

Notice: A non well formed numeric value encountered in

<?php

echo "1 monkey" + "2 bananas";

Page 74: Preparing code for Php 7 workshop

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 75: Preparing code for Php 7 workshop

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

Page 76: Preparing code for Php 7 workshop

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

Page 77: Preparing code for Php 7 workshop

Strings may be invalid

• Upgraded to Fatal error

<?php 

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

> php56 test.php \u{1F418}

> php70 test.php

🐘

<?php 

echo "ni\u{119} m\u{f3}wi\u{119} p\u{f3} po\u{142}\u{15b}";

//nię mówię pó połśku

Page 78: Preparing code for Php 7 workshop

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{

Page 79: Preparing code for Php 7 workshop

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: Preparing code for Php 7 workshop

Warning for strings (7.1)

Upgraded to Fatal error

<?php  

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

6 7 2

Warning: A non-numeric value encountered

Page 81: Preparing code for Php 7 workshop

Exceptions

• Upgraded to Fatal errorThrowable

Exception

LogicException RuntimeException

BadFunctionCallException

BadMethodCallException

DomainExceptionInvalidArgumentException

OutOfRangeException

OutOfBoundsException

OverflowException

RangeException

Error

ParseErrorDivisionByZeroError

AssertionError

Page 82: Preparing code for Php 7 workshop

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: Preparing code for Php 7 workshop

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 }

Page 84: Preparing code for Php 7 workshop

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: Preparing code for Php 7 workshop

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 } 

Page 86: Preparing code for Php 7 workshop

Even more catching exceptions

<?php

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

Page 87: Preparing code for Php 7 workshop

Even more catching exceptionsFederate error catching in catch clause

<?php

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

Page 88: Preparing code for Php 7 workshop

Even more catching exceptions

<?php

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

Page 89: Preparing code for Php 7 workshop

Negative string offset (7.1)

• Upgraded to Fatal error<?php  

$string = "abcde";

print $string[-3];

print "$string[3]";

print "$string[-2]";

c

d

Parse error: syntax error, unexpected '-', expecting identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING)

Page 90: Preparing code for Php 7 workshop

PHP 7.1 : list() with keys =>

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

// Assigns to $a, $b and $c in the same orderlist($a, $b, $c) = $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: Preparing code for Php 7 workshop

Short syntax for list()

<?php 

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

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

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

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

Page 92: Preparing code for Php 7 workshop

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 93: Preparing code for Php 7 workshop

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 94: Preparing code for Php 7 workshop

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

Page 95: Preparing code for Php 7 workshop

Changed behavior

Page 96: Preparing code for Php 7 workshop

Changed behavior

• Indirect expressions

Page 97: Preparing code for Php 7 workshop

func_get_arg()

• func_get_arg() and func_get_args() now return 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 98: Preparing code for Php 7 workshop

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 99: Preparing code for Php 7 workshop

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 100: Preparing code for Php 7 workshop

New features

Page 101: Preparing code for Php 7 workshop

New features

• Breaks backward compatibility sometimes

• FUD

• Search for places to apply them like for incompatibilities

Page 102: Preparing code for Php 7 workshop

New features

• Fixing

• Modernization

• New features

Page 103: Preparing code for Php 7 workshop

Fixing

Page 104: Preparing code for Php 7 workshop

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 105: Preparing code for Php 7 workshop

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

Page 106: Preparing code for Php 7 workshop

Modernization

Page 107: Preparing code for Php 7 workshop

Foreach update the actual array

<?php

$array = [0]; foreach ($array as $k => &$val) {     print "$k\n";     $array[] = 1; } ?>

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

0

PHP 5 PHP 7

Page 108: Preparing code for Php 7 workshop

Closure binding

• Code automation

• Keep it simple

• Won’t accept functioncalls

• Won't accept variables

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

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

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

Page 109: Preparing code for Php 7 workshop

Closure binding

• Code automation

• Keep it simple

• Won’t accept functioncalls

• Won't accept variables

<?php

class   {

  private $hello = " ";

}

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

$nihao = new  ();

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

Page 110: Preparing code for Php 7 workshop

Closure binding

• Code automation

• Keep it simple

• Won’t accept functioncalls

• Won't accept variables

<?php

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

class   {

  private $hello = " ";

}

$nihao = new  ();

$closure->call($nihao);

Page 111: Preparing code for Php 7 workshop

session_start($options)

<?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 112: Preparing code for Php 7 workshop

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 113: Preparing code for Php 7 workshop

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

Page 114: Preparing code for Php 7 workshop

Really new

Page 115: Preparing code for Php 7 workshop

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 116: Preparing code for Php 7 workshop

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 117: Preparing code for Php 7 workshop

Generators delegation

<?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 118: Preparing code for Php 7 workshop

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 119: Preparing code for Php 7 workshop

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 120: Preparing code for Php 7 workshop

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 121: Preparing code for Php 7 workshop

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 122: Preparing code for Php 7 workshop

Return type hint

<?php

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

• scalar, array, callable, class or interfaces

void (PHP 7.1)

Page 123: Preparing code for Php 7 workshop

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 124: Preparing code for Php 7 workshop

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

Page 125: Preparing code for Php 7 workshop

Omitted

• Assertions

• Grouped assertions

• opening tags that were dropped

Page 126: Preparing code for Php 7 workshop

Summary

• Check the manuals

• PHP lint is your friend

• Search in the code

• Use static analysis tools

Page 127: Preparing code for Php 7 workshop

Thank you! Damien Seguy @exakat [email protected] https://www.exakat.io/

Page 128: Preparing code for Php 7 workshop

The end