PHP 8 New Features: Exploring Changes in Part 2 Skip to main content

Search

Image
PHP 8 new features and changes - Part 2 - Banner

This is part 2 of the blog. Here we will discuss the other features and changes in PHP 8.

 

Mixed type

The mixed type was already being widely used in DocBlock comments. In PHP, a missing type can be due to a lot of reasons:

  • A function returning null or nothing.
  • Expecting one of several types.
  • Expecting a type that can’t be typed hinted in PHPbackward-incompatible.

 

mixed itself means one of the following types:

  • array
  • boolean
  • callable
  • int
  • float
  • null
  • object
  • resource
  • string


mixed can also be used as a parameter or property and not just as a return type. Since mixed already includes null so it is not allowed to make it nullable. On doing so, the following error will occur:

// Fatal error: Mixed types cannot be nullable, null is already part of the mixed type.
function myFunction(): ?mixed {}

mixed type can be used to indicate that it accepts any type, or can return any type. In a class/interface context.

function myFunction(mixed $var): void {
    var_dump($var);
}

Static return type

static is a new return type in PHP 8. The static return type declares an object of the called class will be returned. 

class Foo {

    public static function myFunction(): static {

        return new static();

    }

}

Error handling improvements

Internal functions now throw exceptions on type errors or value errors. This is a backward-incompatible change.

throw in expressions

It was not possible to throw exceptions from an expression (e.g. a ternary statement) before PHP 8. It is now possible to do so in PHP 8.

$var = isset($_GET['value'])
    ? $_GET['value']
    : throw new \InvalidArgumentException('value not set');

catch exceptions only by their type

We can catch exceptions by their type, without capturing the exception object.

try {}
catch(TypeError) {
  // Did not catch the $exception object
}

@ Error, Suppression operator does not silent fatal errors

PHP 8.0 changes the behavior of @ error suppression operator. Previously, it used to silence the fatal errors, which would lead to a script failure, due to the @ operator not preventing fatal errors, but rather hiding the error message display.

Default error reporting is set to E_ALL

The default configuration in PHP 8.0 is to show all error messages. It was configured to hide deprecation and strict warnings in older versions.

Default PDO error mode

From the RFC: The current default error mode for PDO is silent. This means that when an SQL error occurs, no errors or warnings may be emitted and no exceptions are thrown unless the developer implements their explicit error handling.


In PHP 8, the default error will change to PDO::ERRMODE_EXCEPTION.


Weak maps

A WeakMap holds references to objects, which does not prevent those objects from being garbage collected.

WeakMap and SplObjectStorage are quite similar. They both use objects as the key and allow arbitrary values to be stored. However, a WeakMap, unlike SplObjectStorage, does not prevent the object from being garbage collected.

Example of WeakMap:

class Myclass
{
    private WeakMap $cache;
 
    public function getAvalueFromCache(object $obj): object
    {
        return $this->cache[$obj]
           ??= $this->computeResult($obj);
    }
}

`::class` magic constant is now allowed on objects

In PHP, the magic constant ::class helps in resolving a class name to its fully-qualified class name. When this magic constant is used with a class name, use and use as statements will be resolved or the present namespace will be prefixed which would make it a fully-qualified class name.

For example:

namespace MyApp\DemoApp;

use MyFoo\Bar;
use MyBar\Baz as BBaz;

class MyDemo {}

// `use` statement is resolved:
echo Bar::class; // "MyFoo\Bar"

// `use` X `as` Y is resolved:
echo BBaz::class; // "MyBar\Baz"

// Current namespace is resolved:
echo Demo::class; // "MyApp\DemoApp\MyDemo"

Before PHP 8.0, the usage of the magic constant ::class was not allowed on objects and it would throw a fatal error like the one below:

$object = new Foo\Bar();
echo $object::class;

// Fatal error: Cannot use ::class with dynamic class name.
Now since it is allowed, we can do this and it would be correctly resolved at run time:

$object = new Foo\Bar();
echo $object::class;

// PHP 8.0+:
// "Foo\Bar"

Trailing commas now allowed in parameter lists and closure `use` lists

PHP 8 is also quite forgiving and allows us to leave trailing commas in parameter lists and closure use lists.

public myfunction(
    string $paramA,
    int $paramB,
    Foo $myobject,
) {
    // …
}

DateTime objects can be created from the interface

There is now a generalised way to convert DateTime and DateTimeImmutable objects to each other by adding DateTime::createFromInterface() and DatetimeImmutable::createFromInterface().

DateTime::createFromInterface(DateTimeInterface $other);

DateTimeImmutable::createFromInterface(DateTimeInterface $other);

Read part 3 of the blog here.