Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

What's new in PHP 8.0?

8,073 views

Published on

PHP 8.0 is expected to be released by the end of the year, so it’s time to take a first look at the next major version of PHP. Attributes, union types, and a just-in-time compiler are likely the flagship features of this release, but there are many more improvements to be excited about. As PHP 8.0 is a major version, this release also includes backwards-incompatible changes, many of which are centered around stricter error handling and more type safety.

Presentation from phpfwdays 2020.

Published in: Technology
  • Be the first to comment

What's new in PHP 8.0?

  1. 1. Release schedule (tentative) June 18th PHP 8.0 Alpha 1 July 28th PHP 8.0 Feature freeze December 3rd PHP 8.0 Release
  2. 2. Just-In-Time (JIT) Compiler ● Compiles PHP code to x86 machine code ● Performance improvements mostly apply to math heavy code
  3. 3. Just-In-Time (JIT) Compiler ● Compiles PHP code to x86 machine code ● Performance improvements mostly apply to math heavy code ● Part of opcache: – opcache.jit=on – opcache.jit_buffer_size=128M
  4. 4. Attributes <?php /** @Entity */ class User { /** * @Id * @Column(type="integer") * @GeneratedValue */ private $id; }
  5. 5. Attributes <?php use DoctrineORMAttributes as ORM; <<ORMEntity>> class User { <<ORMId>> <<ORMColumn("integer")>> <<ORMGeneratedValue>> private $id; }
  6. 6. Attributes <?php use DoctrineORMAttributes as ORM; <<ORMEntity>> class User { <<ORMId>> <<ORMColumn("integer")>> <<ORMGeneratedValue>> private $id; } Class name Constructor arguments
  7. 7. Attributes <?php namespace DoctrineORMAttributes; use PhpAttribute; <<PhpAttribute>> class Column { public function __construct(string $type) { … } }
  8. 8. Attributes <?php $rc = new ReflectionClass(User::class); foreach ($rc->getAttributes() as $attr) { var_dump($attr->getName()); // => "DoctrineORMAttributesEntity" var_dump($attr->getArguments()); // => [] var_dump($attr->newInstance()); // object(DoctrineORMAttributesEntity) ... }
  9. 9. Attributes <?php $rc = new ReflectionClass(User::class); foreach ($rc->getAttributes() as $attr) { var_dump($attr->getName()); // => "DoctrineORMAttributesEntity" var_dump($attr->getArguments()); // => [] var_dump($attr->newInstance()); // object(DoctrineORMAttributesEntity) ... } Attribute validation happens HERE.
  10. 10. Attributes: Limitations ● No named parameters: – @Column(type="string", unique=true) – <<Column("string", ['unique' => true])>>
  11. 11. Attributes: Limitations ● No named parameters: – @Column(type="string", unique=true) – <<Column("string", ['unique' => true])>> ● No nested attributes: – @AssertAll({ @AssertNotBlank, @AssertLength(min=5) })
  12. 12. Attributes: Limitations ● No named parameters: – @Column(type="string", unique=true) – <<Column("string", ['unique' => true])>> ● No nested attributes: – @AssertAll({ @AssertNotBlank, @AssertLength(min=5) }) "new" currently not supported in constant expressions
  13. 13. Attributes: Use-Cases ● Replaces phpdoc annotations in Doctrine, Symfony, etc… ● May add internal attributes: – <<Deprecated("Use xyz instead")>> – <<Jit>>, <<NoJit>>
  14. 14. Union Types ● Existing union types: – ?Type = Type|null – iterable = Traversable|array
  15. 15. Union Types <?php class Number { /** @var int|float $number */ private $number; /** @param int|float $number */ public function setNumber($number) { $this->number = $number; } /** @return int|float */ public function getNumber() { return $this->number; } }
  16. 16. Union Types <?php class Number { private int|float $number; public function setNumber(int|float $number) { $this->number = $number; } public function getNumber(): int|float { return $this->number; } }
  17. 17. Union Types <?php function strpos( string $haystack, string $needle, int $offset = 0 ): int|false {}
  18. 18. Union Types <?php function strpos( string $haystack, string $needle, int $offset = 0 ): int|false {} Very common in standard library
  19. 19. Union Types <?php function strpos( string $haystack, string $needle, int $offset = 0 ): int|false {} function array_key_first(array $arg): int|string|null {} ?Type is a shorthand for Type|null now
  20. 20. Union Types ● Tricky interaction with "weak types" ● Type must be part of union, or... ● Scalars are coerced to int, float, string, bool, in order of preference
  21. 21. Union Types <?php declare(strict_types=0); function test(int|float|bool $arg) { var_dump($arg); } test(45); // int(45) test(45.8); // float(45.8) test("45"); // int(45) test("45.8"); // float(45.8) test(""); // bool(false) test("X"); // bool(true) test([]); // TypeError
  22. 22. Union Types <?php declare(strict_types=1); function test(int|float|bool $arg) { var_dump($arg); } test(45); // int(45) test(45.8); // float(45.8) test("45"); // TypeError test("45.8"); // TypeError test(""); // TypeError test("X"); // TypeError test([]); // TypeError
  23. 23. Mixed Type ● Distinguishes between: – Type is missing because I didn't add one yet – This function really does accept any value
  24. 24. Mixed Type <?php function var_dump(mixed $value, mixed ...$value): void {} function serialize(mixed $value): string {}
  25. 25. Mixed Type <?php // Mixed is a common approximation for generic functions: function array_reduce<K, V, R>( array<K, V> $arg, callable(R, V): R $callback, R $initial = null ): R {}
  26. 26. Mixed Type <?php // Mixed is a common approximation for generic functions: function array_reduce<K, V, R>( array<K, V> $arg, callable(R, V): R $callback, R $initial = null ): R {} // Back down to earth: function array_reduce( array $arg, callable $callback, mixed $initial = null ): mixed {}
  27. 27. Mixed Type <?php // For argument types: // No type same as mixed type class A { public function method(mixed $arg) {} } class B extends A { public function method($arg) {} } Allowed
  28. 28. Mixed Type <?php // For return types: // No type effectively means mixed|void class A { public function method(): mixed {} } class B extends A { public function method() {} }
  29. 29. Mixed Type <?php // For return types: // No type effectively means mixed|void class A { public function method(): mixed {} } class B extends A { public function method() {} } Forbidden: Widening return type
  30. 30. Static Return Type <?php // Named constructor: class TestParent { public function createFromWhatever($whatever): static { return new static($whatever); } }
  31. 31. Static Return Type <?php // Named constructor: class TestParent { public function createFromWhatever($whatever): static { return new static($whatever); } } class TestChild extends TestParent {} // TestChild::createFromWhatever(…) // must return TestChild, not TestParent!
  32. 32. Static Return Type <?php // Wither pattern: class Test { public function withWhatever($whatever): static { $clone = clone $this; $clone->whatever = $whatever; return $clone; } }
  33. 33. Static Return Type <?php // Fluent methods: class Test { public function doWhatever(): static { // Do whatever. return $this; } }
  34. 34. Constructor Promotion <?php class Point { public float $x; public float $y; public float $z; public function __construct( float $x = 0.0, float $y = 0.0, float $z = 0.0, ) { $this->x = $x; $this->y = $y; $this->z = $z; } }
  35. 35. Constructor Promotion <?php class Point { public function __construct( public float $x = 0.0, public float $y = 0.0, public float $z = 0.0, ) {} }
  36. 36. Constructor Promotion <?php class Point { public function __construct( public float $x = 0.0, public float $y = 0.0, public float $z = 0.0, ) {} } Trailing comma in parameters lists now allowed
  37. 37. str_contains etc. <?php function str_contains( string $haystack, string $needle ): bool { return false !== strpos($haystack, $needle); }
  38. 38. str_contains etc. <?php function str_contains( string $haystack, string $needle ): bool {} function str_starts_with( string $haystack, string $needle ): bool {} function str_ends_with( string $haystack, string $needle ): bool {}
  39. 39. str_contains etc. ● No multibyte variants ● All of these functions are safe to use on UTF-8! (If you don't use UTF-8, that's your problem)
  40. 40. WeakMap <?php $map = new WeakMap; $obj = new stdClass; $map[$obj] = $dataForObj; unset($obj); // $obj automatically dropped from WeakMap!
  41. 41. WeakMap <?php class FooBar { private WeakMap $cache; public function getSomethingWithCaching(object $obj) { return $this->cache[$obj] ??= $this->computeSomethingExpensive($obj); } }
  42. 42. Backwards Compatibility Breaks ● Everything deprecated before PHP 8.0 has been removed! ● Full list: https://github.com/php/php-src/blob/master/UPGRADING
  43. 43. Resource To Object Migration ● Long term goal: Convert all resources to objects ● Objects are type-safe and have much better internal support
  44. 44. Resource To Object Migration ● Long term goal: Convert all resources to objects ● Objects are type-safe and have much better internal support (This is why we do not support a "resource" type.)
  45. 45. Resource To Object Migration ● Usually based on "opaque objects" ● Actual object-oriented APIs may be added later
  46. 46. Resource To Object Migration ● Migrated in previous versions – EnchantBroker, EnchantDictionary – GdImage – SysvMessageQueue – SysvSemaphore – XmlParser – XmlWriter (already had an OO API) – … more are in progress
  47. 47. Resource To Object Migration <?php $image = imagecreatefrompng($path); if (!is_resource($image)) { throw new MalformedImageException; }
  48. 48. Resource To Object Migration <?php $image = imagecreatefrompng($path); if (!is_resource($image)) { throw new MalformedImageException; } Now a GdImage object on success We'll always throw...
  49. 49. Resource To Object Migration <?php $image = imagecreatefrompng($path); if (false === $image) { throw new MalformedImageException; }
  50. 50. Warning → Error exception ● Many warnings converted to Error exceptions – TypeError – ValueError
  51. 51. Warning → Error exception ● Only allowed for error conditions that imply programmer error ● It makes no sense to "handle" the error, code needs to be fixed instead
  52. 52. Warning → Error exception <?php var_dump(strlen([])); // Warning: strlen() expects parameter 1 to be string, // array given // NULL function strlen(string $str): int|null {}
  53. 53. Warning → Error exception <?php var_dump(strlen([])); // Uncaught TypeError: strlen(): Argument #1 ($str) // must be of type string, array given function strlen(string $str): int {}
  54. 54. Warning → Error exception <?php var_dump(array_fill(0, -100, "foobar")); // Warning: array_fill(): Number of elements can't // be negative // bool(false) function array_fill( int $start_index, int $num, mixed $value ): array|false {}
  55. 55. Warning → Error exception <?php var_dump(array_fill(0, -100, "foobar")); // Uncaught ValueError: array_fill(): Argument #2 ($num) // must be greater than or equal to 0 function array_fill( int $start_index, int $num, mixed $value ): array {}
  56. 56. Warning → Error exception <?php var_dump(fopen("does_not_exist.txt", "r")); // Warning: fopen(does_not_exist.txt): // Failed to open stream: No such file or directory // bool(false)
  57. 57. Warning → Error exception <?php var_dump(fopen("does_not_exist.txt", "r")); // Warning: fopen(does_not_exist.txt): // Failed to open stream: No such file or directory // bool(false) NOT going to change! fopen() failure is an environment failure condition, it does not imply programmer error!
  58. 58. PHP Stubs ● PHP stub files specify function signatures for internal functions/methods ● Used to generate C code for function registration
  59. 59. PHP Stubs <?php function array_search( mixed $needle, array $haystack, bool $strict = false ): int|string|false {}
  60. 60. PHP Stubs <?php function array_search( mixed $needle, array $haystack, bool $strict = false ): int|string|false {} ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX( arginfo_array_search, 0, 2, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, needle, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, haystack, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE( 0, strict, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO()
  61. 61. PHP Stubs ● Data available through Reflection: – ReflectionFunction::getReturnType() – ReflectionParameter::getType() – ReflectionParameter::getDefaultValue()
  62. 62. PHP Stubs <?php // Stub class DateTime implements DateTimeInterface { /** @return DateTime */ public function add(DateInterval $interval) {} } // Your code class MyDateTime extends DateTime { public function add(DateInterval $interval) { // Do something } }
  63. 63. PHP Stubs <?php // Stub class DateTime implements DateTimeInterface { /** @return DateTime */ public function add(DateInterval $interval) {} } // Your code class MyDateTime extends DateTime { public function add(DateInterval $interval) { // Do something } } Now allowed!
  64. 64. PHP Stubs <?php // Stub class DateTime implements DateTimeInterface { /** @return DateTime */ public function add(DateInterval $interval) {} } // Your code class MyDateTime extends DateTime { public function add(DateInterval $interval) { // Do something } } Now allowed! A real return type would force all extending classes to specify it.
  65. 65. 3v4l.org
  66. 66. Travis CI php: - nightly install: - | if [ $TRAVIS_PHP_VERSION = 'nightly' ]; then composer install --ignore-platform-reqs; else composer install; fi Many libraries are not formally compatible with PHP 8 (yet)
  67. 67. Docker ● https://github.com/devilbox/docker-php-fpm-8.0
  68. 68. Thank You!

×