Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[PHP South Africa 2015] What To Expect When You...

[PHP South Africa 2015] What To Expect When You're Expecting: PHP 7

PHP 7 is coming, and with it will come new features, backwards compatibility breaks, and huge performance gains.

This talk will get you prepared for all the changes in this upcoming release and offer practical advice you can implement now to ensure you code still works come upgrade time.

Davey Shafik

October 02, 2015
Tweet

More Decks by Davey Shafik

Other Decks in Programming

Transcript

  1. W H AT T O E X P E C

    T W H E N Y O U ’ R E E X P E C T I N G : P H P 7 CC-BY-ND: Greg
  2. D AV E Y S H A F I K

    • Author of Zend PHP 5 Certification Study Guide, Sitepoints PHP Anthology: 101 Essential Tips, Tricks & Hacks & PHP Master: Write Cutting Edge Code • A contributor to Zend Framework 1 & 2, phpdoc, & PHP internals • Original creator of PHAR/PHP_Archive • @dshafik
  3. h t t p : / / d e v

    e l o p e r. a k a m a i . c o m
  4. Mar 15
 2015 Jun 15
 2015 Oct 15 2015 Feature

    Freeze Finalize Implementation Release Candidates PHP 7.0 Final Alphas/Betas
  5. W H AT H A P P E N E

    D T O 6 ? var_dump(0x0+1+5);
  6. W H AT H A P P E N E

    D T O 6 ? var_dump(0x0+1+5); => ints(7)
  7. W H AT H A P P E N E

    D T O 6 ? var_dump(0x0+1+5); => ints(7) •(for PHP 5.3.0 - 5.3.10)
  8. R E M O VA L O F D E

    P R E C AT E D F E AT U R E S CC-BY-SA: Shannon Kringen
  9. A LT E R N AT I V E P

    H P TA G S • ASP Tags: <%, <%= and %> • Script Tags: <script language="php"></script>
  10. P O S I X C O M PAT I

    B L E R E G U L A R E X P R E S S I O N S CC-BY-SA: InSapphoWeTrust
  11. P O S I X C O M PAT I

    B L E R E G U L A R E X P R E S S I O N S • All ereg_* functions removed • Use preg_* instead
  12. E X T / M Y S Q L •

    All mysql_* functions removed • Use mysqli_* for direct migration • Use mysqli OO or PDO instead
  13. M U LT I P L E D E FA

    U LT C A S E S I N S W I T C H Copyright © Microsoft
  14. M U LT I P L E D E FA

    U LT C A S E S I N S W I T C H <?php switch ($expr) { default: echo "Hello World"; break; default: // only this one would execute echo "Goodbye Moon!"; break; } Fatal error: Switch statements may only contain one default clause
  15. P E R F O R M A N C

    E CC-BY-SA: Martin Fisch
  16. P E R F O R M A N C

    E ( B E N C H M A R K . P H P ) 0 3,000,000,000 6,000,000,000 9,000,000,000 12,000,000,000 20.01.2014 18.02.2014 21.02.2014 28.02.2014 07.03.2014 14.03.2014 21.03.2014 28.03.2014 04.04.2014 11.04.2014 18.04.2014 25.04.2014 05.05.2014 18.05.2014 26.05.2014 03.06.2014 09.06.2014 30.06.2014 09.07.2014 14.07.2014 15.08.2014 02.09.2014 07.10.2014 21.11.2014 31.12.2014 19.03.2015 30.04.2015 Time (sec) Operations 0.777 0.837 1.159 1.201 1.219 1.302 1.35 1.407 1.367 1.412 1.497 1.492 1.432 1.49 1.414 1.492 1.515 1.559 1.571 1.821 1.941 1.941 1.906 1.941 1.83 1.898 2.115 2.115 1.898 1.83 1.9411.9061.9411.941 1.821 1.5711.559 1.5151.492 1.414 1.49 1.432 1.4921.497 1.412 1.3671.407 1.35 1.302 1.2191.201 1.159 0.837 0.777
  17. P E R F O R M A N C

    E ( W O R D P R E S S H O M E PA G E ) 0 2,500,000,000 5,000,000,000 7,500,000,000 10,000,000,000 20.01.2014 04.04.2014 11.04.2014 18.04.2014 25.04.2014 05.05.2014 18.05.2014 26.05.2014 03.06.2014 09.06.2014 30.06.2014 09.07.2014 14.07.2014 15.08.2014 02.09.2014 07.10.2014 21.11.2014 31.12.2014 19.03.2015 30.04.2015 Time (sec) Operations (Wordpress) 11.081 11.756 12.629 13.43 13.89 14.15 14.864 14.81 15.85 15.94 16.54 17.403 18.245 18.913 18.957 20.857 21.503 22.592 23.676 26.756 26.756 23.676 22.592 21.503 20.857 18.957 18.913 18.245 17.403 16.54 15.94 15.85 14.81 14.864 14.15 13.89 13.43 12.629 11.756 11.081
  18. A S T A B S T R A C

    T S Y N TA X T R E E CC-BY: Johan Neven
  19. Statement Sequence Return while compare op: ≠ branch compare op:

    > assign assign variable: a constant value: 0 variable name: a bin op op: - variable name: a variable name: b variable name: b bin op: op - variable name: b variable name: a Variable name: a condition body variable: a variable: b condition if-body else body
  20. A S T — A B S T R A

    C T S Y N TA X T R E E • Mostly Invisible to Userland • Paves the way for more performance (optimizing is easier with an AST) • Allows for easier implementation of future features
  21. U N I F O R M VA R I

    A B L E S Y N TA X CC-BY-ND: vil.sandi
  22. U N I F O R M VA R I

    A B L E S Y N TA X • Variable-Variables are the problem! • PHP 7 will read left-to-right consistently! • Easy to be forwards compatible with the addition of braces and parenthesis • Lots of new dereferencing options available like nested :: and array-derefenced closures.
  23. U N I F O R M VA R I

    A B L E S Y N TA X : C O N S I S T E N C Y C H A N G E S Syntax Old Interpretation New Interpretation $$var['key1']['key2'] ${$var['key1']['key2']} ($$var)['key1']['key2'] $var->$prop['key'] $var->{$prop['key']} ($var->$prop)['key'] $var->$prop['key']() $var->{$prop['key']}() ($var->$prop)['key']() Class::$var['key']() Class::{$var['key']}() (Class::$var)['key']()
  24. U N I F O R M VA R I

    A B L E S Y N TA X : N E W S Y N TA X
  25. M I S S I N G C O M

    B I N AT I O N S $foo()['bar']() [$obj1, $obj2][0]->prop getStr(){0}
  26. N E S T E D S TAT I C

    A C C E S S O R S $foo['bar']::$baz $foo::$bar::$baz $foo->bar()::baz()
  27. N E S T E D PA R E N

    T H E S E S foo()() $foo->bar()() Foo::bar()() $foo()()
  28. A R B I T R A RY E X

    P R E S S I O N D E R E F E R E N C I N G (...)['foo'] (...)->foo (...)->foo() (...)::$foo (...)::foo() (...)() Including: (function() { ... })() ($obj->closure)()
  29. D E R E F E R E N C

    I N G S C A L A R S "string"->toLower() • Allows for future object-scalars
 [$obj, 'method']() • Allows array-method callables 'Foo'::$bar • ¯\_(ϑ)_/¯
  30. N O L O N G E R S U

    P P O R T E D global $$foo->bar; // instead use: global ${$foo->bar};
 (or better yet: don’t use globals!)
  31. A S S E R T I O N S

    • Behavior of assert() expanded in PHP 7 • Can be turned off, to remove overhead in production • Can emit exceptions on failure, defaults to a WARNING • Allow for a custom message
  32. A S S E R T I O N S

    zend.assertions = 1 ; Enable assertions zend.assertions = 0 ; Disable warning/exceptions zend.assertions = -1; Completely Ignored assert.exception = 1 ; Throw exception on failure
  33. A S S E R T I O N S

    assert("false === true"); 
 // Not evaluated if zend.assertions = 0 Warning: assert(): Assertion "false === true" failed assert("false === true", "Expression was falsey"); 
 // Supply a custom error message Warning: assert(): Expression was falsey: "false === true" failed
  34. E R R O R H A N D L

    I N G CC-BY-SA: stallio
  35. C AT C H A B L E FATA L

    E R R O R : C A L L T O M E M B E R F U N C T I O N O N N O N - O B J E C T
  36. C AT C H A B L E FATA L

    E R R O R : C A L L T O M E M B E R F U N C T I O N O N N O N - O B J E C T • When calling a method on a non-object it is now a catchable fatal error. • This means you can continue execution if the error is handled.
  37. set_error_handler(function($code, $message) { var_dump($code, $message); }); $var = null; $var->method();


    // Fatal Error: Call to a member function method() on null echo "Hello World"; // Still runs Catchable Fatal Error: Call to member function on non-object
  38. set_error_handler(function($code, $message) { var_dump($code, $message); }); $var = null; $var->method();


    // Fatal Error: Call to a member function method() on null echo "Hello World"; // Still runs Catchable Fatal Error: Call to member function on non-object
  39. E N G I N E E X C E

    P T I O N S
  40. Engine Exceptions: Call to member function on non-object 
 try

    { $var = null; $var->method(); } catch (\Error $e) { echo $e->getMessage(); 
 // Call to a member function method() on null } echo "Hello World"; // Still runs
  41. E N G I N E E X C E

    P T I O N S • Can be handled gracefully • Finally blocks are called • Destructors are called • Easier Catchable fatal error handling
  42. E X C E P T I O N H

    I E R A R C H Y \Throwable interface ├── \Exception implements \Throwable └── \Error implements \Throwable ├── \TypeError extends \Error ├── \ParseError extends \Error └── \AssertionError extends \Error
  43. \ T H R O WA B L E •

    Engine exceptions do not extend \Exception so that old catch-all’s will not catch them, preserving BC • New \Throwable interface from which \Error and \Exception implement • catch (\Throwable) { } is the new catch-all. • Cannot be implemented in userland — you must extend \Error or \Exception still • \Throwable can itself be extended and implemented
  44. \ E R R O R • Now throws \Error

    exceptions instead of Catchable/Fatal errors • No BC break for Fatal (uncaught exception == actually Fatal) • Small BC break for Catchable: no longer possible to suppress errors entirely in set_error_handler() (must catch the exception)
  45. \ P A R S E E R R O

    R • Thrown when a parse error is encountered in an include/ require or eval() try { include "parse-error.php"; } catch (\ParseError $e) { var_dump($e); } // parse-error.php function $foo() { }
  46. \ P A R S E E R R O

    R object(ParseError)#1 (7) { ["message":protected]=> string(84) "syntax error, 
 unexpected '$foo' (T_VARIABLE), expecting identifier 
 (T_STRING) or '('" ["string":"Error":private]=> string(0) "" ["code":protected]=> int(4) ["file":protected]=> string(21) "/root/parse-error.php" ["line":protected]=> int(2) ["trace":"Error":private]=> array(0) {} ["previous":"Error":private]=> NULL }
  47. \ T Y P E E R R O R

    • Throws \TypeError on type mis-matches in strict mode function compare(Comparable $a, Comparable $b) { return $a <=> $b; } try { echo compare($obj, $obj2); } catch (\TypeError $e) { var_dump($e); }
  48. \ T Y P E E R R O R

    object(TypeError)#1 (7) { ["message":protected]=> string(110) "Argument 1 passed to compare() must 
 be of the type Comparable, int given" ["string":"Error":private]=> string(0) "" ["code":protected]=> int(1) ["file":protected]=> string(20) "/root/type-error.php" ["line":protected]=> int(3) ["trace":"Error":private]=> array(1) { [0]=> array(4) { ["file"]=> string(20) "/root/type-error.php" ["line"]=> int(8) ["function"]=> string(3) "compare" ["args"]=> array(2) { [0]=> … [1]=> … } } } ["previous":"Error":private]=> NULL }
  49. ini_set('zend.assertions', 1); ini_set('assert.exception', 1); try { assert("false === true", "Expression

    was falsey"); } catch (\AssertionError $e) { var_dump($e); } \ A S S E R T I O N E R R O R • Throws \AssertionError on assert() failures
  50. \ A S S E R T I O N

    E R R O R object(AssertionError)#1 (7) { ["message":protected]=> string(21) "Expression was falsey" ["string":"Error":private]=> string(0) "" ["code":protected]=> int(1) ["file":protected]=> string(22) "/root/assert-error.php" ["line":protected]=> int(6) ["trace":"Error":private]=> array(1) { [0]=> array(4) { ["file"]=> string(22) "/root/assert-error.php" ["line"]=> int(6) ["function"]=> string(6) "assert" ["args"]=> array(2) { [0]=> string(14) "false === true" [1]=> string(21) "Expression was falsey" } } } ["previous":"Error":private]=> NULL }
  51. N E W F E AT U R E S

    CC-BY-SA: Steven Gerner
  52. C O M B I N E D C O

    M PA R I S O N O P E R AT O R
  53. S PA C E S H I P O P

    E R AT O R : T _ S PA C E S H I P CC-BY: Virgin Galactic/Mark Greenberg
  54. S PA C E S H I P O P

    E R AT O R : • First trinary return operator: • Returns -1 if left operand is less than right • Returns 0 if left and right operands are identical • Returns +1 if left operand is greater than right • Originally proposed by me! • Thankfully championed by Andrea Faulds and finally Stas Malyshev • Looks like a spaceship: <=> • Mostly useful for sorting callbacks
  55. S PA C E S H I P O P

    E R AT O R // Pre Spacefaring^W PHP 7 function order_func($a, $b) { return ($a < $b) ? -1 : (($a > $b) ? 1 : 0); } // Post PHP 7 function order_func($a, $b) { return $a <=> $b; }
  56. U N I C O D E C O D

    E P O I N T E S C A P E S Y N TA X CC-BY: frontriver
  57. U N I C O D E C O D

    E P O I N T E S C A P E S Y N TA X •\u{CODEPOINT} •e.g. ! can be expressed as "\u{1F49A}"
  58. N U L L C O A L E S

    C E O P E R AT O R Attribution
  59. N U L L C O A L E S

    C E O P E R AT O R • Double question mark: ?? • Will return left operand if not null, or the right operand • Will not raise a notice if the left operand is non-existant (like isset()) • Can be nested:
 $conf = $conf ?? $this->conf ?? static::$defaultConf;
  60. B I N D C L O S U R

    E O N C A L L
  61. B I N D C L O S U R

    E O N C A L L • Similar to $Closure->bindTo() or Closure::bind() • $Closure->call($object, $closureArgs, $here); • Binds $this/scope to $object • Both must be the same
  62. B I N D C L O S U R

    E O N C A L L class HelloWorld { private $greeting = "Hello"; } $closure = function($whom) { echo $this->greeting . ' ' . $whom; } $obj = new HelloWorld(); $closure->call($obj, 'World'); // Hello World
  63. G R O U P U S E D E

    C L A R AT I O N S CC-BY: Buddy Venturanza
  64. G R O U P U S E D E

    C L A R AT I O N S •Simplify multiple use statements with common parent // Original use Framework\Component\SubComponent\ClassA; use Framework\Component\SubComponent\ClassB as ClassC; use Framework\Component\OtherComponent\ClassD; // With Group Use use Framework\Component\{ SubComponent\ClassA, SubComponent\ClassB as ClassC, OtherComponent\ClassD };
  65. G R O U P U S E D E

    C L A R AT I O N S ( C O N T. ) •Also works for functions and constants: use Framework\Component\{ SubComponent\ClassA, function OtherComponent\someFunction, const OtherComponent\SOME_CONSTANT };
  66. G E N E R AT O R E N

    H A N C E M E N T S CC-BY: Will Folsom
  67. G E N E R AT O R R E

    T U R N E X P R E S S I O N S • Generators can now return a value • Retrieved by $generator->getReturn()
  68. G E N E R AT O R R E

    T U R N VA L U E S function gen() { yield "Hello"; yield " "; yield "World!"; return "Goodbye Moon!"; } $gen = gen(); foreach ($gen as $value) { echo $value; } // Outputs "Hello" on iteration 1, " " on iterator 2, and "World!" on iteration 3 echo $gen->getReturn(); // Goodbye Moon!
  69. G E N E R AT O R D E

    L E G AT I O N • Yield other generators or iterable structures — sub-generators • Uses yield from
  70. G E N E R AT O R D E

    L E G AT I O N function hello() { yield "Hello"; yield " "; yield "World!"; yield from goodbye(); } function goodbye() { yield "Goodbye"; yield " "; yield "Moon!"; }
  71. G E N E R AT O R D E

    L E G AT I O N $gen = hello(); foreach ($gen as $value) { echo $value; } 1. "Hello" 2. " " 3. "World!" 4. "Goodbye" 5. " " 6. "Moon!"
  72. A N O N Y M O U S C

    L A S S E S CC-BY: Toren Monson
  73. A N O N Y M O U S C

    L A S S E S • Like closures but for object instances • Uses new class($args) followed by a regular class definition • Can be namespaced • Support inheritance, traits, and interfaces • The internal name is based on it’s address • e.g. class@0x7fa77f271bd0 • If you extend a class, it will use that class as the prefix instead • This means that if you create anonymous classes in a loop it will actually create multiple of the same anonymous class
  74. A N O N Y M O U S C

    L A S S E S $obj = new class($args) { public function __construct($args) { ... } }; $obj = new class ($args) extends Foo implements Bar { use Bat; };
  75. A N O N Y M O U S C

    L A S S E S foreach ($array as $value) { $instances[] = new class($value) extends ValueObject { ... } } $instance = new class($value) extends ValueObject { ... }; $instances[..] == $instances[..]; // where $value is the same $instances[..] != $instance; // These are different classes and 
 // will never match
  76. S C A L A R T Y P E

    H I N T S XKCD #1537
  77. S C A L A R T Y P E

    H I N T S • Type-hint function/method arguments • Type-hint return values • Default: non-strict, will coerce types when possible • Allows for strict, applies to that file only, and only to the things it calls (with type-hints), not the things it defines.
  78. S C A L A R T Y P E

    H I N T S : N O N - S T R I C T function sendHttpStatus(int $statusCode, 
 string $message) { header('HTTP/1.0 ' .$statusCode. ' ' .$message); }
 sendHttpStatus(404, "File Not Found"); 
 // integer and string passed sendHttpStatus("403", "OK"); 
 // string "403" coerced to int(403)
  79. S C A L A R T Y P E

    H I N T S : N O N - S T R I C T • Default non-strict behavior coerces • int(1) => function(float $foo) => float(1.0) • float(1.5) => function(int $foo) => int(1) • string("100") => function (int $foo) => int(100)
  80. S C A L A R T Y P E

    H I N T S • Strict Type Hints: declare(strict_types=1); • Must be the first statement (even before namespace) • Throws a \TypeException on mis-match declare(strict_types=1); // must be the first statement try { sendHttpStatus(404, "File Not Found"); sendHttpStatus("403", "OK"); } catch (\TypeException $e) { var_dump($e); } 
 // Argument 1 passed to sendHttpStatus() must be of the type integer, string given
  81. R E T U R N T Y P E

    H I N T S • Type hint return values • Allows for all type hints, not just scalars • Suffix argument list with a colon and the hint (same syntax as Hack) function isValidStatusCode(int $statusCode): bool { return isset($this->statuses[$statusCode]); }
  82. W H AT N E X T ? • https://github.com/rlerdorf/php7dev

    • https://github.com/janatzend/docker-php7-nightly-build • http://gophp7.org/gophp7-ext/ • https://wiki.php.net/rfc#php_70
  83. F E E D B A C K & Q

    U E S T I O N S Feedback: Twitter: Email: Slides: https://joind.in/ @dshafik [email protected] http://daveyshafik.com/slides 14835