Pro Yearly is on sale from $80 to $50! »

PHP's Not Dead - PHP7 In Practice

PHP's Not Dead - PHP7 In Practice

33d8f6c5f5c8b940ff4d6422a5f32b02?s=128

Łukasz Szymański

August 20, 2016
Tweet

Transcript

  1. szymanskilukasz PHP7 in practice szymanskilukasz

  2. szymanskilukasz Łukasz Szymański Development Team Lead at @szymanskilukasz https://www.linkedin.com/in/szymanskilukasz https://twitter.com/szymanskilukasz

    https://speakerdeck.com/szymanskilukasz
  3. szymanskilukasz About OLX

  4. szymanskilukasz 40+ Countries

  5. szymanskilukasz +260 Milion Monthly Active Users

  6. szymanskilukasz 25 Milion Monthly Listings

  7. szymanskilukasz 8,5 Milion Monthly Transactions

  8. szymanskilukasz 4 mld Page Views Monthly in Poland

  9. szymanskilukasz Migration

  10. szymanskilukasz // PHP 5 era code that will break.
 function

    handler(Exception $e) { ... }
 set_exception_handler('handler');
 
 // PHP 5 and 7 compatible.
 function handler($e) { ... }
 
 // PHP 7 only.
 function handler(Throwable $e) { ... }
  11. szymanskilukasz Memcached Memcache

  12. szymanskilukasz $factory = new CacheWrapperFactory();
 $factory->createServer(
 extension_loaded('memcache') 
 ? 'memcache'

    : 'memcached',
 $uri
 );
  13. szymanskilukasz Memcache Serializer != Memcached Serializer

  14. szymanskilukasz memory object serialized by memcache serialization / deserialization application

    memcache memcached serialize deserialize x
  15. szymanskilukasz Question Time

  16. szymanskilukasz Restart

  17. szymanskilukasz APC

  18. szymanskilukasz APC is opcode cache and data store

  19. szymanskilukasz APC is opcode cache and data store APCu is

    only data store
  20. szymanskilukasz APC is opcode cache and data store APCu is

    only data store OPcache is only opcode cache
  21. szymanskilukasz APCu is APC stripped of opcode caching. APC is

    opcode cache and data store APCu is only data store OPcache is only opcode cache
  22. szymanskilukasz APCu Backward Compatible https://pecl.php.net/package/apcu_bc

  23. szymanskilukasz Issues with libs PHP7 support in general

  24. szymanskilukasz We were ready

  25. szymanskilukasz Promises

  26. szymanskilukasz source: http://www.zend.com/en/resources/php7_infographic

  27. szymanskilukasz source: http://www.zend.com/en/resources/php7_infographic

  28. szymanskilukasz source: http://www.zend.com/en/resources/php7_infographic

  29. szymanskilukasz source: http://www.zend.com/en/resources/php7_infographic

  30. szymanskilukasz Effects

  31. szymanskilukasz 20 Physical Servers 32 CPU Cores for Apache OLX.PL

  32. szymanskilukasz CPU

  33. szymanskilukasz CPU ~ 50% -> 20%

  34. szymanskilukasz Load

  35. szymanskilukasz Load ~ 16 -> 5

  36. szymanskilukasz Now we can use 7 of them for something

    else OLX.PL
  37. szymanskilukasz Business

  38. szymanskilukasz Performance deep dive

  39. szymanskilukasz Memory Optimization

  40. szymanskilukasz Reduce Number Of Allocations

  41. szymanskilukasz Reduce Number Of Allocations PHP5 spends 20% of CPU

    time in allocator
  42. szymanskilukasz Reduce Memory Usage

  43. szymanskilukasz CPU L1D L2 L3 RAM 32KB 256KB few MB

    1ns 4ns 12ns 100ns
  44. szymanskilukasz Reduce Indirection

  45. szymanskilukasz Pointer points to pointer etc.

  46. szymanskilukasz Code

  47. szymanskilukasz Scalar type declarations

  48. szymanskilukasz class PHPisNotDead
 {
 public function addIntegers($a, $b) {
 return

    $a + $b;
 }
 
 public function addFloats($a, $b) {
 return $a + $b;
 }
 
 public function reverseString($a) {
 return strrev($a);
 }
 
 public function isItTrue($a) {
 return $a ? 'yes' : 'no';
 }
 } PHP5
  49. szymanskilukasz class PHPisNotDead
 {
 public function addIntegers(MyInteger $a, MyInteger $b)

    {
 return $a + $b;
 }
 
 public function addFloats(MyFloat $a, MyFloat $b) {
 return $a + $b;
 }
 
 public function reverseString(MyString $a) {
 return strrev($a);
 }
 
 public function isItTrue($a) {
 return $a ? 'yes' : 'no';
 }
 } PHP5 + Value Objects
  50. szymanskilukasz PHP7 class PHPisNotDead
 {
 public function addIntegers(int $a, int

    $b) : int {
 return $a + $b;
 }
 
 public function addFloats(float $a, float $b) : float {
 return $a + $b;
 }
 
 public function reverseString(string $a) : string {
 return strrev($a);
 }
 
 public function isItTrue(bool $a) : string {
 return $a ? 'yes' : 'no';
 }
 }
  51. szymanskilukasz

  52. szymanskilukasz Not Really

  53. szymanskilukasz PHP7 class PHPisNotDead
 {
 public function addIntegers(int $a, int

    $b) : int {
 return $a + $b;
 }
 
 public function addFloats(float $a, float $b) : float {
 return $a + $b;
 }
 
 public function reverseString(string $a) : string {
 return strrev($a);
 }
 
 public function isItTrue(bool $a) : string {
 return $a ? 'yes' : 'no';
 }
 }
  54. szymanskilukasz PHP7 $php = new PHPisNotDead(); 
 var_dump($php->addIntegers(1.3, 5.7)); //

    int(6)
 var_dump($php->addFloats(4, '3.4')); // double(7.4)
 var_dump($php->reverseString(12345)); // string(5) "54321"
 var_dump($php->isItTrue(21.37)); // string(3) "yes"
  55. szymanskilukasz PHP7 $php = new PHPisNotDead(); 
 var_dump($php->addIntegers(1.3, 5.7)); //

    int(6)
 var_dump($php->addFloats(4, '3.4')); // double(7.4)
 var_dump($php->reverseString(12345)); // string(5) "54321"
 var_dump($php->isItTrue(21.37)); // string(3) "yes" WTF?
  56. szymanskilukasz PHP7 $php = new PHPisNotDead(); 
 var_dump($php->addIntegers(1.3, 5.7)); //

    int(6)
 var_dump($php->addFloats(4, '3.4')); // double(7.4)
 var_dump($php->reverseString(12345)); // string(5) "54321"
 var_dump($php->isItTrue(21.37)); // string(3) "yes" Coercive Mode (default)
  57. szymanskilukasz public function addIntegers(int $a,int $b) : int {
 return

    $a + $b;
 } 
 public function addIntegers($a, $b) { 
 $a = (int) $a; 
 $b = (int) $b; 
 return (int) ($a + $b);
 } PHP7
  58. szymanskilukasz public function addIntegers(int $a,int $b) : int {
 return

    $a + $b;
 } 
 public function addIntegers($a, $b) { 
 $a = (int) $a; 
 $b = (int) $b; 
 return (int) ($a + $b);
 } PHP7
  59. szymanskilukasz declare (strict_types=1);

  60. szymanskilukasz declare (strict_types=1); class PHPisNotDead
 {
 public function addIntegers(int $a,

    int $b) : int {
 return $a + $b;
 }
 
 public function addFloats(float $a, float $b) : float {
 return $a + $b;
 }
 
 public function reverseString(string $a) : string {
 return strrev($a);
 }
 
 public function isItTrue(bool $a) : string {
 return $a ? 'yes' : 'no';
 }
 } PHPisNotDead.php
  61. szymanskilukasz

  62. szymanskilukasz Not Even Close

  63. szymanskilukasz index.php require "PHPisNotDead.php";
 
 $php = new PHPisNotDead();
 var_dump($php->addIntegers(1.3,

    5.7)); // int(6)
 var_dump($php->addFloats(4, '3.4')); // double(7.4)
 var_dump($php->reverseString(12345)); // string(5) "54321"
 var_dump($php->isItTrue(21.37)); // string(3) "yes"
  64. szymanskilukasz index.php require "PHPisNotDead.php";
 
 $php = new PHPisNotDead();
 var_dump($php->addIntegers(1.3,

    5.7)); // int(6)
 var_dump($php->addFloats(4, '3.4')); // double(7.4)
 var_dump($php->reverseString(12345)); // string(5) "54321"
 var_dump($php->isItTrue(21.37)); // string(3) "yes" WTF2?
  65. szymanskilukasz declare (strict_types=1); class PHPisNotDead
 {
 public function addIntegers(int $a,

    int $b) : int {
 return $a + $b;
 }
 
 public function addFloats(float $a, float $b) : float {
 return $a + $b;
 }
 
 public function reverseString(string $a) : string {
 return strrev($a);
 }
 
 public function isItTrue(bool $a) : string {
 return $a ? 'yes' : 'no';
 }
 } PHPisNotDead.php
  66. szymanskilukasz declare (strict_types=1); class PHPisNotDead
 {
 public function addIntegers(int $a,

    int $b) : int {
 return $a + $b;
 }
 
 public function addFloats(float $a, float $b) : float {
 return $a + $b;
 }
 
 public function reverseString(string $a) : string {
 return strrev($a);
 }
 
 public function isItTrue(bool $a) : string {
 return $a ? 'yes' : 'no';
 }
 } PHPisNotDead.php
  67. szymanskilukasz PHPisNotDead.php declare (strict_types = 1);
 
 class PHPisNotDead
 {


    public function addIntegers(int $a, int $b) : int {
 return (string) ($a + $b);
 }
 
 public function addFloats(float $a, float $b) : float {
 return $a + $b;
 }
 
 public function reverseString(string $a) : string {
 return strrev($a);
 }
 
 public function isItTrue(bool $a) : string {
 return $a ? 'yes' : 'no';
 }
 }
  68. szymanskilukasz Fatal error: Uncaught TypeError: Return value of PHPisNotDead::addIntegers() must

    be of the type integer, string returned
  69. szymanskilukasz declare (strict_types = 1);
 
 require "PHPisNotDead.php";
 
 $php

    = new PHPisNotDead();
 var_dump($php->addIntegers(1.3, 5.7));
 var_dump($php->addFloats(4, '3.4'));
 var_dump($php->reverseString(12345));
 var_dump($php->isItTrue(21.37));
  70. szymanskilukasz declare (strict_types = 1);
 
 require "PHPisNotDead.php";
 
 $php

    = new PHPisNotDead();
 var_dump($php->addIntegers(1.3, 5.7));
 var_dump($php->addFloats(4, '3.4'));
 var_dump($php->reverseString(12345));
 var_dump($php->isItTrue(21.37));
  71. szymanskilukasz TypeError: Argument 1 passed to PHPisNotDead::addIntegers() must be of

    the type integer, float given
  72. szymanskilukasz Errors & Exceptions

  73. szymanskilukasz $php = new PHPisNotDead();
 try {
 var_dump($php->addIntegers(1.3, 5.7)); }

    catch (TypeError $error) {
 echo $error->getMessage();
 } catch (Error $error) {
 echo $error->getMessage();
 } catch (Exception $exception) {
 echo $exception->getMessage();
 } catch (Throwable $throwable) {
 echo $throwable->getMessage();
 }
  74. szymanskilukasz (float)

  75. szymanskilukasz var_dump((float) "php");

  76. szymanskilukasz PHP5.6 ? var_dump((float) "php");

  77. szymanskilukasz PHP5.6 float(0) var_dump((float) "php");

  78. szymanskilukasz PHP5.6 float(0) PHP7.0 ? var_dump((float) "php");

  79. szymanskilukasz PHP5.6 float(0) PHP7.0 var_dump((float) "php"); float(0)

  80. szymanskilukasz var_dump((float) "nananana");

  81. szymanskilukasz var_dump((float) "nananana"); PHP5.6 ?

  82. szymanskilukasz var_dump((float) "nananana"); PHP5.6 float(0)

  83. szymanskilukasz var_dump((float) "nananana"); PHP5.6 float(0) PHP7.0 ?

  84. szymanskilukasz var_dump((float) "nananana"); PHP5.6 float(0) PHP7.0 float(NAN)

  85. szymanskilukasz Future

  86. szymanskilukasz http://php.net/supported-versions.php

  87. szymanskilukasz PHP7.1

  88. szymanskilukasz Void Return Type

  89. szymanskilukasz function should_return_nothing(): void {
 return 1; // Fatal error:

    A void function must not return a value
 }
 
 function lacks_return(): void {
 // valid
 }
 
 function returns_nothing(): void {
 return; // valid
 }
 
 function returns_null(): void {
 return null; // Fatal error: A void function must not return a value
 }
 
 function foobar(void $foo) {}
 // Fatal error: void cannot be used as a parameter type
  90. szymanskilukasz checked at compile-time error is produced without the function

    needing to be called.
  91. szymanskilukasz Class Constant Visibility

  92. szymanskilukasz class Token {
 // Constants default to public
 const

    PUBLIC_CONST = 0;
 
 // Constants then also can have a defined visibility
 private const PRIVATE_CONST = 0;
 protected const PROTECTED_CONST = 0;
 public const PUBLIC_CONST_TWO = 0;
 
 //Constants can only have one visibility declaration list
 private const FOO = 1, BAR = 2;
 }
  93. szymanskilukasz //Interfaces only support public consts, // and a compile

    time error will be thrown // for anything else. // Mirroring the behavior of methods. 
 interface ICache {
 public const PUBLIC = 0;
 const IMPLICIT_PUBLIC = 1;
 }
  94. szymanskilukasz Nullable Types

  95. szymanskilukasz function answer(): ?int {
 return null; //ok
 }
 


    function answer(): ?int {
 return 42; // ok
 }
 
 function answer(): ?int {
 return new stdclass(); // error
 }
  96. szymanskilukasz function say(?string $msg) {
 if ($msg) {
 echo $msg;


    }
 }
 
 say('hello'); // ok -- prints hello
 say(null); // ok -- does not print
 say(); // error -- missing parameter
 say(new stdclass); //error -- bad type
  97. szymanskilukasz // nullability can be removed by a subclass interface

    Fooable {
 function foo(): ?Fooable;
 }
 interface StrictFooable extends Fooable {
 function foo(): Fooable; // valid
 }
  98. szymanskilukasz // but it cannot be added interface Fooable {


    function foo(): Fooable;
 }
 interface LooseFooable extends Fooable {
 function foo(): ?Fooable; // invalid
 }
  99. szymanskilukasz // Valid use: loosening the nullable marker // in

    a parameter: 
 interface Fooable {
 function foo(Fooable $f);
 }
 interface LooseFoo extends Fooable {
 function foo(?Fooable $f);
 }
  100. szymanskilukasz // Invalid use: tightening // the nullable marker in

    a parameter:
 interface Fooable {
 function foo(?Fooable $f);
 }
 interface StrictFoo extends Fooable {
 function foo(Fooable $f);
 }
  101. szymanskilukasz Iterable pseudo-type

  102. szymanskilukasz // If a value is not an array or

    instance of Traversable,
 // a TypeError will be thrown.
 function foo(iterable $iterable) {
 foreach ($iterable as $value) {
 // ...
 }
 }
 
 // If the returned value is not an array
 // or instance of Traversable, a TypeError will be thrown.
 function bar(): iterable {
 return [1, 2, 3];
 }
 
 // Parameters declared as iterable
 // may use null or an array as a default value
 function foo(iterable $iterable = []) {
 // ...
 }
  103. szymanskilukasz Under Discussion

  104. szymanskilukasz Class Friendship Created 2015/12/10

  105. szymanskilukasz class Person
 {
 friend HumanResourceReport;
 
 protected $id;
 protected

    $firstName;
 protected $lastName;
 
 public function __construct($id, $firstName, $lastName)
 {
 $this->id = $id;
 $this->firstName = $firstName;
 $this->lastName = $lastName;
 }
 
 public function makeReport()
 {
 return new HumanResourceReport($this);
 }
 }
  106. szymanskilukasz class HumanResourceReport
 {
 private $person;
 
 public function __construct(Person

    $person)
 {
 $this->person = $person;
 }
 
 public function getFullName()
 {
 // HumanResourceReport would not have access to protected 
 // members of Person if not explicitly listed as a friend.
 return $this->person->firstName . ' ' . $this->person->lastName;
 }
 
 public function getReportIdentifier()
 {
 return "HR_REPORT_ID_{$this->person->id}";
 }
 }
  107. szymanskilukasz class HumanResourceReport
 {
 private $person;
 
 public function __construct(Person

    $person)
 {
 $this->person = $person;
 }
 
 public function getFullName()
 {
 // HumanResourceReport would not have access to protected 
 // members of Person if not explicitly listed as a friend.
 return $this->person->firstName . ' ' . $this->person->lastName;
 }
 
 public function getReportIdentifier()
 {
 return "HR_REPORT_ID_{$this->person->id}";
 }
 }
  108. szymanskilukasz $person = new Person(Uuid::uuid4(), 'Alice', 'Wonderland');
 $report = $person->makeReport();


    
 var_dump($report->getFullName()); 
 // string(16) "Alice Wonderland"
 var_dump($report->getReportIdentifier()); 
 // string(49) "HR_REPORT_ID_3F2504E0-4F89-41D3-9A0C-0305E82C3301"
  109. szymanskilukasz Named Parameters Created 2013/09/06

  110. szymanskilukasz // Using positional arguments:
 array_fill(0, 100, 42);
 // Using

    named arguments:
 array_fill(start_index => 0, num => 100, value => 42);
  111. szymanskilukasz htmlspecialchars($string, default, default, false);
 // vs
 htmlspecialchars($string, double_encode =>

    false);
 
 $str->contains("foo", true);
 // vs
 $str->contains("foo", caseInsensitive => true);
  112. szymanskilukasz Generic Types and Functions Created 2015/04/28

  113. szymanskilukasz class Entry<KeyType, ValueType>
 {
 protected $key;
 protected $value;
 


    public function __construct(KeyType $key, ValueType $value)
 {
 $this->key = $key;
 $this->value = $value;
 }
 
 public function getKey(): KeyType
 {
 return $this->key;
 }
 
 public function getValue(): ValueType
 {
 return $this->value;
 }
 }
  114. szymanskilukasz class Entry<KeyType, ValueType>
 {
 protected $key;
 protected $value;
 


    public function __construct(KeyType $key, ValueType $value)
 {
 $this->key = $key;
 $this->value = $value;
 }
 
 public function getKey(): KeyType
 {
 return $this->key;
 }
 
 public function getValue(): ValueType
 {
 return $this->value;
 }
 }
  115. szymanskilukasz $entry = new Entry<int,string>(1, 'test');
 
 $entry = new

    Entry(1, 'test');
  116. szymanskilukasz In Draft

  117. szymanskilukasz Immutable classes and properties

  118. szymanskilukasz class Email {
 private $_email;
 
 public function __construct

    ($email) {
 // validation
 
 $this->_email = $email;
 }
 
 public function getValue() {
 return $this->_email;
 }
 }
  119. szymanskilukasz immutable class Email {
 public $email;
 
 public function

    __construct ($email) {
 // validation
 
 $this->email = $email;
 }
 }
  120. szymanskilukasz immutable class Email {
 public $email;
 
 public function

    __construct ($email) {
 // validation
 
 $this->email = $email;
 }
 }
  121. szymanskilukasz immutable class Email {
 public $email;
 
 public function

    __construct ($email) {
 // validation
 
 $this->email = $email;
 }
 }
  122. szymanskilukasz immutable class Email {
 public $email;
 
 public function

    __construct ($email) {
 // validation
 
 $this->email = $email;
 }
 }
 
 $email = new Email("foo@php.net");
 $email->email = "bar@php.net" // Call will result in Fatal Error
  123. szymanskilukasz class Email {
 public immutable $email;
 
 public function

    __construct ($email) {
 // validation
 
 $this->email = $email;
 }
 }
 
 $email = new Email("foo@php.net");
 $email->email = "bar@php.net" // Call will result in Fatal Error
  124. szymanskilukasz Property type-hints

  125. szymanskilukasz class BoxedInt {
 public int $value;
 }
 
 $i

    = new BoxedInt();
 $i->value = 'oops'; 
 // Catchable fatal error:
 // property BoxedInt::$value must be of
 // the type integer, string given
  126. szymanskilukasz

  127. szymanskilukasz Performance

  128. szymanskilukasz Code Quality

  129. szymanskilukasz Bright Future

  130. szymanskilukasz Łukasz Szymański Development Team Lead at @szymanskilukasz https://www.linkedin.com/in/szymanskilukasz https://twitter.com/szymanskilukasz

    https://speakerdeck.com/szymanskilukasz
  131. szymanskilukasz http://www.slideshare.net/nikita_ppv/php-7-what-changed-internally-php-barcelona-2015 http://www.phpinternalsbook.com/ resources http://php.net/manual/en/migration70.new-features.php https://wiki.php.net/ http://www.zend.com/en/resources/php7_infographic