What's new in PHP 8.0?

如果无法正常显示,请先停止浏览器的去广告插件。
分享至:
1. What's new in PHP 8.0? Nikita Popov @ PhpConChina 2020
2.
3. PHP 8.0 ● Planned release date: November 26th ● Large number of new features ● Backwards-compatibility breaks
4. Just-In-Time (JIT) Compiler ● ● Compiles PHP code to x86 machine code Performance improvement depends on type of code
5. Just-In-Time (JIT) Compiler ● ● Compiles PHP code to x86 machine code Performance improvement depends on type of code – WordPress: ~5% improvement – PHP-Parser: 2x faster
6. Just-In-Time (JIT) Compiler ● Compiles PHP code to x86 machine code ● Part of opcache: – opcache.jit=on – opcache.jit_buffer_size=128M
7. Attributes <?php /** @Entity */ class User { /** * @Id * @Column(type="integer") * @GeneratedValue */ private $id; }
8. Attributes <?php use Doctrine\ORM\Attributes as ORM; #[ORM\Entity] class User { #[ORM\Id] #[ORM\Column("integer")] #[ORM\GeneratedValue] private $id; }
9. Attributes <?php use Doctrine\ORM\Attributes as ORM; Class name #[ORM\Entity] class User { Constructor arguments #[ORM\Id] #[ORM\Column("integer")] #[ORM\GeneratedValue] private $id; }
10. Attributes <?php namespace Doctrine\ORM\Attributes; use Attribute; #[Attribute] class Column { public function __construct(string $type) { … } }
11. Attributes <?php namespace Doctrine\ORM\Attributes; use Attribute; #[Attribute(Attribute::TARGET_PROPERTY)] class Column { public function __construct(string $type) { … } }
12. Attributes <?php $rc = new ReflectionProperty(User::class, "id"); foreach ($rc->getAttributes() as $attr) { var_dump($attr->getName()); // => "Doctrine\ORM\Attributes\Column" var_dump($attr->getArguments()); // => ["integer"] } var_dump($attr->newInstance()); // object(Doctrine\ORM\Attributes\Column)
13. Attributes <?php $rc = new ReflectionClass(User::class); foreach ($rc->getAttributes() as $attr) { var_dump($attr->getName()); // => "Doctrine\ORM\Attributes\Column" var_dump($attr->getArguments()); // => ["integer"] } var_dump($attr->newInstance()); // object(Doctrine\ORM\Attributes\Column) Attribute validation happens HERE.
14. 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; }
15. Constructor Promotion <?php class Point { public function __construct( public float $x = 0.0, public float $y = 0.0, public float $z = 0.0, ) {} }
16. 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
17. Named Arguments <?php // Using positional arguments: array_fill(0, 100, 50);
18. Named Arguments <?php // Using positional arguments: array_fill(0, 100, 50); // Using named arguments: array_fill(start_index: 0, count: 100, value: 50);
19. Named Arguments <?php // Using positional arguments: array_fill(0, 100, 50); // Using named arguments: array_fill(start_index: 0, count: 100, value: 50); // Order does not matter! array_fill(value: 50, count: 100, start_index: 0);
20. Named Arguments <?php // Using positional arguments: htmlspecialchars( $string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
21. Named Arguments <?php // Using positional arguments: htmlspecialchars( $string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); // Using named arguments: htmlspecialchars($string, double_encode: false);
22. Named Arguments <?php // Using positional arguments: htmlspecialchars( $string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); // Using named arguments: htmlspecialchars($string, double_encode: false); Can combine named & positional. But: Positional must come first. Can skip optional arguments.
23. Named Arguments <?php use Symfony\Component\Routing\Annotation\Route; class SomeController { /** * @Route("/path", name="action") */ public function someAction() { // ... } }
24. Named Arguments <?php use Symfony\Component\Routing\Annotation\Route; class SomeController { #[Route("/path", name: "action")] public function someAction() { // ... } }
25. Named Arguments <?php class Point { public function __construct( public float $x, public float $y, public float $z, ) {} } new Point(x: 2.0, y: 3.1, z: 4.2);
26. Named Arguments <?php class Point { public function __construct( public float $x, public float $y, public float $z, ) {} } $array = ["x" => 2.0, "y" => 3.1, "z" => 4.2]; new Point(...$array);
27. Named Arguments <?php function acceptsAnything(...$args) { var_dump($args); } acceptsAnything(1, 2, x: 3, y: 4); // $args = [1, 2, "x" => 3, "y" => 4]
28. Named Arguments <?php class A { public function method($name_a) {} } class B extends A { public function method($name_b) {} } // Error: Unknown named parameter $name_a (new B)->method(name_a: 42); Names not the same
29. 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; } }
30. 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; } }
31. Union Types <?php function strpos( string $haystack, string $needle, int $offset = 0 ): int|false {}
32. Union Types <?php function strpos( string $haystack, string $needle, int $offset = 0 ): int|false {} Very common in standard library
33. 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
34. 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
35. Union Types <?php declare(strict_types=0); function test(int|float|bool $arg) { var_dump($arg); } test(45); test(45.8); test("45"); test("45.8"); test(""); test("X"); test([]); // // // // // // // int(45) float(45.8) int(45) float(45.8) bool(false) bool(true) TypeError
36. Union Types <?php declare(strict_types=1); function test(int|float|bool $arg) { var_dump($arg); } test(45); test(45.8); test("45"); test("45.8"); test(""); test("X"); test([]); // // // // // // // int(45) float(45.8) TypeError TypeError TypeError TypeError TypeError
37. Mixed Type ● Distinguishes between: – Type is missing because I didn't add one yet – This function really does accept any value
38. Mixed Type <?php function var_dump(mixed $value, mixed ...$value): void {} function serialize(mixed $value): string {}
39. 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 {}
40. 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 {}
41. 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
42. 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() {} }
43. 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
44. Static Return Type <?php // Named constructor: class TestParent { public function createFromWhatever($whatever): static { return new static($whatever); } }
45. 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!
46. Static Return Type <?php // Wither pattern: class Test { public function withWhatever($whatever): static { $clone = clone $this; $clone->whatever = $whatever; return $clone; } }
47. Static Return Type <?php // Fluent methods: class Test { public function doWhatever(): static { // Do whatever. return $this; } }
48. Match Expression <?php switch ($operator) { case '+': $result = $a + $b; break; case '-': $result = $a - $b; break; case '*': $result = $a * $b; break; default: throw new UnsupportedOperator($operator); }
49. Match Expression <?php $result = match ($operator) { '+' => $a + $b, '-' => $a - $b, '*' => $a * $b, default => throw new UnsupportedOperator($operator); };
50. Match Expression <?php Expression with a return value $result = match ($operator) { '+' => $a + $b, '-' => $a - $b, '*' => $a * $b, default => throw new UnsupportedOperator($operator); };
51. Match Expression <?php Expression with a return value $result = match ($operator) { '+' => $a + $b, '-' => $a - $b, '*' => $a * $b, default => throw new UnsupportedOperator($operator), }; Each match clause is an expression ("throw" is an expression now)
52. Match Expression <?php function evalOp($operator, $a, $b) { return match ($operator) { '+' => $a + $b, '-' => $a - $b, '*' => $a * $b, }; } // Match is exhaustive: evalOp('/', 10, 2); // UnhandledMatchError
53. Match Expression <?php function evalOp($operator, $a, $b) { return match ($operator) { '+' => $a + $b, '-' => $a - $b, '*' => $a * $b, }; } // Match compares using ===, not ==. evalOp(true, 10, 2); // UnhandledMatchError
54. Nullsafe Operator <?php $name = $session !== null ? $session->getUser()->name : null; // Same as: $name = $session?->getUser()->name;
55. Nullsafe Operator <?php $name = $session?->getUser()?->name; // Approximately same as: $name = null; if ($session !== null) { $user = $session->getUser(); if ($user !== null) { $name = $user->name; } }
56. Other Features ● catch (Exception) without variable ● $object::class ● str_contains(), str_starts_with(), str_ends_with() ● get_debug_type() ● Stable sorting ● WeakMap
57. Backwards Compatibility Breaks ● ● Functionality deprecated before PHP 8.0 has been removed! Full list: https://github.com/php/php-src/blob/master/UPGRADING
58. Number to String Comparison <?php $validValues = ["foo", "bar", "baz"]; $value = 0; var_dump(in_array($value, $validValues)); // bool(true) // ???
59. Number to String Comparison <?php 0 == "foo"; // Before: 0 == (int)"foo"; // After: (string)0 == "foo";
60. Number to String Comparison Comparison | Before | After ------------------------------ 0 == "0" | true | true 0 == "0.0" | true | true 0 == "foo" | true | false 0 == "" | true | false 42 == " 42" | true | true 42 == "42foo" | true | false
61. Resource To Object Migration ● ● Long term goal: Convert all resources to objects Objects are type-safe and have much better internal support
62. Resource To Object Migration ● ● ● Long term goal: Convert all resources to objects Objects are type-safe and have much better internal support Using "opaque objects" – Actual object-oriented APIs may be added later
63. Resource To Object Migration ● CurlHandle, CurlMultiHandle, CurlShareHandle ● EnchantBroker, EnchantDictionary ● GdImage ● InflateContext, DeflateContext ● OpenSSLCertificate, OpenSSLCertificateSigningRequest, OpenSSLAsymmetricKey ● Shmop ● Socket, AddressInfo ● SysvMessageQueue, SysvSemaphore, SysvSharedMemory ● XmlParser ● XmlWriter (already had an OO API)
64. Resource To Object Migration <?php $image = imagecreatefrompng($path); if (!is_resource($image)) { throw new MalformedImageException; }
65. Resource To Object Migration <?php Now a GdImage object on success $image = imagecreatefrompng($path); if (!is_resource($image)) { throw new MalformedImageException; } Will always throw...
66. Resource To Object Migration <?php $image = imagecreatefrompng($path); if (false === $image) { throw new MalformedImageException; }
67. Warning → Error exception ● Many warnings converted to Error exceptions – TypeError – ValueError
68. 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
69. Warning → Error exception <?php var_dump(strlen([])); // Warning: strlen() expects parameter 1 to be string, // array given // NULL function strlen(string $str): int|null {}
70. 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 {}
71. 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 {}
72. Warning → Error exception <?php var_dump(array_fill(0, -100, "foobar")); // Uncaught ValueError: array_fill(): Argument #2 ($count) // must be greater than or equal to 0 function array_fill( int $start_index, int $count, mixed $value ): array {}
73. 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)
74. 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!
75. PHP Stubs ● ● PHP stub files specify function signatures for internal functions/methods Used to generate C code for function registration
76. PHP Stubs <?php function array_search( mixed $needle, array $haystack, bool $strict = false ): int|string|false {}
77. 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()
78. PHP Stubs ● Data available through Reflection: – ReflectionFunction::getReturnType() – ReflectionParameter::getType() – ReflectionParameter::getDefaultValue()
79. 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 } }
80. PHP Stubs <?php // Stub class DateTime implements DateTimeInterface { /** @return DateTime */ public function add(DateInterval $interval) {} } Now allowed! // Your code class MyDateTime extends DateTime { public function add(DateInterval $interval) { // Do something } }
81. PHP Stubs <?php A real return type would force all extending classes to specify it. // Stub class DateTime implements DateTimeInterface { /** @return DateTime */ public function add(DateInterval $interval) {} } Now allowed! // Your code class MyDateTime extends DateTime { public function add(DateInterval $interval) { // Do something } }
82. 3v4l.org
83. Travis CI php: - nightly install: - | if [ $TRAVIS_PHP_VERSION = 'nightly' ]; then composer install --ignore-platform-reqs; else composer install; fi Some libraries are not formally compatible with PHP 8 (yet)
84. Thank You!

首页 - Wiki
Copyright © 2011-2024 iteam. Current version is 2.137.1. UTC+08:00, 2024-11-23 23:55
浙ICP备14020137号-1 $访客地图$