Let’s take a closer look at what major changes php8 has introduced, as well as many new features and performance improvements
ValueError exception is added
This is the new ValueError built-in Exception class introduced in 8, which inherits from the Exception base class. Every time you pass a value to a function, throw this exception if it detects an invalid type. Prior to PHP 8, such an operation would be directly warned.
Sample code:
<? php declare(strict_types=1); Array_rand ([], 0); array_rand([], 0); array_rand([], 0); array_rand([], 0); /** * Json_decode depth parameters must be valid positive integer values, * so ValueError is raised */ json_decode('{}', true, -1);Copy the code
Running results:
Added support for union types
New union type, which allows a variable to have multiple types of values. Example code is as follows:
<? php declare(strict_types=1); / * * * the Number of support to define a joint type class * / class Number {private int | float $Number; public function setNumber(int|float $number): void { $this->number = $number; } public function getNumber(): int|float { return $this->number; $Number = new Number(); $Number = new Number(); $number->setNumber(5); var_dump($number->getNumber()); $number - > setNumber (11.54); var_dump($number->getNumber()); exit;Copy the code
Running results:
Variable arguments are allowed when overriding a method
When you override a parent method in a subclass, any number of arguments can be replaced with mutable arguments, as long as the corresponding argument types are compatible. Sample code is as follows
<? php declare(strict_types=1); class A { public function method(int $many, string $parameters, $here) { } } class B extends A { public function method(... $everything) { var_dump($everything); } } $b = new B(); $b->method('i can be overwritten! '); exit;Copy the code
Running results:
Static return type
In 8, you can use the static keyword to identify a method and return the class to which the method currently belongs, even if it is inherited and can be used for later static binding. Example code is as follows:
<? php declare(strict_types=1); class Test { public function doWhatever(): static { // Do whatever. return $this; } } exit;Copy the code
Added WeakMap feature
WeakMap allows you to create mappings of objects to arbitrary values (this is similar to SplObjectStorage) without preventing key objects from being garbage collected. If an object key is garbage collected, the corresponding key-value pair is removed from the collection.
This new feature is so useful that developers don’t have to worry about memory leaks in their code. Most PHP developers probably don’t care, but you should be aware of this problem when writing long-running processes, such as event-driven programming using ReactPHP. Objects referenced by WeakMap are automatically garbage collected when they fail.
If you do the same thing in an array, you will still hold a reference to that object, but it will leak memory. Example code is as follows:
<? php declare(strict_types=1); class FooBar { public WeakMap $cache; public function __construct() { $this->cache = new WeakMap(); } public function getSomethingWithCaching(object $obj) { return $this->cache[$obj] ?? = $this->computeSomethingExpensive($obj); } public function computeSomethingExpensive(object $obj) { var_dump("I got called"); return rand(1, 100); } } $cacheObject = new stdClass; $obj = new FooBar; $obj->getSomethingWithCaching($cacheObject); $obj->getSomethingWithCaching($cacheObject); $obj->getSomethingWithCaching($cacheObject); var_dump(count($obj->cache)); // WeakMap frees the corresponding memory unset($cacheObject) when the object is deleted; var_dump(count($obj->cache)); exit;Copy the code
Corresponding running results:
Variable syntax adjustment
The 8 new and instanceof keywords are supported for arbitrary expressions, as shown in the sample code below
<? php declare(strict_types=1); class Foo {} class Bar {} $names = ['Foo', 'Bar']; $class = new ($names[array_rand($names)]); var_dump($class); exit;Copy the code
Running results:
The class name of an object
Supported in 8
Object ::class Gets the class name of the object, returns the result and get_class(
Object ::class Gets the class name of the object, and returns the same result as getClass (object). Sample code:
<? php declare(strict_types=1); class Test { } $test = new Test(); var_dump($test::class); var_dump(get_class($test)); exit;Copy the code
Running results:
Optional trailing commas are allowed in argument lists
Like trailing commas in arrays, 8 supports defining trailing commas in argument lists. Sample code:
<? php declare(strict_types=1); function method_with_many_arguments( $a, $b, $c, $d, ) { var_dump("this is valid syntax"); } method_with_many_arguments( 1, 2, 3, 4, ); exit;Copy the code
Results of the above code:
Stringable interface
8 introduces a new Stringable interface. Whenever a class implements a __toString method, it is treated as automatically implementing the Stringable interface (similar to the Go implementation) without having to explicitly and declaratively implement the interface.
<? php declare(strict_types=1); class Foo { public function __toString() { return 'I am a class'; } } $obj = new Foo; var_dump($obj instanceof Stringable); exit;Copy the code
Running results:
Throw already supports being used as an expression
Throw statements can be used where only expressions are allowed, such as arrow functions, merge operators, and ternary operators: example code
<? php declare(strict_types=1); $callable = fn() => throw new Exception(); $nullableValue = null; $value = $nullableValue?? throw new \InvalidArgumentException(); exit;Copy the code
Catch exceptions without storing them in variables
You can write catch (Exception) code to catch an Exception without storing it in a variable:
<? php declare(strict_types=1); $nullableValue = null; try { $value = $nullableValue ?? throw new \InvalidArgumentException(); } catch (\InvalidArgumentException) { var_dump("Something went wrong"); } exit;Copy the code
Results of the above code:
PHP 8 added support for annotations
Annotations actually contain multiple RFCS:
https://wiki.php.net/rfc/attributes_v2
https://wiki.php.net/rfc/attribute_amendments
https://wiki.php.net/rfc/shorter_attribute_syntax
https://wiki.php.net/rfc/shorter_attribute_syntax_change
Copy the code
Annotations are one of the biggest new features introduced in PHP 8, and can be a little difficult to understand at first (relatively easy if you have Java background).
Annotations allow you to add metadata to PHP functions, parameters, classes, and so on, which can then be retrieved programmatically. Doing so in PHP 7 or later requires parsing code comment blocks, while annotations provide direct access to deep integration into PHP itself.
Let’s say you want to allow developers to add middleware to controller classes/methods, using annotations. You can do this:
<? php declare(strict_types=1); #[Attribute] class ApplyMiddleware {public array $middlware = []; public function __construct(... $middleware) { $this->middleware = $middleware; }} // The following syntax adds the above annotation to the MyController class, And pass auth as parameter #[ApplyMiddleware('auth')] class MyController {public function Index () {}} // Then we can use reflection to get all of them in the class ApplyMiddleware annotates and reads the given middleware parameter $reflectionClass = new reflectionClass (MyController::class); $attributes = $reflectionClass->getAttributes(ApplyMiddleware::class); foreach ($attributes as $attribute) { $middlewareAttribute = $attribute->newInstance(); var_dump($middlewareAttribute->middleware); } exit;Copy the code
Run the code above to print the result:
8 Added constructor attribute hint support
This new feature is a syntactic shorthand for combining attribute declarations and constructor attribute initializations. Example code for this feature is as follows:
<? php declare(strict_types=1); class User { public function __construct( public int $id, public string $name, ) {} } $user = new User(1, 'Marcel'); var_dump($user->id); var_dump($user->name); exit;Copy the code
Results of the above code:
The Trait in PHP8 supports defining abstract private methods, as shown in the following code:
<? php declare(strict_types=1); trait MyTrait { abstract private function neededByTheTrait(): string; public function doSomething() { return strlen($this->neededByTheTrait()); } } class TraitUser { use MyTrait; Private function neededByTheTrait(): string {} private function neededByTheTrait(): string {} Private static function neededByTheTrait(): string {}} exit; private static function neededByTheTrait(): string {}} exit;Copy the code
Php8 added support for match expressions
Match expressions are similar to switch branch statements, except that they are semantically more secure and can return a value directly: the code for this example is shown below
<? php declare(strict_types=1); echo match (1) { 0 => 'Foo', 1 => 'Bar', 2 => 'Baz', }; exit;Copy the code
Results of the above code:
PHP 8 introduces a new type called mixed
This type is equivalent to an array | bool | callable | int | float | null | object | resource | string, the example code is as follows:
<? php declare(strict_types=1); function debug_function(mixed ... $data) { var_dump($data); } debug_function(1, 'string', []); exit;Copy the code
Results of the above code:
8 Added support for named parameters
Named parameters allow you to pass parameters to a function based on their name, not their location. As a result, the function arguments are self-explanatory and sequence-independent, allowing default values to be skipped, as shown in the following code:
<? php declare(strict_types=1); array_fill(start_index: 0, num: 100, value: 50); exit;Copy the code
New air-safe operator? – > support
When the left-hand evaluation of this operator is NULL, execution of the entire code link is terminated and the entire evaluation is NULL. But if it is not null, it does what the normal -> operator does:
<? php declare(strict_types=1); class User { public function getAddress() {} } $user = new User(); $country = $user? ->getAddress()? ->country? ->iso_code; var_dump($country); exit;Copy the code
Results of the above code: