PHP 8.0

New features. Braking changes. Deprecations.

Named arguments

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

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

Constructor promotion

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) {}
}

Union types

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;
    }
}

Mixed pseudo type

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

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

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

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();

Migration from resource to object #BC

In PHP 8.0, some of the most used extensions changes move away from the traditional resource objects to standard PHP classes. Changed extensions:

  • curl
  • gd
  • sockets
  • openSSL
  • XMLWritter
  • XML

Error handling

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 & catch extension

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
}

Default error handling

  • E_ALL by default
  • display_startup_errors = 1 by default
  • Assertions throw exceptions by default
  • @ Error Suppression operator does not silent fatal errors

Fatal errors on incompatible method signatures #BC

PHP 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{}
}

Calling non-static class methods statically result in a fatal error #BC

PHP 8.0 no longer allows calling class methods as static method.

class Foo {
    public function bar() {}
}

Foo::bar(); // ERROR!

PHP 8.0

By Piotr Woszczyk

PHP 8.0

  • 32