Welcome to the continuation of the blog on “What’s New in PHP 8”. In my previous blog we have seen about JIT and how can JIT make the CPU-intensive workloads run significantly faster. PHP8 has been officially released for general availability on 26 Nov 2020. PHP 8 comes with various benefits including named arguments, union types, attributes, constructor property promotion, match expression, null safe operator, JIT, and improvements in the type system, error handling, and consistency, here I have handpicked a selection of changes and enhancements, which makes PHP more reliable and efficient.

PHP 8 Improvements and New Features

  • Union types Request for Comment (RFC)

As PHP is dynamic in nature, there are lot of cases where Union types can be useful. Union types are a collection of two or more types which indicate that either one of those can be used.

Note: Void cannot be a part of Union type, since it indicates no return value. Nullable union types can written using |null or by using existing ? notation.

  • The nullsafe operator(RFC)

When you are calling an function or a method we always need check whether it is null, which leads to deeper nesting and repetitions in PHP. Now in PHP8 there are introducing a null safe operator.


//Before Nullsafe operator
$country =  null;
if ($session !== null) {
$user = $session->user;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
// do something with $country

/*--------------------------------------------*///After using Null Safe Operator the above code will be
$country = $session?->user?->getAddress()?->country;
// do something with $country
  • Named arguments (RFC)

Named arguments allows you to pass the values to a function, by specifying the value name, so you do not have to consider order and you can skip optional parameters.


function foo(string $user, string $firstname, ? string $phone = null)
{/**/}

foo(firstname : 'Seshu', user:'PHProckstar');
  • Match expression (RFC)

Match is a like switch expression, 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",
};
  • Constructor property promotion (RFC)

In this RFC adds a Synthetic Sugar to create value objects or data transfer objects. Currently all the properties in the class need to be repeated. Now in new changes introduce a shorthand syntax, which allows combining the definition of properties and the constructor.


// Instead of doing this
    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;
}
    }
//Now we can rewrite the above code as below
class Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
  • Throw expression(RFC)

In PHP as throw is a statement, so it is not possible to use it in the places where only an expression is allowed. In this RFC, they propose to convert throw statement in to an expression so it can used in any context where expressions are allowed.


$callable = fn() => throw new Exception();

// $value is non-nullable.
$value = $nullableValue ?? throw new InvalidArgumentException();
 
    // $value is truthy.
    $value = $falsableValue ?: throw new InvalidArgumentException();
  • Inheritance with private methods (RFC)

Currently in PHP a method with the same name as parent method, is still checked for some inheritance rules regardless of the parent’s visibility methods. Which even leads to inheritance checks being executed if the parent method is private. As it doesn’t make sense, because private methods won’t be accessible by the child class.

Now in this RFC, they changed behavior, so that inheritance checks are not performed on Private methods anymore.

  • Weak maps (RFC)

A weak map is a collection of data(objects) in which keys are weakly referenced, meaning that they are not prevented from being garbage collected.
In PHP 7.4 support for weak references were introduced. It has a way to retain reference to an object that doesn’t prevent the object itself from being destroyed. Which being pointed by Nikita Popov as “Raw weak references are only of limited usefulness by themselves and weak maps are much more commonly used in practice. It is not possible to implement an efficient weak map on top of PHP weak references because the ability to register a destruction callback is not provided”.

As in this RFC a “weak map” class has been introduced to create objects to be used as weak map keys that can be destroyed and removed from the weak maps if there aren’t any further references to the key object. See the below example from the RFC


$map = new WeakMap;
$obj = new stdClass;
$map[$obj] = 42;

var_dump($map);

// object(WeakMap)#1 (1) {
//   [0]=>
//   array(2) {
//     ["key"]=>
//     object(stdClass)#2 (0) {
//     }
//     ["value"]=>
//     int(42)
//   }
// }
 
// The object is destroyed here, 
//and the key is automatically removed from the weak map.
unset($obj);
var_dump($map);
// object(WeakMap)#1 (0) {
// }
  • Allow:: class on objects (RFC)

It is a new feature, which makes use “: : class” on objects instead of using get_class().


$foo = new Foo();
var_dump($foo::class);
  • Non-capturing catches (RFC)

In PHP, if we need to capture an exception, we must store it in a variable regardless whether we use it or not. But with this RFC we can omit the variable, which mean we don’t need to store the exception to a variable.


//Instead of this
try {
// Something goes wrong
} catch (MySpecialException $exception) {
Log::error("Something went wrong");
}

//We Can do this

try {
// Something goes wrong
} catch (MySpecialException) {
    Log::error("Something went wrong");
}

 

  • Trailing comma in parameter lists (RFC)

In this RFC, trailing commas in parameter lists with functions, methods, and closures are now supported.


class Foo {
    public function __construct(
string $x,
int $y,
float $z, // trailing comma
) {
        // do something
}
}

 

Str_Contains checks is a string is contained in another string and returns a Boolean value (true/false).


str_contains("abc", "a"); // true
str_contains("abc", "d"); // false
             
// $needle is an empty string
str_contains("abc", "");  // true
str_contains("", "");     // true
  • str_starts_with() and str_ends_with(RFC)

str_starts_with checks if a string begins with another string and returns a boolean value (true/false) whether it does.

str_ends_with checks if a string ends with another string and returns a boolean value (true/false) whether it does.


str_starts_with('haystack', 'hay'); // true
str_ends_with('haystack', 'stack'); // true

 

  • get_debug_type(RFC)

This new function works similar way as the gettype function but get_debug_type returns native type names and resolves class names.


$bar = $arr['key'];
 
if (!($bar instanceof Foo)) { 
throw new TypeError(
'Expected ' . Foo::class . 
' got ' . (is_object($bar) ? get_class($bar) : gettype($bar))
);
}

// would become
if (!($bar instanceof Foo)) { 
throw new TypeError(
'Expected ' . Foo::class . 
' got ' . get_debug_type($bar));
}

$bar->someFooMethod();

 

  • Ensure correct signatures of magic methods (RFC)

PHP’s Magic Methods is something that PHP provides allowing developers to track and act on specific changes of behavior of a certain class.
In this RFC proposes to add parameter and return types checks as provided by the RFC details.


Foo::__call(string $name, array $arguments): mixed;
 
Foo::__callStatic(string $name, array $arguments): mixed;
 
Foo::__clone(): void;
 
Foo::__debugInfo(): ?array;
 
Foo::__get(string $name): mixed;
 
Foo::__invoke(mixed $arguments): mixed;
 
Foo::__isset(string $name): bool;
 
Foo::__serialize(): array;
 
Foo::__set(string $name, mixed $value): void;
 
Foo::__set_state(array $properties): object;
 
Foo::__sleep(): array;
 
Foo::__unserialize(array $data): void;
 
Foo::__unset(string $name): void;
 
Foo::__wakeup(): void;

 

Conclusion
This new major update brings a whole bunch of optimization and powerful features to the language and we are excited to drive you through the most interesting changes that will allow us to write better code and build more powerful applications.

Seshendra
Seshendra
SSDE