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

What's new in PHP 7.2

What's new in PHP 7.2

New features, new functions, new constants, deprecations, other changes and optimizations coming with the new PHP 7.2 release. This talk should give a brief overview of what has changed, what has improved and what you should fix to be able to upgrade to future versions of PHP.

Talk at PHP USERGROUP DRESDEN e.V.

Holger Woltersdorf

December 19, 2017
Tweet

More Decks by Holger Woltersdorf

Other Decks in Programming

Transcript

  1. HOLGER WOLTERSDORF CIO • FATHER • HUSBAND • PHP DEV

    WITH ♥ github.com/hollodotme @hollodotme
  2. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF OBJECT TYPE 6 class GrandMother { public function howAboutFood( object $child ) : void { echo "G: How about food?\nK: {$child!->getStatus()}\n"; } public function feed( object $child ) : object { echo "G: I've got some cookies for you!\n"; return $child!->eat(); } } class Child { private $status = 'I am hungry!'; public function eat() : Child { echo "K: Mhh nom nom nom\n"; $this!->status = 'I am full up.'; return $this; } public function getStatus() : string { return $this!->status; } } $kiddo = new Child(); $granny = new GrandMother(); $granny!->howAboutFood( $kiddo ); $fatKiddo = $granny!->feed( $kiddo ); $granny!->howAboutFood( $fatKiddo );
  3. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF OBJECT TYPE 7 class GrandMother { public function howAboutFood( object $child ) : void { echo "G: How about food?\nK: {$child!->getStatus()}\n"; } public function feed( object $child ) : object { echo "G: I've got some cookies for you!\n"; return $child!->eat(); } } class Child { private $status = 'I am hungry!'; public function eat() : Child { echo "K: Mhh nom nom nom\n"; $this!->status = 'I am full up.'; return $this; } public function getStatus() : string { return $this!->status; } } $kiddo = new Child(); $granny = new GrandMother(); $granny!->howAboutFood( $kiddo ); $fatKiddo = $granny!->feed( $kiddo ); $granny!->howAboutFood( $fatKiddo ); G: How about food? K: I am hungry! G: I've got some cookies for you! K: Mhh nom nom nom G: How about food? K: I am full up. OUTPUT:
  4. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF OBJECT TYPE 8 class GrandMother { public function howAboutFood( object $child ) : void { echo "G: How about food?\nB: {$child!->getStatus()}\n"; } public function feed( object $child ) : object { echo "G: I've got some cookies for you!\n"; return $child!->eat(); } } class Baby { private $status = 'I am hungry!'; public function eat() : string { echo "B: Mhh nom nom nom\n"; return 'I want m`00´re""...'; } public function getStatus() : string { return $this!->status; } } $baby = new Baby(); $granny = new GrandMother(); $granny!->howAboutFood( $baby ); $fatBaby = $granny!->feed( $baby ); $granny!->howAboutFood( $fatBaby );
  5. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF OBJECT TYPE 9 class GrandMother { public function howAboutFood( object $child ) : void { echo "G: How about food?\nB: {$child!->getStatus()}\n"; } public function feed( object $child ) : object { echo "G: I've got some cookies for you!\n"; return $child!->eat(); } } class Baby { private $status = 'I am hungry!'; public function eat() : string { echo "B: Mhh nom nom nom\n"; return 'I want m`00´re""...'; } public function getStatus() : string { return $this!->status; } } $baby = new Baby(); $granny = new GrandMother(); $granny!->howAboutFood( $baby ); $fatBaby = $granny!->feed( $baby ); $granny!->howAboutFood( $fatBaby ); G: What about food? B: I am hungry! G: I've got some cookies for you! B: Mhh nom nom nom PHP Fatal error: Uncaught TypeError: Return value of GrandMother!::feed() must be an object, string returned OUTPUT:
  6. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF OBJECT TYPE 10 class GrandMother { public function howAboutFood( object $child ) : void { echo "G: How about food?\nB: {$child!->getStatus()}\n"; } public function feed( object $child ) : object { echo "G: I've got some cookies for you!\n"; return $child!->eat(); } } class Baby { private $status = 'I am hungry!'; public function eat() : string { echo "B: Mhh nom nom nom\n"; return 'I want m`00´re""...'; } public function getStatus() : string { return $this!->status; } } $baby = new Baby(); $granny = new GrandMother(); $granny!->howAboutFood( $baby ); $fatBaby = $granny!->feed( $baby ); $granny!->howAboutFood( $fatBaby ); G: What about food? B: I am hungry! G: I've got some cookies for you! B: Mhh nom nom nom PHP Fatal error: Uncaught TypeError: Return value of GrandMother!::feed() must be an object, string returned OUTPUT:
  7. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF OBJECT TYPE 11 ๏ BUT REMEMBER: ๏ object has no meaningful interface ๏ Don't be lazy - define proper interfaces! ๏ Reasonable when you expect a non-scalar / non-array value 
 e.g. for an instanceof check
  8. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF LOAD EXTENSIONS BY NAME 12 [redis] extension="redis.so" extension="redis.dll" # OR <?php dl('redis.so'); # *nix dl('redis.dll'); # win [redis] extension="redis" # OR <?php dl('redis'); # *nix + win PHP < 7.2 PHP ">= 7.2 Warning This function dl() was removed from most SAPIs in PHP 5.3.0, and was removed from PHP-FPM in PHP 7.0.0.
  9. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF ABSTRACT METHOD OVERWRITE 13 class Lighter { } class Match { } interface CandleInterface { public function fireUp( Match $fireSupply ); } abstract class Candle implements CandleInterface { abstract public function fireUp( Match $fireSupply ); } final class TableCandle extends Candle { public function fireUp( Match $fireSupply ) { echo "See the romance?\n"; } } interface CandleCollectionInterface extends CandleInterface { public function fireUp( $fireSupply ) : int; } abstract class CandleCollection extends Candle implements CandleCollectionInterface { abstract public function fireUp( $fireSupply ) : int; } final class FairyLights extends CandleCollection { public function fireUp( $fireSupply ) : int { return 42; } } $tableCandle = new TableCandle(); $tableCandle!->fireUp( new Match() ); # !!--- $fairyLights = new FairyLights(); $firedUp = $fairyLights!->fireUp( new Lighter() ); printf( 'Our tree has %d burning candles.', $firedUp ); See the romance? Our tree has 42 burning candles. OUTPUT:
  10. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF class Lighter { } class Match { } interface CandleInterface { public function fireUp( Match $fireSupply ); } abstract class Candle implements CandleInterface { abstract public function fireUp( Match $fireSupply ); } final class TableCandle extends Candle { public function fireUp( Match $fireSupply ) { echo "See the romance?\n"; } } interface CandleCollectionInterface extends CandleInterface { public function fireUp( $fireSupply ) : int; } abstract class CandleCollection extends Candle implements CandleCollectionInterface { abstract public function fireUp( $fireSupply ) : int; } final class FairyLights extends CandleCollection { public function fireUp( $fireSupply ) : int { return 42; } } ABSTRACT METHOD OVERWRITE 14 $tableCandle = new TableCandle(); $tableCandle!->fireUp( new Match() ); # !!--- $fairyLights = new FairyLights(); $firedUp = $fairyLights!->fireUp( new Lighter() ); printf( 'Our tree has %d burning candles.', $firedUp ); See the romance? Our tree has 42 burning candles. OUTPUT:
  11. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF class Lighter { } class Match { } interface CandleInterface { public function fireUp( Match $fireSupply ); } abstract class Candle implements CandleInterface { abstract public function fireUp( Match $fireSupply ); } final class TableCandle extends Candle { public function fireUp( Match $fireSupply ) { echo "See the romance?\n"; } } interface CandleCollectionInterface extends CandleInterface { public function fireUp( $fireSupply ) : int; } abstract class CandleCollection extends Candle implements CandleCollectionInterface { abstract public function fireUp( $fireSupply ) : int; } final class FairyLights extends CandleCollection { public function fireUp( $fireSupply ) : int { return 42; } } ABSTRACT METHOD OVERWRITE 15 $tableCandle = new TableCandle(); $tableCandle!->fireUp( new Match() ); # !!--- $fairyLights = new FairyLights(); $firedUp = $fairyLights!->fireUp( new Lighter() ); printf( 'Our tree has %d burning candles.', $firedUp ); See the romance? Our tree has 42 burning candles. OUTPUT: DECLARATIONS MUST BE EQUAL
  12. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF class Lighter { } class Match { } interface CandleInterface { public function fireUp( Match $fireSupply ); } abstract class Candle implements CandleInterface { abstract public function fireUp( Match $fireSupply ); } final class TableCandle extends Candle { public function fireUp( Match $fireSupply ) { echo "See the romance?\n"; } } interface CandleCollectionInterface extends CandleInterface { public function fireUp( $fireSupply ) : int; } abstract class CandleCollection extends Candle implements CandleCollectionInterface { abstract public function fireUp( $fireSupply ) : int; } final class FairyLights extends CandleCollection { public function fireUp( $fireSupply ) : int { return 42; } } ABSTRACT METHOD OVERWRITE 16 $tableCandle = new TableCandle(); $tableCandle!->fireUp( new Match() ); # !!--- $fairyLights = new FairyLights(); $firedUp = $fairyLights!->fireUp( new Lighter() ); printf( 'Our tree has %d burning candles.', $firedUp ); See the romance? Our tree has 42 burning candles. OUTPUT: DECLARATIONS MUST BE EQUAL DECLARATIONS CAN BE EQUAL
  13. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF class Lighter { } class Match { } interface CandleInterface { public function fireUp( Match $fireSupply ); } abstract class Candle implements CandleInterface { abstract public function fireUp( Match $fireSupply ); } final class TableCandle extends Candle { public function fireUp( $fireSupply ) : void { echo "See the romance?\n"; } } interface CandleCollectionInterface extends CandleInterface { public function fireUp( $fireSupply ) : int; } abstract class CandleCollection extends Candle implements CandleCollectionInterface { abstract public function fireUp( $fireSupply ) : int; } final class FairyLights extends CandleCollection { public function fireUp( $fireSupply ) : int { return 42; } } ABSTRACT METHOD OVERWRITE 17 $tableCandle = new TableCandle(); $tableCandle!->fireUp( new Match() ); # !!--- $fairyLights = new FairyLights(); $firedUp = $fairyLights!->fireUp( new Lighter() ); printf( 'Our tree has %d burning candles.', $firedUp ); See the romance? Our tree has 42 burning candles. OUTPUT: DECLARATIONS MUST BE EQUAL DECLARATIONS CAN DIFFER
  14. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF class Lighter { } class Match { } interface CandleInterface { public function fireUp( Match $fireSupply ); } abstract class Candle implements CandleInterface { abstract public function fireUp( Match $fireSupply ); } final class TableCandle extends Candle { public function fireUp( $fireSupply ) : void { echo "See the romance?\n"; } } interface CandleCollectionInterface extends CandleInterface { public function fireUp( $fireSupply ) : int; } abstract class CandleCollection extends Candle implements CandleCollectionInterface { abstract public function fireUp( $fireSupply ) : int; } final class FairyLights extends CandleCollection { public function fireUp( $fireSupply ) : int { return 42; } } ABSTRACT METHOD OVERWRITE 18 $tableCandle = new TableCandle(); $tableCandle!->fireUp( new Match() ); # !!--- $fairyLights = new FairyLights(); $firedUp = $fairyLights!->fireUp( new Lighter() ); printf( 'Our tree has %d burning candles.', $firedUp ); See the romance? Our tree has 42 burning candles. OUTPUT: DECLARATIONS CAN DIFFER
  15. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF class Lighter { } class Match { } interface CandleInterface { public function fireUp( Match $fireSupply ); } abstract class Candle implements CandleInterface { abstract public function fireUp( Match $fireSupply ); } final class TableCandle extends Candle { public function fireUp( Match $fireSupply ) { echo "See the romance?\n"; } } interface CandleCollectionInterface extends CandleInterface { public function fireUp( $fireSupply ) : int; } abstract class CandleCollection extends Candle implements CandleCollectionInterface { abstract public function fireUp( $fireSupply ) : int; } final class FairyLights extends CandleCollection { public function fireUp( $fireSupply ) : int { return 42; } } ABSTRACT METHOD OVERWRITE 19 $tableCandle = new TableCandle(); $tableCandle!->fireUp( new Match() ); # !!--- $fairyLights = new FairyLights(); $firedUp = $fairyLights!->fireUp( new Lighter() ); printf( 'Our tree has %d burning candles.', $firedUp ); See the romance? Our tree has 42 burning candles. OUTPUT: DECLARATIONS CAN DIFFER
  16. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF class Lighter { } class Match { } interface CandleInterface { public function fireUp( Match $fireSupply ); } abstract class Candle implements CandleInterface { abstract public function fireUp( Match $fireSupply ); } final class TableCandle extends Candle { public function fireUp( Match $fireSupply ) { echo "See the romance?\n"; } } interface CandleCollectionInterface extends CandleInterface { public function fireUp( $fireSupply ) : int; } abstract class CandleCollection extends Candle implements CandleCollectionInterface { abstract public function fireUp( $fireSupply ) : int; } final class FairyLights extends CandleCollection { public function fireUp( $fireSupply ) : int { return 42; } } ABSTRACT METHOD OVERWRITE 20 $tableCandle = new TableCandle(); $tableCandle!->fireUp( new Match() ); # !!--- $fairyLights = new FairyLights(); $firedUp = $fairyLights!->fireUp( new Lighter() ); printf( 'Our tree has %d burning candles.', $firedUp ); See the romance? Our tree has 42 burning candles. OUTPUT: DECLARATIONS MUST BE EQUAL
  17. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF class Lighter { } class Match { } interface CandleInterface { public function fireUp( Match $fireSupply ); } abstract class Candle implements CandleInterface { abstract public function fireUp( Match $fireSupply ); } final class TableCandle extends Candle { public function fireUp( Match $fireSupply ) { echo "See the romance?\n"; } } interface CandleCollectionInterface extends CandleInterface { public function fireUp( $fireSupply ) : int; } abstract class CandleCollection extends Candle implements CandleCollectionInterface { abstract public function fireUp( $fireSupply ) : int; } final class FairyLights extends CandleCollection { public function fireUp( Lighter $fireSupply ) : int { return 42; } } ABSTRACT METHOD OVERWRITE 21 $tableCandle = new TableCandle(); $tableCandle!->fireUp( new Match() ); # !!--- $fairyLights = new FairyLights(); $firedUp = $fairyLights!->fireUp( new Lighter() ); printf( 'Our tree has %d burning candles.', $firedUp ); See the romance? Fatal error: Declaration of FairyLights!::fireUp(Lighter $fireSupply): int must be compatible with CandleCollection!::fireUp($fireSupply): int OUTPUT: DECLARATIONS CANNOT DIFFER
  18. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF ABSTRACT METHOD OVERWRITE 22 ๏ REMEMBER: ๏ Increases effort to understand the code. ๏ Don't be lazy - define proper interfaces! ๏ Interfaces are not entirely breakable. ๏ Overwriting methods still must maintain the contravariance for parameters 
 and the covariance for return ๏ TL;DR: You can only widen input and restrict output - not vice-versa.
  19. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF PDO::DEBUGDUMPPARAMS() 23 $pdo = new \PDO( 'mysql:host=127.0.0.1;port=3306', 'root', 'root', [ \PDO!::ATTR_EMULATE_PREPARES !=> true, ] ); $statement = $pdo!->prepare( 'SELECT * FROM mysql.user WHERE user = :user LIMIT 1' ); $statement!->execute( ['user' !=> 'root'] ); $statement!->debugDumpParams(); SQL: [51] SELECT * FROM mysql.user WHERE user = :user LIMIT 1 Params: 1 Key: Name: [5] :user paramno=-1 name=[5] ":user" is_param=1 param_type=2 PHP < 7.2 PHP ">= 7.2 SQL: [51] SELECT * FROM mysql.user WHERE user = :user LIMIT 1 Sent SQL: [52] SELECT * FROM mysql.user WHERE user = 'root' LIMIT 1 Params: 1 Key: Name: [5] :user paramno=-1 name=[5] ":user" is_param=1 param_type=2
  20. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF PDO::DEBUGDUMPPARAMS() 24 $pdo = new \PDO( 'mysql:host=127.0.0.1;port=3306', 'root', 'root', [ \PDO!::ATTR_EMULATE_PREPARES !=> false, ] ); $statement = $pdo!->prepare( 'SELECT * FROM mysql.user WHERE user = :user LIMIT 1' ); $statement!->execute( ['user' !=> 'root'] ); $statement!->debugDumpParams(); SQL: [51] SELECT * FROM mysql.user WHERE user = :user LIMIT 1 Params: 1 Key: Name: [5] :user paramno=-1 name=[5] ":user" is_param=1 param_type=2 PHP < 7.2 PHP ">= 7.2 SQL: [51] SELECT * FROM mysql.user WHERE user = :user LIMIT 1 Params: 1 Key: Name: [5] :user paramno=-1 name=[5] ":user" is_param=1 param_type=2
  21. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF PDO::PARAM_STR_NATL 25 $pdo = new \PDO( 'mysql:host=127.0.0.1;port=3306', 'root', 'root', [ \PDO!::MYSQL_ATTR_INIT_COMMAND !=> 'SET NAMES UTF8;', ] ); $statement = $pdo!->prepare( "SELECT :umlaut" ); $statement!->bindValue( 'umlaut', 'äüöÄÜÖ', PDO!::PARAM_STR | PDO!::PARAM_STR_NATL ); $statement!->execute(); $statement!->debugDumpParams(); echo "\nResult: " . $statement!->fetchColumn(); OUTPUT: SQL: [14] SELECT :umlaut Sent SQL: [22] SELECT N'äüöÄÜÖ' Params: 1 Key: Name: [7] :umlaut paramno=-1 name=[7] ":umlaut" is_param=1 param_type=1073741826 Result: äüöÄÜÖ
  22. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF ARGON2 PASSWORD HASH ALGO 26 $options = [ !// number of KiB that should be consumed !// (default values are 1!<<10, or 1024 KiB, or 1 MiB) 'memory_cost' !=> PASSWORD_ARGON2_DEFAULT_MEMORY_COST, !// number of iterations of the hashing algorithm !// (defaults to 2) 'time_cost' !=> PASSWORD_ARGON2_DEFAULT_TIME_COST, !// number of parallel threads that will be used !// (defaults to 2) 'threads' !=> PASSWORD_ARGON2_DEFAULT_THREADS, ]; echo password_hash( 'password', PASSWORD_ARGON2I, $options ); OUTPUT: $argon2i$v=19$m=1024,t=2,p=2$VEluMktEUGZvZVRyakhRcQ$zA08nETLeMoOgo/dvqf1qMZyCMl4yz3U6vPtqiYpS48 | ARGON2 IS A KEY DERIVATION FUNCTION THAT WAS SELECTED AS THE WINNER OF THE PASSWORD HASHING COMPETITION IN JULY 2015. | IT WAS DESIGNED BY ALEX BIRYUKOV, DANIEL DINU, AND DMITRY KHOVRATOVICH FROM UNIVERSITY OF LUXEMBOURG.
  23. PLEASE WELCOME TO THE PHP CORE Sodium is a chemical

    element with symbol Na libsodium is a Fork of NaCl (Natriumchlorid = Salt) Modern crypto for 2017
  24. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF SODIUM PASSWORD HASHING 29 $password = 'password'; !// hash the password and return an ASCII string suitable for storage $hashStr = sodium_crypto_pwhash_str( $password, SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE ); echo $hashStr, "\n"; if ( sodium_crypto_pwhash_str_verify( $hashStr, $password ) ) { echo "Verification: Password is valid.\n"; } else { echo "Verification: Password is valid.\n"; } sodium_memzero( $password ); # wipe the plaintext password from memory OUTPUT: $argon2id$v=19$m=65536,t=2,p=1$yF1wB5WDGe3ENYZ7GHZZuQ$e/GHZ6Yra0UqLvqnQpIdHS1tJX+FloKyTl3Hmf8FIFc Verification: Password is valid.
  25. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF SODIUM PASSWORD HASHING 30 $password = 'password'; !// hash the password and return an ASCII string suitable for storage $hashStr = sodium_crypto_pwhash_str( $password, SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE ); echo $hashStr, "\n"; if ( sodium_crypto_pwhash_str_verify( $hashStr, $password ) ) { echo "Verification: Password is valid.\n"; } else { echo "Verification: Password is invalid.\n"; } sodium_memzero( $password ); # wipe the plaintext password from memory OUTPUT: $argon2id$v=19$m=65536,t=2,p=1$yF1wB5WDGe3ENYZ7GHZZuQ$e/GHZ6Yra0UqLvqnQpIdHS1tJX+FloKyTl3Hmf8FIFc Verification: Password is valid.
  26. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF SODIUM AUTHENTICATED EN/DECRYPTION 31 function deriveKeyFromPassword( string $password, string $salt ) : string { $outLength = SODIUM_CRYPTO_SIGN_SEEDBYTES; $seed = sodium_crypto_pwhash( $outLength, $password, $salt, SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE ); return $seed; } function encrypt( string $plainText, string $password ) : string { $salt = random_bytes( SODIUM_CRYPTO_PWHASH_SALTBYTES ); $key = deriveKeyFromPassword( $password, $salt ); $nonce = random_bytes( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $cipherText = sodium_crypto_secretbox( $plainText, $nonce, $key ); return $salt . $nonce . $cipherText; } function decrypt( string $cipherText, string $password ) : string { $salt = substr( $cipherText, 0, SODIUM_CRYPTO_PWHASH_SALTBYTES ); $nonce = substr( $cipherText, SODIUM_CRYPTO_PWHASH_SALTBYTES, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $encryptedText = substr( $cipherText, SODIUM_CRYPTO_PWHASH_SALTBYTES + SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $key = deriveKeyFromPassword( $password, $salt ); $plainText = sodium_crypto_secretbox_open( $encryptedText, $nonce, $key ); if ( false !!=== $plainText ) throw new \InvalidArgumentException( 'Bad cipher text' ); return $plainText; } $password = 'password'; $message = 'Ho-Ho-Ho'; $encrypted = encrypt( $message, $password ); var_dump( $encrypted ); $decrypted = decrypt( $encrypted, $password ); var_dump( $decrypted );
  27. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF SODIUM AUTHENTICATED EN/DECRYPTION 32 function deriveKeyFromPassword( string $password, string $salt ) : string { $outLength = SODIUM_CRYPTO_SIGN_SEEDBYTES; $seed = sodium_crypto_pwhash( $outLength, $password, $salt, SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE ); return $seed; } function encrypt( string $plainText, string $password ) : string { $salt = random_bytes( SODIUM_CRYPTO_PWHASH_SALTBYTES ); $key = deriveKeyFromPassword( $password, $salt ); $nonce = random_bytes( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $cipherText = sodium_crypto_secretbox( $plainText, $nonce, $key ); return $salt . $nonce . $cipherText; } function decrypt( string $cipherText, string $password ) : string { $salt = substr( $cipherText, 0, SODIUM_CRYPTO_PWHASH_SALTBYTES ); $nonce = substr( $cipherText, SODIUM_CRYPTO_PWHASH_SALTBYTES, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $encryptedText = substr( $cipherText, SODIUM_CRYPTO_PWHASH_SALTBYTES + SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $key = deriveKeyFromPassword( $password, $salt ); $plainText = sodium_crypto_secretbox_open( $encryptedText, $nonce, $key ); if ( false !!=== $plainText ) throw new \InvalidArgumentException( 'Bad cipher text' ); return $plainText; } $password = 'password'; $message = 'Ho-Ho-Ho'; $encrypted = encrypt( $message, $password ); var_dump( $encrypted ); $decrypted = decrypt( $encrypted, $password ); var_dump( $decrypted ); string(64) "[BINARY DATA]" string(8) "Ho-Ho-Ho" OUTPUT:
  28. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF SODIUM IN PHP CORE 33 ๏ TAKE-AWAYS: ๏ Password hashing is equivalent to password_hash() with Argon2 ๏ (Authenticated) encryption is easy with sodium ๏ sodium is currently poorly documented on php.net (YOU CAN CHANGE THAT!) ๏ Have a look at: ๏ GitBook: https://www.gitbook.com/book/jedisct1/libsodium/details ๏ PHP examples: https://paragonie.com/book/pecl-libsodium ๏ Official docs: https://download.libsodium.org/doc/
  29. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF WHAT ELSE... 34 # OLD: arrays $array = [1, 2, 3,]; # NEW: grouped namespaces use Foo\Bar\ { Bar, Baz, Foo, }; Read and write support for encrypted archives has been added (requires libzip 1.2.0). The ZipArchive class now implements the Countable interface. The zip:"// stream now accepts a 'password' context option. The proc_nice() function is now supported on Windows.
  30. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF NEW FUNCTIONS 36 # Is the stream a file descriptor attached to a terminal? var_dump( stream_isatty( STDIN ) ); var_dump( stream_isatty( STDOUT ) ); var_dump( stream_isatty( STDERR ) ); var_dump( stream_isatty( fopen( 'php:"//memory', 'rb' ) ) ); var_dump( stream_isatty( tmpfile() ) ); # Prints bool(true) bool(true) bool(true) bool(false) bool(false) CORE: stream_isatty() CORE: sapi_windows_vt100_support() (づ。◕‿‿◕。)づ ¯\_(ツ)_/¯
  31. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF NEW FUNCTIONS 37 # Returns the integer object handle for the given object $a = new \stdClass(); $b = new class { }; $c = function () { }; var_dump( spl_object_id( $a ) ); var_dump( spl_object_id( $b ) ); var_dump( spl_object_id( $c ) ); unset($b); var_dump( spl_object_id( $a ) ); var_dump( spl_object_id( $b ) ); var_dump( spl_object_id( $c ) ); var_dump( spl_object_id( $a ) ); var_dump( spl_object_id( new \stdClass() ) ); var_dump( spl_object_id( $c ) ); # Prints int(1) int(2) int(3) int(1) PHP Warning: spl_object_id() expects parameter 1 to be object, null given !!... NULL int(3) int(1) int(2) # reused int(3) SPL: spl_object_id()
  32. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF NEW FUNCTIONS 38 $xml = ""<<<EOT <PHP> <WHAT> <IS"/> <NEW"/> "</WHAT> <WHAT> <IN"/> <PHP72"/> "</WHAT> "</PHP> EOT; $dom = new \DOMDocument( '1.0', 'UTF-8' ); $dom!->loadXML( $xml ); $nodeList = $dom!->getElementsByTagName( 'WHAT' ); var_dump( $nodeList!->count() ); var_dump( $nodeList instanceof Countable ); # Prints int(2) bool(true) DOM: DOMNodeList::count() $xml = ""<<<EOT <PHP> <WHAT is="new" in="php72"> <IS"/> <NEW"/> "</WHAT> <WHAT> <IN"/> <PHP72"/> "</WHAT> "</PHP> EOT; $dom = new \DOMDocument( '1.0', 'UTF-8' ); $dom!->loadXML( $xml ); $namedNodeMap = $dom!->getElementsByTagName( 'WHAT' )!->item(0); var_dump( $namedNodeMap!->attributes!->count() ); var_dump( $namedNodeMap!->attributes instanceof Countable ); # Prints int(2) bool(true) DOM: DOMNamedNodeMap::count()
  33. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF NEW CONSTANTS (CORE) 40 ๏ PHP_FLOAT_DIG
 Number of decimal digits that can be rounded into a float and back without precision loss. ๏ PHP_FLOAT_EPSILON
 Smallest representable positive number x, so that x + 1.0 != 1.0. ๏ PHP_FLOAT_MIN
 Smallest representable floating point number. ๏ PHP_FLOAT_MAX
 Largest representable floating point number. ๏ PHP_OS_FAMILY
 The operating system family PHP was built for. Either of 'Windows', 'BSD', 'Darwin', 'Solaris', 'Linux' or 'Unknown'.
  34. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF NEW CONSTANTS (FILE INFO) 41 ๏ FILEINFO_EXTENSION
 Returns the file extension appropriate for a the MIME type detected in the file. 
 For types that commonly have multiple file extensions, such as JPEG images, 
 then the return value is multiple extensions separated by a forward slash e.g.: "jpeg/jpg/jpe/jfif". 
 For unknown types not available in the magic.mime database, then return value is "???".
  35. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF NEW CONSTANTS (JSON) 42 ๏ JSON_INVALID_UTF8_IGNORE
 Ignores invalid UTF-8 characters. ๏ JSON_INVALID_UTF8_SUBSTITUTE
 Substitutes invalid UTF-8 characters. $string = "\xf8\xa1\xa1\xa1\xa1-A-valid-string"; var_dump( json_encode( $string, JSON_INVALID_UTF8_IGNORE ) ); var_dump( json_encode( $string, JSON_INVALID_UTF8_SUBSTITUTE ) ); # Prints string(17) ""-A-valid-string"" string(47) ""\ufffd\ufffd\ufffd\ufffd\ufffd-A-valid-string""
  36. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF NEW CONSTANTS (PCRE) 43 $pattern = '/^(what)(\s+i)?(s)\s+(new)\s+(in)\s+(php72)$/'; $string = 'whats new in php72'; preg_match( $pattern, $string, $matches ); var_export( $matches ); preg_match( $pattern, $string, $matches, PREG_UNMATCHED_AS_NULL ); var_export( $matches ); PREG_UNMATCHED_AS_NULL array ( 0 !=> 'whats new in php72', 1 !=> 'what', 2 !=> '', 3 !=> 's', 4 !=> 'new', 5 !=> 'in', 6 !=> 'php72', ) array ( 0 !=> 'whats new in php72', 1 !=> 'what', 2 !=> NULL, 3 !=> 's', 4 !=> 'new', 5 !=> 'in', 6 !=> 'php72', ) OUTPUT:
  37. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF BC BREAKS 45 # number_format var_dump( number_format( -0.01 ) ); # Prints string(1) "0" # in PHP < 7.2 string(2) "-0" # array to object $arr = [ 0 !=> 1 ]; $obj = (object)$arr; var_dump( $obj, $obj!->{'0'}, # now accessible $obj!->{0} # now accessible ); # Prints class stdClass#1 (1) { public $0 !=> int(1) } int(1) int(1) # PHP < 7.2 object(stdClass)#1 (1) { [0]!=> int(1) } NULL NULL # object to array $obj = new class { public function !__construct() { $this!->{0} = 1; } }; $arr = (array)$obj; var_dump( $arr, $arr[0], # now accessible $arr['0'] # now accessible ); # Prints array(1) { [0] !=> int(1) } int(1) int(1) # PHP < 7.2 array(1) { ["0"]!=> int(1) } NULL NULL
  38. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF BC BREAKS 46 class Test { public function getClassName() { return get_class(null); } } echo (new Test)!->getClassName(); # Prints PHP Warning: get_class() expects parameter 1 to be object, null given # PHP < 7.2 Test # counting non-countable types var_dump( count( 1 ), count( 'abc' ), count( new stdClass() ), count( [ 1, 2 ] ) ); # Prints PHP Warning: count(): Parameter must be an array or an object that implements Countable PHP Warning: count(): Parameter must be an array or an object that implements Countable PHP Warning: count(): Parameter must be an array or an object that implements Countable int(1) int(1) int(1) int(2) # PHP < 7.2 int(1) int(1) int(1) int(2) # Improved SSL/TLS defaults Protocol: tls:"// now defaults to TLSv1.0 or TLSv1.1 or TLSv1.2 Protocol ssl:"// is an alias of tls:"// STREAM_CRYPTO_METHOD_TLS_* constants default to TLSv1.0 or TLSv1.1 + TLSv1.2, instead of TLSv1.0 only
  39. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF BC BREAKS 47 # gettype on closed resources $resource = fopen( 'php:"//memory', 'rb' ); var_dump( gettype( $resource ) ); fclose( $resource ); var_dump( gettype( $resource ) ); # Prints string(8) "resource" string(17) "resource (closed)" # PHP < 7.2 string(8) "resource" string(12) "unknown type" Previously, using is_object() on the "__PHP_Incomplete_Class class would return FALSE. Now, TRUE will be returned. Unqualified references to undefined constants will now generate an E_WARNING (instead of an E_NOTICE). In the next major version of PHP, they will generate Error exceptions. The officially supported, minimum Windows versions are now Windows 7 and Server 2008 R2. The object name was previously soft- reserved in PHP 7.0. This is now hard- reserved, prohibiting it from being used as a class, trait, or interface name. Support for NetWare has now been removed. \o/ The bcmod() function no longer truncates fractional numbers to integers. As such, its behavior now follows fmod(), rather than the % operator. For example bcmod('4', '3.5') now returns 0.5 instead of 1. The json_decode() function option, JSON_OBJECT_AS_ARRAY, is now used if the second parameter (assoc) is NULL. Previously, JSON_OBJECT_AS_ARRAY was always ignored. Sequences generated by rand() and mt_rand() for a specific seed may differ from PHP 7.1 on 64-bit machines (due to the fixing of a modulo bias bug in the implementation).
  40. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF DEPRECATIONS 49 # Undefined constants var_dump(NONEXISTENT); # Prints PHP Warning: Use of undefined constant NONEXISTENT - assumed 'NONEXISTENT' (this will throw an Error in a future version of PHP) string(11) "NONEXISTENT" # PHP < 7.2 Notice: Use of undefined constant NONEXISTENT - assumed 'NONEXISTENT' string(11) "NONEXISTENT" # assert with string argument $a = 1; var_dump( assert( '$a"==1' ) ); # Prints PHP Deprecated: assert(): Calling assert() with a string argument is deprecated bool(true) # PHP < 7.2 bool(true) # Magic autoload function !__autoload( $classname ) { echo $classname; } # Prints PHP Deprecated: !__autoload() is deprecated, use spl_autoload_register() instead # parse_str without 2nd argument parse_str( 'test=this' ); # Prints PHP Deprecated: parse_str(): Calling parse_str() without the result argument is deprecated When the track_errors ini setting is enabled, a $php_errormsg variable is created in the local scope when a non- fatal error occurs. Given that the preferred way of retrieving such error information is by using error_get_last(), this feature has been deprecated. create_function(): Given the security issues of this function (being a thin wrapper around eval()), this dated function has now been deprecated. The preferred alternative is to use anonymous functions. each(): This function is far slower at iteration than a normal foreach, and causes implementation issues for some language changes. It has therefore been deprecated. eval() "== evil!
  41. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF OTHER CHANGES 51 The utf8_encode() and utf8_decode() functions have now been moved to the standard extension as string functions, whereas before the XML extension was required for them to be available. The MCrypt extension has now been moved out of the core to PECL. Given the mcrypt library has not seen any updates since 2007, its usage is highly discouraged. Instead, either the OpenSSL or Sodium extension should be used.
  42. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF DEAD CODE ELIMINATION (DCE) 52 function test() { $a = 1; return 0; } $ php -d opcache.optimization_level=-1 -d opcache.opt_debug_level=0x20000 script.php # PHP 7.1 fn: (lines=2, args=0, vars=1, tmps=0) L0: ASSIGN CV0($a) int(1) L1: RETURN int(0) # PHP 7.2 fn: (lines=1, args=0, vars=0, tmps=0) L0: RETURN int(0)
  43. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF DEAD CODE ELIMINATION (DCE) 53 function foo( string $s1, string $s2, string $s3, string $s4 ) { $x = ($s1 . $s2) . ($s3 . $s4); $x = 0; return $x; } PHP 7.1 PHP 7.2 foo: (lines=10, args=4, vars=5, tmps=3) foo: (lines=5, args=4, vars=4, tmps=3) L0: CV0($s1) = RECV 1 L0: CV0($s1) = RECV 1 L1: CV1($s2) = RECV 2 L1: CV1($s2) = RECV 2 L2: CV2($s3) = RECV 3 L2: CV2($s3) = RECV 3 L3: CV3($s4) = RECV 4 L3: CV3($s4) = RECV 4 L4: T6 = CONCAT CV0($s1) CV1($s2) L4: RETURN int(0) L5: T7 = CONCAT CV2($s3) CV3($s4) L6: T5 = CONCAT T6 T7 L7: ASSIGN CV4($x) T5 L8: ASSIGN CV4($x) int(0) L9: RETURN CV4($x)
  44. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF DEAD CODE ELIMINATION (DCE) 54 CraPHPy code executed even faster now!
  45. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF SWITCH-CASE OPTIMIZATION 55 $cc = 'no'; switch ( $cc ) { case 'de': echo 'Deutsch'; break; case 'en': echo 'English'; break; case 'nl': echo 'Nederlands'; break; case 'no': echo 'Norsk'; break; default: echo 'unknown'; break; } if ( $cc !!=== 'de' ) { echo 'Deutsch'; } else { if ( $cc !!=== 'en' ) { echo 'English'; } else { if ( $cc !!=== 'nl' ) { echo 'Nederlands'; } else { if ( $cc !!=== 'no' ) { echo 'Norsk'; } else { echo 'unknown'; } } } } PHP 7.1 PHP 7.2
  46. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF SWITCH-CASE OPTIMIZATION 56 $table = [ 'de' !=> 1, 'en' !=> 2, 'nl' !=> 3, 'no' !=> 4 ]; if ( gettype( $cc ) !!=== 'string' ) { if ( array_key_exists( $cc, $table ) ) { goto "jmp_{$table[$cc]}"; } else { goto jmp_default; } } else { !/* do original if/else if/else sequence !*/ } jmp_1: echo "DEUTSCH"; goto end; jmp_2: echo "English"; goto end; jmp_3: echo "Nederlands"; goto end; jmp_4: echo "Norsk"; goto end; jmp_default: echo "unknown"; end: ๏ PSEUDO-CODE ๏ OPTIMIZATION APPLIES ONLY IF ALL KEYS ARE EITHER STRING OR INT
  47. GO GET YOU PHP 7.2 TODAY http:"//php.net/downloads.php MAC: brew install

    homebrew/php/php72-xdebug 
 WINDOWS: http:!//windows.php.net/download#php-7.2 DEBIAN: $ add-apt-repository ppa:ondrej/php # Update index $ apt-get update # Install php7.2-fpm with needed extensions $ apt-get install php7.2-fpm php7.2-cli php7.2-common php7.2-opcache !!...
  48. THANK YOU! github.com/hollodotme @hollodotme / @F9T3ch fortuneglobe.com phpug-dresden.org @phpugdd HOLGER

    WOLTERSDORF icehawk.github.io speakerdeck.com/hollodotme Slides available at:
  49. WHAT'S NEW IN PHP 7.2 • DECEMBER 19TH 2017 •

    PHP USERGROUP DRESDEN HOLGER WOLTERSDORF LINKS / REFERENCES 59 ๏ PHP Migrating from PHP 7.1.x to PHP 7.2.x: http://php.net/migration72 ๏ PHP 7.2.0 Release notes: http://php.net/ChangeLog-7.php#7.2.0 ๏ PHP Downloads: http://php.net/downloads.php#v7.2.0 ๏ Argon2 Algorithm Wikipedia: https://en.wikipedia.org/wiki/Argon2 ๏ PHP in 2018 by Rasmus Lerdorf: http://talks.php.net/ruhr17#/ ๏ Switch case optimization by Derick Rethans: https://derickrethans.nl/php7.2-switch.html ๏ PHP 7.2 news by Benjamin Cremer: https://talks.benjamin-cremer.de/phpugms_php72/#/ ๏ PHP 7.2.1 Changelog: http://git.php.net/?p=php- src.git;a=blob;f=NEWS;h=205e7ea9f90f7c4d4471ac0e7e70c50712815097;hb=refs/heads/PHP-7.2#l8 ๏ Code for this talk: https://github.com/hollodotme/talk-preps/tree/master/whats-new-in-php72