Released!
PHP 8.1 ist ein Minor-Update der Sprache PHP.
Es beinhaltet viele neue Features und Verbesserungen.
Unter anderem Enumerations, Readonly-Properties, First-Class Callable Syntax, Fibers, Intersection-Types, Performance-Optimierungen.

Enumerations RFC Doc

PHP < 8.1
class Status
{
    const
DRAFT = 'draft';
    const
PUBLISHED = 'published';
    const
ARCHIVED = 'archived';
}
function
acceptStatus(string $status) {...}
PHP 8.1
enum Status
{
    case
Draft;
    case
Published;
    case
Archived;
}
function
acceptStatus(Status $status) {...}

Du kannst nun Enums statt Konstanten für mehr Typensicherheit und direkter Validierung nutzen.

Readonly-Properties RFC Doc

PHP < 8.1
class BlogData
{
    private
Status $status;
  
    public function
__construct(Status $status)
    {
       
$this->status = $status;
    }
   
    public function
getStatus(): Status
   
{
        return
$this->status;   
    }
}
PHP 8.1
class BlogData
{
    public
readonly Status $status;
  
    public function
__construct(Status $status)
    {
       
$this->status = $status;
    }
}

Readonly-Properties können nach einer Initialisierung nicht mehr verändert werden.
Sie sind ein ideales Werkzeug um Value-Objekte und Data-Transfer-Objekte zu erstellen.

First-Class Callable Syntax RFC Doc

PHP < 8.1
$foo = [$this, 'foo'];

$fn = Closure::fromCallable('strlen');
PHP 8.1
$foo = $this->foo(...);

$fn = strlen(...);

Durch die sogenannte First-Class Callable Syntax kannst du eine Referenz zu jeder beliebigen Funktion erhalten.

New in Initialisierungen RFC

PHP < 8.1
class Service
{
    private
Logger $logger;

    public function
__construct(
        ?
Logger $logger = null,
    ) {
       
$this->logger = $logger ?? new NullLogger();
    }
}
PHP 8.1
class Service
{
    private
Logger $logger;
   
    public function
__construct(
       
Logger $logger = new NullLogger(),
    ) {
       
$this->logger = $logger;
    }
}

Objekte können nun als Default-Wert für Parameter, statische Variablen, Konstanten, so wie als Argument für Attribute genutzt werden.

Dies ermöglicht nun auch die Nutzung von verschachtelten Attributen.

PHP < 8.1
class User
{
   
/**
     * @Assert\All({
     *     @Assert\NotNull,
     *     @Assert\Length(min=5)
     * })
     */
   
public string $name = '';
}
PHP 8.1
class User
{
   
#[\Assert\All(
       
new \Assert\NotNull,
        new \
Assert\Length(min: 6))
    ]
    public
string $name = '';
}

Pure-Intersection-Types RFC Doc

PHP < 8.1
function count_and_iterate(Iterator $value) {
    if (!(
$value instanceof Countable)) {
        throw new
TypeError('value must be Countable');
    }

    foreach (
$value as $val) {
        echo
$val;
    }

   
count($value);
}
PHP 8.1
function count_and_iterate(Iterator&Countable $value) {
    foreach (
$value as $val) {
        echo
$val;
    }

   
count($value);
}

Nutze die Intersection-Types, wenn du sicherstellen möchtest, dass das übergebene Objekt mehrere Typen implementieren.

Es ist aktuell nicht möglich eine Kombination aus Intersection- und Union-Types zu nutzen, wie z.B. A&B|C.

Der Rückgabetyp Never RFC Doc

PHP < 8.1
function redirect(string $uri) {
   
header('Location: ' . $uri);
    exit();
}

function
redirectToLoginPage() {
   
redirect('/login');
    echo
'Hello'; // <- dead code
}
PHP 8.1
function redirect(string $uri): never {
   
header('Location: ' . $uri);
    exit();
}

function
redirectToLoginPage(): never {
   
redirect('/login');
    echo
'Hello'; // <- dead code detected by static analysis
}

Eine Funktion mit dem Rückgabetyp never gibt an, dass sie keinen Rückgabewert besitzt und die Funktion entweder eine Exception wirft oder das Script durch die(), exit(), trigger_error(), oder einer ähnlichen Funktion terminiert wird.

Final Klassen Konstanten RFC Doc

PHP < 8.1
class Foo
{
    public const
XX = "foo";
}

class
Bar extends Foo
{
    public const
XX = "bar"; // No error
}
PHP 8.1
class Foo
{
    final public const
XX = "foo";
}

class
Bar extends Foo
{
    public const
XX = "bar"; // Fatal error
}

Es ist nun möglich Klassen Konstanten als final zu definieren, sodass diese in einer Vererbung nicht überschrieben werden können.

Explizite Oktalsystem-Zahl Notation RFC Doc

PHP < 8.1
016 === 16; // false because `016` is octal for `14` and it's confusing
016 === 14; // true
PHP 8.1
0o16 === 16; // false — not confusing with explicit notation
0o16 === 14; // true

Du kannst nun Oktalsystem-Zahlen explizit durch einen 0o-Prefix angeben.

Fibers RFC Doc

PHP < 8.1
$httpClient->request('https://example.com/')
        ->
then(function (Response $response) {
            return
$response->getBody()->buffer();
        })
        ->
then(function (string $responseBody) {
            print
json_decode($responseBody)['code'];
        });
PHP 8.1
$response = $httpClient->request('https://example.com/');
print
json_decode($response->getBody()->buffer())['code'];

Fibers sind eine grundlegende Funktionalität zur Implementierung von verzahnten Abläufen. Sie sind dazu gedacht Code-Blöcke zu erstellen, die pausiert und wiederaufgenommen werden ähnlich wie die Generator-Implementierung, jedoch von überall aus. Fibers selbst stellen keine Nebenläufigkeit bereit und benötigen somit eine Event-Loop Implementierung. Aber sie ermöglichen die gemeinsame Nutzung einer API in einem blockierenden und nicht blockierenden Kontext.

Fibers können dazu dienen, Funktionen wie z.B. Promise::then() oder Generator basierte Koroutinen zu ersetzen. Generell wird davon ausgegangen, dass Bibliotheken-Entwickler eine Abstraktion um die Fibers herum bauen werden, sodass man selten in Berührung mit den Fibers kommen wird.

Entpacken von Arrays mit string-basierten Keys RFC Doc

PHP < 8.1
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];

$result = array_merge(['a' => 0], $arrayA, $arrayB);

// ['a' => 1, 'b' => 2]
PHP 8.1
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];

$result = ['a' => 0, ...$arrayA, ...$arrayB];

// ['a' => 1, 'b' => 2]

PHP unterstützte bereits das Entpacken von Arrays mit int-basiertem Key in andere Arrays. Jetzt ist es auch möglich Arrays mit einem string-basiertem Key oder auch einer Kombination aus beiden Varianten zu entpacken.

Performance-Optimierungen

Symfony Demo App Request Zeit
25 aufeinanderfolgende Läufe, 250 Requests (sek)
(kleiner ist besser)

Das Ergebnis (Relativ zu PHP 8.0):

  • 23.0% schnellere Symfony Demo
  • 3.5% schnelleres WordPress

Performance relevante Features in PHP 8.1:

  • JIT Backend für ARM64 (AArch64)
  • Vererbungscache (verhindern das Relinken von Klassen in bei jedem Request)
  • Schnelleres auflösen von Klassennamen (verhindern von Kleinschreibungsumwandlung und Hash Lookups )
  • timelib und ext/date Performance-Optimierungen
  • SPL Dateisystem Iteratoren-Optimierungen
  • Serialisierung- / Deserialisierung-Optimierungen
  • Einige Optimierungen an internen Funktionen (get_declared_classes(), explode(), strtr(), strnatcmp(), dechex())
  • JIT Verbesserungen und Korrekturen

Neue Klassen, Interfaces und Funktionen

  • Neues Attribut #[ReturnTypeWillChange].
  • Neue Funktionen fsync und fdatasync.
  • Neue Funktion array_is_list.
  • Neue Sodium XChaCha20 Funktionen.

Veraltete Funktionalität und inkompatible Änderungen zu vorherigen PHP Versionen

  • Übergabe von null an nicht null-fähige interne Funktionsparameter ist veraltet.
  • Interne PHP Klassen-Methoden besitzen nun Rückgabetypen
  • Das Serializable Interface ist nun veraltet.
  • HTML-Entitäten en/decode Funktionen verarbeiten und ersetzen einfache Anführungszeichen im Standard.
  • Restriktionen an der $GLOBALS Variable.
  • MySQLi: Der Standard Error-Modus wirft nun Exceptions.
  • Implizite nicht kompatible Float zu Int Konvertierung ist veraltet.
  • finfo Erweiterung: file_info nutzt nun das finfo-Objekt statt einer resource.
  • IMAP: imap nutzt nun das IMAP\Connection Objekt statt des resource-Typen.
  • FTP Erweiterung: Nutzt nun das FTP\Connection Objekt statt des resource-Typen.
  • GD Erweiterung: Die Klasse GdFont ersetzt nun den zuvor genutzten resource-Typ.
  • LDAP: Die resource-Typen wurden auf LDAP\Connection, LDAP\Result und LDAP\ResultEntry umgestellt.
  • PostgreSQL: Die resource-Typen wurden auf PgSql\Connection, PgSql\Result und PgSql\Lob umgestellt.
  • Pspell: Der resource-Typ von pspell und pspell config wurden auf PSpell\Dictionary und PSpell\Config umgestellt.
To Top