PHP 8 will be released on november 26, 2020, according to the RFC there will a lot of improvements and features added to this major version of PHP.
New Features
Promoted Properties in Constructors
You might saw promoted properties in languages such as kotlin. Promoted properties allows class property declaration and constructor assignment right from the constructor.
So consider this example:
class Example { private string $name; public function __construct(string $name) { $this->name = $name; } }
Now with promoted properties you can write this instead:
class Example { public function __construct(private string $name) {} }
And you can access $this->name in the normal way in any method just you do with a normal property.
Union Types 2.0
Union types will be added in PHP 8 which allows for defining multiple types for properties, function parameters and return types.
class Example { private int|float $number1; public function calc(float|int $number2): int|float { return $this->number1 + $number2; } }
Trailing Comma in Parameter Lists
Trailing commas are commas appended to lists of items in different contexts. In PHP 7.2 there are trailing commas in list syntax, PHP 7.3 introduced trailing commas in function calls. Now in PHP 8 there will introduce trailing commas in parameter lists in methods, functions and closures.
public function( string $parameterA, int $parameterB, Foo $objectfoo, ) { // … }
::class syntax on objects
To get class name on objects prior to PHP 8 we can use get_class($object). In PHP 8 we can use $object::class to get the class name.
$object = new stdClass; var_dump($object::class); // "stdClass"
Abstract Method Signature Validation in Traits
There is a new improvement when using abstract methods in traits, before PHP 8 you can write something like this:
trait Test { abstract public function test(int $input): int; } class UsesTrait { use Test; public function test($input) { return $input; } }
Note that when implementing the method test() we omitted the parameter types and return type. But PHP 8 will perform proper method signature validation when using a trait and implementing its abstract methods, so the above example will be like this:
trait Test { abstract public function test(int $input): int; } class UsesTrait { use Test; public function test(int $input) : int { return $input; } }
Incompatible Method Signatures
In PHP, inheritance errors due to incompatible method signatures throw either a fatal error or a warning depending on what is causing the error.
class Foo { public function process(stdClass $item): array{} } class SuperFoo extends Foo{ public function process(array $items): array{} // ^^^^^ mismatch }
If you run this snippet it will show this warning:
Warning: Declaration of SuperFoo::process(array $items): array should be compatible with Foo::process(stdClass $item): array in ... on line ...
In PHP 8, such signature mismatches result in fatal error.
Fatal error: Declaration of SuperFoo::process(array $items): array must be compatible with Foo::process(stdClass $item): array in ... on line ...
Arrays Starting With Negative Index
Look at this example:
$a = array_fill(-5, 4, true); var_dump($a);
This code will output:
array(4) { [-5]=> bool(true) [0]=> bool(true) [1]=> bool(true) [2]=> bool(true) }
Now in php 8 arrays start with negative indices will be changed so that the second index would be start_index + 1
, whichever the value of start_index
. So in php 8 this code will output:
array(4) { [-5]=> bool(true) [-4]=> bool(true) [-3]=> bool(true) [-2]=> bool(true) }
Consistent Type Errors for Internal Functions
When passing a parameter of illegal type, internal and user-defined functions behave differently. User-defined functions throw a TypeError
, but internal functions behave in a variety of ways, depending on several conditions for example:
var_dump(strlen(new stdClass));
This example will result in:
Warning: strlen() expects parameter 1 to be string, object given in /path/to/your/test.php on line 4 NULL
In PHP 8 this example throws the following error:
Fatal error: Uncaught TypeError: strlen(): Argument #1 ($str) must be of type string, object given in /path/to/your/test.php:4 Stack trace: #0 {main} thrown in /path/to/your/test.php on line 4
‘throw’ Expression
In PHP, throw
is a statement, so it’s not possible to use it in places where only an expression is allowed. In PHP 8 throw will be converted to an expression for example it can be used in arrow functions, null coalesce operator, ternary and elvis operators, etc.
$callable = fn() => throw new Exception(); // $value is non-nullable. $value = $nullableValue ?? throw new InvalidArgumentException(); // $value is truthy. $value = $falsableValue ?: throw new InvalidArgumentException();
Weakmap
A WeakMap
implementation is added in PHP 8. WeakMap
holds references to objects, which don’t prevent those objects from being garbage collected.
$map = new WeakMap; $obj = new stdClass; $map[$obj] = 42; var_dump($map);
Non-capturing catches
Before PHP 8 whenever you wanted to catch an exception before PHP 8, you had to store it in a variable, regardless whether you used that variable or not.
try { // Something goes wrong } catch (MySpecialException $exception) { Log::error("Something went wrong"); }
Now you can do this:
try { // Something goes wrong } catch (MySpecialException) { Log::error("Something went wrong"); }
The nullsafe Operator
With the addition of the nullsafe operator, we can now have null coalescing-like behaviour on methods!
$dateAsString = $booking->getStartDate()?->asDateTimeString();
Named arguments
If you are familiar with Ecmascript 6 perhaps you might saw something like named arguments. Named arguments allow you to pass in values to a function, by specifying the value name, so that you don’t have to take their order into consideration, and you can also skip optional parameters!
function foo(int $a, float $b, ?string $c = null, ?string $d = null) { /* … */ } foo( b: 2, a: 2.5, d: 'john', );
Match expression
The Match expression like the classic switch statement but it’s more shorter. match
can return values, doesn’t require break
statements, can combine conditions, uses strict type comparisons and doesn’t do any type coercion.
$result = match($input) { 0 => "hello", '1', '2', '3' => "world", };
New ‘static’ return type
static
wasn’t a valid return type until PHP 8. Given PHP’s dynamically typed nature, it’s a feature that will be useful to many developers.
class Foo { public function test(): static { return new static(); } }
New Stringable Interface
The Stringable
interface can be used to type hint anything that implements __toString()
. Whenever a class implements __toString()
, it automatically implements the interface behind the scenes
class Foo { public function __toString(): string { return 'foo'; } } function bar(string|Stringable $stringable) { /* … */ } bar(new Foo()); bar('abc');
New str_contains Function
Like strpos() function to know whether a string contains another string.
Instead of doing this:
if (strpos('string with lots of words', 'words') !== false) { /* … */ }
You can now do this
if (str_contains('string with lots of words', 'words')) { /* … */ }
New str_starts_with() and str_ends_with() Functions
str_starts_with('hello world', 'hel'); // true str_ends_with('hello world', 'orld'); // true
Other Features Also Include:
- JIT (Just In-time Compiler)
- Attributes (Annotations in other languages)
- New ‘mixed’ type
- Create DateTime objects from interfaces
- get_debug_type() function
- get_resource_id() function