International PHP Conference Berlin 2023

Neue Features

Deklaration skalarer Typen

Für die Deklaration des Typs von Skalaren gibt es zwei Möglichkeiten: erzwungen (Standard) und strikt. Die folgenden Typen können nun für Parameter erzwungen werden: Zeichenketten (string), Ganzzahlen (int), Gleitkommazahlen (float), und Booleans (bool). Sie ergänzen die anderen in PHP 5 eingeführten Typen: Klassennamen, Schnittstellen, array und callable.

<?php
// Erzwingender Modus
function sumOfInts(int ...$ints)
{
    return 
array_sum($ints);
}

var_dump(sumOfInts(2'3'4.1));

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

int(9)

Um den strikten Modus zu aktivieren, muss am Anfang der Datei eine einzelne declare-Direktive stehen. Das bedeutet, dass die Strenge der Typisierung für Skalare für jede Datei einzeln festgelegt wird. Diese Anweisung wirkt sich nicht nur auf die Typ-Deklarationen von Parametern aus, sondern auch auf den Rückgabetyp von Funktionen (siehe Deklaration des Rückgabetyps), auf eingebaute PHP-Funktionen und auf Funktionen von geladenen Erweiterungen.

Eine vollständige Dokumentation und Beispiele für die Deklaration von Skalartypen ist im Abschnitt über die Deklaration des Typs zu finden.

Deklaration des Rückgabetyps

PHP 7 unterstützt die Deklaration des Rückgabetyps. Ähnlich wie bei der Deklaration des Parameter-Typs gibt die Deklaration des Rückgabetyps den Typ des Wertes an, der von einer Funktion zurückgegeben wird. Für die Deklaration des Rückgabetyps stehen dieselben Typen zur Verfügung wie für die Deklaration des Parameter-Typs.

<?php

function arraysSum(array ...$arrays): array
{
    return 
array_map(function(array $array): int {
        return 
array_sum($array);
    }, 
$arrays);
}

print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Array
(
    [0] => 6
    [1] => 15
    [2] => 24
)

Eine vollständige Dokumentation und Beispiele für die Deklaration des Rückgabetyps ist im Abschnitt über die Deklaration des Rückgabetyps zu finden.

Null-Koaleszenz-Operator

Der null-Koaleszenz-Operator (etwa: Operator für die Kombination mit null) ?? wurde als syntaktische Vereinfachung hinzugefügt für den häufigen Fall, dass ein ternärer Operator in Verbindung mit isset() verwendet wird. Er gibt seinen ersten Operanden zurück, wenn er existiert und nicht null ist; andernfalls gibt er seinen zweiten Operanden zurück.

<?php
// Gibt den Wert von $_GET['user'] zurück, falls er existiert,
// und andernfalls 'nobody'.
$username $_GET['user'] ?? 'nobody';
// Dies ist gleichbedeutend mit:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

// Dieser Operator kann verkettet werden. Das Beispiel gibt den
// ersten definierten Wert aus $_GET['user'], $_POST['user'] und
// 'nobody' zurück.
$username $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>

Raumschiff-Operator (Spaceship)

Der Raumschiff-Operator wird für den Vergleich zweier Ausdrücke verwendet. Er gibt -1, 0 oder 1 zurück, wenn $a kleiner, gleich oder größer ist als $b. Vergleiche werden gemäß den üblichen Regeln für Typenvergleiche in PHP durchgeführt.

<?php
// Ganzzahlen
echo <=> 1// 0
echo <=> 2// -1
echo <=> 1// 1

// Gleitkommazahlen
echo 1.5 <=> 1.5// 0
echo 1.5 <=> 2.5// -1
echo 2.5 <=> 1.5// 1

// Zeichenketten
echo "a" <=> "a"// 0
echo "a" <=> "b"// -1
echo "b" <=> "a"// 1
?>

Definieren von Array-Konstanten mit define()

Es ist nun möglich, Array-Konstanten mit define() zu definieren. Bis zu PHP 5.6 konnten Array-Konstanten nur mit const definiert werden.

<?php
define
('ANIMALS', [
    
'dog',
    
'cat',
    
'bird'
]);

echo 
ANIMALS[1]; // gibt "cat" aus
?>

Anonyme Klassen

Mit new class wurde die Unterstützung für anonyme Klassen hinzugefügt. Dies kann anstelle von vollständigen Klassendefinitionen verwendet werden für Objekte, die nur einmal benötigt werden:

<?php
interface Logger {
    public function 
log(string $msg);
}

class 
Application {
    private 
$logger;

    public function 
getLogger(): Logger {
         return 
$this->logger;
    }

    public function 
setLogger(Logger $logger) {
         
$this->logger $logger;
    }
}

$app = new Application;
$app->setLogger(new class implements Logger {
    public function 
log(string $msg) {
        echo 
$msg;
    }
});

var_dump($app->getLogger());
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

object(class@anonymous)#2 (0) {
}

Die vollständige Dokumentation befindet sich im Abschnitt Anonyme Klassen.

Syntax für die Maskierung von Unicode-Codepunkten

Diese Syntax nimmt einen Unicode-Codepunkt in hexadezimaler Form und gibt diesen Codepunkt in UTF-8 in eine Zeichenkette mit doppelten Anführungszeichen oder einen Heredoc aus. Jeder gültige Codepunkt wird akzeptiert, wobei führende Nullen optional sind.

echo "\u{aa}";
echo "\u{0000aa}";
echo "\u{9999}";

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

ª
ª (wie zuvor, jedoch mit führenden Nullen)
香

Closure::call()

Die Methode Closure::call() ist ein leistungsfähigerer und kürzerer Weg, um den Gültigkeitsbereich eines Objekts vorübergehend an eine Closure zu binden und diese aufzurufen.

<?php
class {private $x 1;}

// Code vor PHP 7
$getX = function() {return $this->x;};
$getXCB $getX->bindTo(new A'A'); // zwischengeschaltete Closure
echo $getXCB();

// Code in PHP 7+
$getX = function() {return $this->x;};
echo 
$getX->call(new A);

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

1
1

Gefiltertes unserialize()

Dieser Mechanismus soll zusätzliche Sicherheit beim Deserialisieren von Objekten aus nicht vertrauenswürdigen Daten bieten. Durch die Definition einer Whitelist für Klassen, die deserialisiert werden dürfen, können Angriffe durch Code-Injection verhindert werden.

<?php

// wandelt alle Objekte in __PHP_Incomplete_Class-Objekte um
$data unserialize($foo, ["allowed_classes" => false]);

// wandelt mit Ausnahme von MyClass und MyClass2 alle Objekte in __PHP_Incomplete_Class-Objekte um
$data unserialize($foo, ["allowed_classes" => ["MyClass""MyClass2"]]);

// In der Voreinstellung (entspricht dem Weglassen des zweiten Parameters) werden alle Klassen akzeptiert
$data unserialize($foo, ["allowed_classes" => true]);

IntlChar

Die neue Klasse IntlChar wurde hinzugefügt, um zusätzliche Funktionalitäten von ICU zu nutzen. Die Klasse selbst definiert eine Reihe von statischen Methoden und Konstanten, die zur Bearbeitung von Unicode-Zeichen verwendet werden können.

<?php

printf
('%x'IntlChar::CODEPOINT_MAX);
echo 
IntlChar::charName('@');
var_dump(IntlChar::ispunct('!'));

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

10ffff
COMMERCIAL AT
bool(true)

Um diese Klasse verwenden zu können, muss die Erweiterung Intl installiert sein.

Expectations (Annahmen)

Die Expectations sind eine abwärtskompatible Weiterentwicklung der alten Funktion assert(). Sie ermöglichen Assertions ohne Leistungsverluste im Produktionscode und bieten die Möglichkeit, benutzerdefinierte Exceptions auszulösen, wenn eine Assertion fehlschlägt.

Während die alte API aus Kompatibilitätsgründen beibehalten wird, ist assert() nun ein Sprachkonstrukt, das es ermöglicht, dass der erste Parameter ein Ausdruck sein kann und nicht nur ein auszuwertender string-Wert oder ein zu testender bool)-Wert.

<?php
ini_set
('assert.exception'1);

class 
CustomError extends AssertionError {}

assert(false, new CustomError('Irgendeine Fehlermeldung'));
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Fatal error: Uncaught CustomError: Irgendeine Fehlermeldung

Alle Details zu diesem Feature, einschließlich der Konfiguration sowohl in Entwicklungs- und Produktionsumgebungen, befinden sich im Abschnitt Expectations der assert()-Referenz.

Zusammengefasste use-Deklarationen

Klassen, Funktionen und Konstanten, die aus demselben namespace importiert werden, können nun in einer einzigen use-Anweisung zusammengefasst werden.

<?php
// Code vor PHP 7
use some\namespace\ClassA;
use 
some\namespace\ClassB;
use 
some\namespace\ClassC as C;

use function 
some\namespace\fn_a;
use function 
some\namespace\fn_b;
use function 
some\namespace\fn_c;

use const 
some\namespace\ConstA;
use const 
some\namespace\ConstB;
use const 
some\namespace\ConstC;

// Code in PHP 7+
use some\namespace\{ClassAClassBClassC as C};
use function 
some\namespace\{fn_afn_bfn_c};
use const 
some\namespace\{ConstAConstBConstC};
?>

Generatoren können Werte zurückgeben

Dieses Feature baut auf der Generator-Funktionalität auf, die in PHP 5.5 eingeführt wurde. Sie ermöglicht es, eine return-Anweisung innerhalb eines Generators zu verwenden, damit der Wert eines Ausdrucks zurückgegeben werden kann (eine Rückgabe per Referenz ist nicht erlaubt). Dieser Wert kann mit der neuen Methode Generator::getReturn() abgerufen werden, die erst verwendet werden darf, nachdem der Generator die Ausgabe von Werten abgeschlossen hat.

<?php

$gen 
= (function() {
    yield 
1;
    yield 
2;

    return 
3;
})();

foreach (
$gen as $val) {
    echo 
$valPHP_EOL;
}

echo 
$gen->getReturn(), PHP_EOL;

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

1
2
3

Die Möglichkeit, den Endwert eines Generators explizit zurückzugeben, ist sehr nützlich. Dadurch kann der Client-Code, der den Generator ausführt, den letzten vom Generator zurückgegebenen Wert (das Ergebnis einer Berechnung durch eine Art Co-Routine) als Sonderfall behandeln. Dies ist viel einfacher, als einen clientseitigen Code zu schreiben, der zunächst prüft, ob der zurückgegebene Wert der Letzte ist, und ihn dann gegebenenfalls als speziellen Wert behandelt.

Delegierung durch Generatoren

Generatoren können nun automatisch an einen anderen Generator, ein Traversable-Objekt oder ein Array delegieren, ohne dass Boilerplate (redundanter Code) in den äußersten Generator geschrieben werden muss. Dies wird durch die Verwendung des Konstrukts yield from erreicht.

<?php
function gen()
{
    yield 
1;
    yield 
2;
    yield from 
gen2();
}

function 
gen2()
{
    yield 
3;
    yield 
4;
}

foreach (
gen() as $val)
{
    echo 
$valPHP_EOL;
}
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

1
2
3
4

Ganzzahl-Division mit intdiv()

Die neue Funktion intdiv() führt eine Ganzzahl-Division ihrer Operanden durch und gibt das Ergebnis zurück.

<?php
var_dump
(intdiv(103));
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

int(3)

Optionen für Session

Die Funktion session_start() akzeptiert nun ein Array von Optionen. Diese überschreiben die Session-Konfigurationsanweisungen, die normalerweise in der php.ini gesetzt werden.

Diese Optionen unterstützen nun auch session.lazy_write. Diese Option ist standardmäßig aktiviert und bewirkt, dass PHP eine Session-Datei nur dann überschreibt, wenn sich die Session-Daten geändert haben. Außerdem wurde die Option read_and_close hinzugefügt. Sie kann nur an session_start() übergeben werden und gibt an, dass die Session-Daten gelesen werden sollen und die Session dann sofort unverändert geschlossen werden soll.

Um zum Beispiel session.cache_limiter auf private zu setzen und die Session nach dem Lesen sofort zu schließen, kann Folgendes verwendet werden:

<?php
session_start
([
    
'cache_limiter' => 'private',
    
'read_and_close' => true,
]);
?>

preg_replace_callback_array()

Wenn die Funktion preg_replace_callback() verwendet werden müsste, kann stattdessen mit der neuen Funktion preg_replace_callback_array() saubererer Code geschrieben werden. Vor PHP 7 musste für jeden regulären Ausdruck ein Callback ausgeführt werden, was dazu führte, dass die Callback-Funktion voller Verzweigungen sein musste.

Nun können Callbacks für jeden regulären Ausdruck registriert werden, indem ein assoziatives Array verwendet wird, bei dem die regulären Ausdrücke die Schlüssel sind, und die Callback-Funktionen deren Werte.

CSPRNG-Funktionen

Zwei neue Funktionen wurden hinzugefügt, um plattformübergreifend kryptographisch sichere Ganzzahlen und Zeichenketten zu erzeugen: random_bytes() und random_int().

list() kann nun immer Objekte entpacken, die ArrayAccess implementieren

Zuvor war nicht gewährleistet, dass list() bei Objekten, die ArrayAccess implementieren, korrekt funktioniert. Dies wurde nun behoben.

Andere Features

  • Es wurde die Möglichkeit hinzugefügt, beim Klonen auf Klassenelemente zuzugreifen, z. B. (clone $foo)->bar().
add a note

User Contributed Notes 7 notes

up
146
PawelD
6 years ago
<?php
class foo { static $bar = 'baz'; }
var_dump('foo'::$bar);
?>

if < php7.0

then we will receive a syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)

but php7 returns string(3) "baz"

I think it's not documented anywhere
up
40
Adrian Wiik
2 years ago
A good rule of thumb for remembering what the spaceship operator expression returns is to replace the spaceship operator with a minus sign (-). If the result is negative, 0 or positive, the expression will return -1, 0 or 1 respectively.

Example:
<?php
echo 5 <=> 8; // 5 - 8 = -3, prints -1
echo 2 <=> 2; // 2 - 2 = 0, prints 0
echo 4 <=> 2; // 4 - 2 = 2, prints 1
up
12
Julian Sawicki
2 years ago
In php 7.0 it's possible to curry functions in a way that's similar to JavaScript.

<?php

// A curried function
function add($a) {
  return function(
$b) use ($a) {
    return
$a + $b;
  };
}

// Invoking curried function in PHP 7
$result = add(10)(15);

var_dump($result); // int 25

?>

Currying in this way is not possible in php 5.6.
up
9
Julian Sawicki
2 years ago
Currying was possible in php 5.6. But in php 7.0 it is now possible to invoke a curryied function with a one liner.

<?php
// A curried function
function add($a) {
  return function(
$b) use ($a) {
    return
$a + $b;
  };
}

// Invoking a curried function in PHP 7 
$result = add(10)(15);
var_dump($result); // int 25

// Invoking a curried function in PHP 5.6 
$add10 = add(10);
$result = $add10(15);
var_dump($result); // int 25
?>
up
14
ricasiano at gmail dot com
2 years ago
Be careful on performing null coalesce on typecasted properties. Enclose them in parenthesis

<?php
$foo
= new StdClass;
//(int) 23
$bar = $foo->bas ?? 23;
var_dump($bar);

$foo = new StdClass;
//(int) 23
$bar = (int) ($foo->bas ?? 23);
var_dump($bar);

$foo = new StdClass;
$bar = (int) $foo->bas ?? 23;
//Notice: Undefined property: stdClass::$bas
var_dump($bar);
up
5
TerryE
5 years ago
$a = ''; // or 0 or false

$b = $a ?? 'a'; 
// $b is '' or 0 or false

$c = $a ?: 'a';
// $c is 'a'
up
-7
nevercode at pm dot me
2 years ago
It is worth nothing that the following code just works in PHP 7.4:

```
function nullOrDefault($x = null)
{
    $x ??= 3222;

    return $x;
}
```
To Top