A new syntax to declare class properties right from the class constructor (__construct magic method).
class User {
public function __construct(private string $name) {}
}
In the constructor, PHP 8.0 supports declaring the visibility (public, private, or protected) and type. Those properties will be registered as class properties with the same visibility and type they are declared in the constructor.
This backward-incompatible feature can help reduce boilerplate code when declaring value-object classes.
The ?-> null-safe operator short-circuits the rest of the expression if it encounters a null value, and immediately returns null without causing any errors.
Match expressions are similar to switch blocks, but match blocks provide type-safe comparisons, supports a return value, does not require break statements to break-out, and supports multiple matching values. it also guarantees that at least one branch is matched, ensuring all cases are accounted for.
Not all switch blocks might convert well to match blocks. Code that requires backward-compatibility, switch blocks with multiple statements (as opposed to single-line expressions), or expects fall-through functionality still fits the switch statements.
PHP 8.0 introduces a few new functions to ease string inspections (contains, starts with substring, or ends with substring) to replace the meticulous strpos() !== false calls that are less readable, and error-prone due to weak type comparisons.
The new Stringable interface is automatically added to all classes that implement __toString method, and those explicitly declare that they implements Stringable.
With the Stringable interface, it is now easy to declare types as string|Stringable for on functions that can accept/return strings or objects with a __toString() method.
PHP 8.0 brings mixed type, that was already being widely used in DocBlock comments.
mixed type can be used to indicate that it accepts any type or can return any type. In a class/interface context, mixed type plays by the same rules of Liskov Substitution Principle.
Static return type, already supports as a DocBlock return type is now supported in PHP 8.0. The static return type declares an object of the called class will be returned.
From PHP 8.0 and later, magic methods (e.g __toString(), __get(), etc), if they declare types, must implement the signature PHP expects. This is to avoid the smallest chance of the user declaring a magic method that doesn't follow the semantic meaning.
Declarations like Foo::__toString(): object was allowed in previous PHP versions, but PHP 8.0 and throws an exception if the signature does not meet the requirements.
PHP 8.0 relaxes the signature, abstract, and static flag enforcement for private class methods. This change comes from the rationale that private methods are just that: Private.
From PHP 8.0, it is now allowed for the child classes to declare abstract methods, and change static/flags for private methods.
The ::class magic constant returns the fully-qualified class name. This was only allowed on class names (such as Foo\Bar::class), but in PHP 8.0, the ::class magic constant works on instantiated objects too.
When the mathematical + and - operators are used in the same expression with the concatenation operator (.), the + and - operators take higher precedence. This resulted in a deprecation notice in PHP versions prior to 8.0, but now it happens silently and as per the warning.
function parse_value(string|int|float): string|null {}
function dd(mixed $var): void {
var_dump($var);
}
class Foo {
public static function getInstance(): static {
return new static();
}
}
$value = isset($_GET['value'])
? $_GET['value']
: throw new \InvalidArgumentException('value not set');
try {}
catch(TypeError) {
// Did not catch the $exception object
}
class Foo {
public function process(stdClass $item): array{}
}
class SuperFoo extends Foo{
public function process(array $items): array{}
// ^^^^^ mismatch
}
Fatal error: Declaration of SuperFoo::process(array $items): array must be compatible with Foo::process(stdClass $item): array in ... on line ...
class Foo {
public function __toString(): object {
}
}
class Foo {
public function bar() {}
}
Foo::bar();