Statement on glibc/iconv Vulnerability
Released!
PHP 8.3 ist ein Major-Update der Sprache PHP.
Es beinhaltet viele neue Features und Verbesserungen.
Unter anderem die Typisierung von Klassen-Konstanten, tiefes Klonen von Readonly-Properties und Erweiterungen der Zufallsfunktionalität. Darüber hinaus sind wie üblich Performance-Optimierungen, Bug-Fixes und andere Aufräumarbeiten eingeflossen.

Typisierung von Klassen-Konstanten RFC

PHP < 8.3
interface I {
// We may naively assume that the PHP constant is always a string.
const PHP = 'PHP 8.2';
}

class
Foo implements I {
// But implementing classes may define it as an array.
const PHP = [];
}
PHP 8.3
interface I {
const
string PHP = 'PHP 8.3';
}

class
Foo implements I {
const
string PHP = [];
}

// Fatal error: Cannot use array as value for class constant
// Foo::PHP of type string

Dynamisches Abrufen von Klassen-Konstanten RFC

PHP < 8.3
class Foo {
const
PHP = 'PHP 8.2';
}

$searchableConstant = 'PHP';

var_dump(constant(Foo::class . "::{$searchableConstant}"));
PHP 8.3
class Foo {
const
PHP = 'PHP 8.3';
}

$searchableConstant = 'PHP';

var_dump(Foo::{$searchableConstant});

Das neue #[\Override]-Attribut RFC

PHP < 8.3
use PHPUnit\Framework\TestCase;

final class
MyTest extends TestCase {
protected
$logFile;

protected function
setUp(): void {
$this->logFile = fopen('/tmp/logfile', 'w');
}

protected function
taerDown(): void {
fclose($this->logFile);
unlink('/tmp/logfile');
}
}

// The log file will never be removed, because the
// method name was mistyped (taerDown vs tearDown).
PHP 8.3
use PHPUnit\Framework\TestCase;

final class
MyTest extends TestCase {
protected
$logFile;

protected function
setUp(): void {
$this->logFile = fopen('/tmp/logfile', 'w');
}

#[
\Override]
protected function
taerDown(): void {
fclose($this->logFile);
unlink('/tmp/logfile');
}
}

// Fatal error: MyTest::taerDown() has #[\Override] attribute,
// but no matching parent method exists
Durch das Nutzen des #[\Override]-Attributs bei einer Methode, wird PHP nun sicherstellen, dass diese Methode in einer Elternklasse oder einem implementierten Interface vorhanden ist. Die Angabe des Attributs macht deutlich, dass das Überschreiben der Method absichtlich erfolgt ist und erleichtert ein Refactoring, da das Entfernen der überschriebenen Methode in der Elternklasse dazu führt, dass ein Fehler geworfen wird.

Klonen von Readonly-Properties RFC

PHP < 8.3
class PHP {
public
string $version = '8.2';
}

readonly class
Foo {
public function
__construct(
public
PHP $php
) {}

public function
__clone(): void {
$this->php = clone $this->php;
}
}

$instance = new Foo(new PHP());
$cloned = clone $instance;

// Fatal error: Cannot modify readonly property Foo::$php
PHP 8.3
class PHP {
public
string $version = '8.2';
}

readonly class
Foo {
public function
__construct(
public
PHP $php
) {}

public function
__clone(): void {
$this->php = clone $this->php;
}
}

$instance = new Foo(new PHP());
$cloned = clone $instance;

$cloned->php->version = '8.3';
readonly-Properties können nun innerhalb der magischen __clone Methode geändert werden.

New json_validate() Funktion RFC Doc

PHP < 8.3
function json_validate(string $string): bool {
json_decode($string);

return
json_last_error() === JSON_ERROR_NONE;
}

var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true
PHP 8.3
var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true
json_validate() erlaubt es einen String auf syntaktisch korrektes JSON auf eine effizientere Art und Weise als json_decode() zu prüfen.

Neue Methode Randomizer::getBytesFromString() RFC Doc

PHP < 8.3
// This function needs to be manually implemented.
function getBytesFromString(string $string, int $length) {
$stringLength = strlen($string);

$result = '';
for (
$i = 0; $i < $length; $i++) {
// random_int is not seedable for testing, but secure.
$result .= $string[random_int(0, $stringLength - 1)];
}

return
$result;
}

$randomDomain = sprintf(
"%s.example.com",
getBytesFromString(
'abcdefghijklmnopqrstuvwxyz0123456789',
16,
),
);

echo
$randomDomain;
PHP 8.3
// A \Random\Engine may be passed for seeding,
// the default is the secure engine.
$randomizer = new \Random\Randomizer();

$randomDomain = sprintf(
"%s.example.com",
$randomizer->getBytesFromString(
'abcdefghijklmnopqrstuvwxyz0123456789',
16,
),
);

echo
$randomDomain;
Die Random-Erweiterung, die in PHP 8.2 hinzugefügt wurde, wurde um eine neue Methode erweitert, die es erlaubt einen String zu generieren, der ausschließlich aus bestimmten Zeichen besteht. Diese Methode erlaubt es auf einfache Weise zufällige Bezeichner, wie beispielsweise Domainnamen, und numerische Strings beliebiger Länge zu erzeugen.

Neue Methoden Randomizer::getFloat() und Randomizer::nextFloat() RFC Doc

PHP < 8.3
// Returns a random float between $min and $max, both including.
function getFloat(float $min, float $max) {
// This algorithm is biased for specific inputs and may
// return values outside the given range. This is impossible
// to work around in userland.
$offset = random_int(0, PHP_INT_MAX) / PHP_INT_MAX;

return
$offset * ($max - $min) + $min;
}

$temperature = getFloat(-89.2, 56.7);

$chanceForTrue = 0.1;
// getFloat(0, 1) might return the upper bound, i.e. 1,
// introducing a small bias.
$myBoolean = getFloat(0, 1) < $chanceForTrue;
PHP 8.3
$randomizer = new \Random\Randomizer();

$temperature = $randomizer->getFloat(
-
89.2,
56.7,
\Random\IntervalBoundary::ClosedClosed,
);

$chanceForTrue = 0.1;
// Randomizer::nextFloat() is equivalent to
// Randomizer::getFloat(0, 1, \Random\IntervalBoundary::ClosedOpen).
// The upper bound, i.e. 1, will not be returned.
$myBoolean = $randomizer->nextFloat() < $chanceForTrue;

Durch die limitierte Präzision und der impliziten Rundung von Gleitkommazahlen war das gleichverteilte Generieren von Gleitkommazahlen innerhalb eines vorgegebenen Bereichs nicht einfach. Gängige Userland-Lösungen führen zu einer ungleichmäßigen Verteilung und geben potentiell Zahlen außerhalb des gewünschten Bereichs zurück.

Der Randomizer wurde daher um zwei Methoden erweitert, um zufällige Gleitkommazahlen mit einer Gleichverteilung zu generieren. Die Randomizer::getFloat()-Methode nutzt den γ-section-Algorithmus, welcher in Drawing Random Floating-Point Numbers from an Interval. Frédéric Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022. veröffentlicht wurde.

Kommandozeilen-Linter unterstützt mehrere Dateien PR Doc

PHP < 8.3
php -l foo.php bar.php No syntax errors detected in foo.php
PHP 8.3
php -l foo.php bar.php No syntax errors detected in foo.php No syntax errors detected in bar.php

Der Kommandozeilen-Linter erlaubt nun die Prüfung mehrerer Dateien.

Neue Klassen, Interfaces, und Funktionen

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

To Top