New features. Braking changes. Deprecations.
PHP 8.0 introduced named arguments as an extension of the existing positional parameters. Named arguments allow passing arguments to a function based on the parameter name, rather than the parameter position.
<?php
// 7.4: positional arguments:
array_fill(0, 100, 50);
// 8.0: named arguments:
array_fill(start_index: 0, count: 100, value: 50);
// OR
array_fill(value: 50, count: 100, start_index: 0);
?>Attributes are small meta-data elements added for PHP classes, functions, closures, class properties, class methods, constants, and even on anonymous classes.
<?php // 7.4
class AboutPage extends AbstractController {
/**
* @Route("/about")
*/
public function page() {}
}<?php // 8.0
class AboutPage extends AbstractController {
#[Route('/about')]
public function page() {}
}#[ is no longer interpreted as the start of a comment, as this syntax is now used for attributes. #BC
Property promotion allows you to combine class fields, constructor definition and variable assignments all into one syntax, in the construct parameter list.
<?php // 7.4
class Job
{
public string $name;
public function __construct(
string $name
) {
$this->name = $name;
}
}<?php // 8.0
class Job
{
public function __construct(public string $name) {}
}From PHP 8.0, you can declare more than one type for arguments, return types, and class properties.
<?php // 8.0
class Job {
private int|float $salary;
public function setSalary(float|int $salary): int|float {
$this->salary = $salary;
}
}PHP 8.0 brings mixed type, that was already being widely used in DocBlock comments.
<?php // 8.0
function disable(mixed $countryCode): void {
// ...
}Mixed became reserved word. #BC
Static return type, already support 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.
<?php // 8.0
class JobDTO {
public static function createFromJobExtern($jobExtern): static {
return new static($jobExtern->getName());
}
}Match expressions are similar to switch blocks, but match blocks provide type-safe comparisons, support a return value, do not require break statements, and support multiple matching values.
<?php // 8.0
$response = match($error) {
'debug' => $this->devNull(),
'warning', 'error' => $this->log('Sth went wrong'),
$this->customErorrs() => $this->log('Sth went wrong but we expect it')
};Match became reserved word. #BC
Nullsafe operator provides safety in method/property chaining when the return value or property can be null.
<?php // 7.4
if (is_null($job)) {
$result = null;
} else {
$result = $job->getSalary();
}<?php // 8.0
$result = $job?->getSalary();In PHP 8.0, some of the most used extensions changes move away from the traditional resource objects to standard PHP classes. Changed extensions:
A major and backward-incompatible change in PHP 8.0 is that internal functions now throw exceptions on type errors or value errors. #BC
A ValueError is thrown when the type of an argument is correct but the value of it is incorrect, e.g. passing a negative integer when the function expects a positive one or passing an empty string/array when the function expects it to not be empty.
Throw in expressions
<?php // 8.0
$value = isset($_GET['value'])
? $_GET['value']
: throw new \InvalidArgumentException('value not set');Catch exceptions only by type
<?php // 8.0
try {}
catch(TypeError) {
// Did not catch the $exception object
}E_ALL by defaultdisplay_startup_errors = 1 by defaultPHP 8.0 throws fatal errors when Liskov Substitution Principle is not followed when classes are extended, or interfaces are implemented.
class Foo {
public function process(stdClass $item): array{}
}
class SuperFoo extends Foo{
// ERROR
public function process(array $items): array{}
}PHP 8.0 no longer allows calling class methods as static method.
class Foo {
public function bar() {}
}
Foo::bar(); // ERROR!