-
match
ist nun ein reserviertes Schlüsselwort.
-
mixed
ist nun ein reserviertes Wort, kann also nicht zur Benennung einer Klasse, Schnittstelle oder eines Traits verwendet werden und darf auch nicht in Namespaces verwendet werden.
-
Assertion-Fehler werden nun standardmäßig ausgelöst. Wenn das alte
Verhalten gewünscht wird, kann in den INI-Einstellungen
assert.exception=0
gesetzt werden.
-
Methoden mit dem gleichen Namen wie die Klasse werden nicht mehr als
Konstruktoren interpretiert. Stattdessen sollte die Methode
__construct() verwendet werden.
-
Die Möglichkeit, nicht-statische Methoden statisch aufzurufen, wurde
entfernt. Deshalb schlägt is_callable() fehl, wenn
eine nicht-statische Methode mit einem Klassennamen geprüft wird (muss
mit einer Objektinstanz überprüft werden).
-
Die Typumwandlungen (real)
und (unset)
wurden
entfernt.
-
Die INI-Direktive track_errors
wurde entfernt. Das bedeutet, dass php_errormsg nicht
mehr verfügbar ist. Stattdessen kann die Funktion
error_get_last() verwendet werden.
-
Die Möglichkeit, Konstanten ohne Berücksichtigung der Groß- und
Kleinschreibung zu definieren, wurde entfernt. Das dritte Argument von
define() kann nicht mehr true
sein.
-
Die Möglichkeit, einen Autoloader mit einer
__autoload()-Funktion anzugeben, wurde entfernt.
Stattdessen sollte spl_autoload_register() verwendet
werden.
-
Der Parameter errcontext
wird nicht mehr an
benutzerdefinierte Fehlerbehandlungen übergeben, die mit der Funktion
set_error_handler() gesetzt wurden.
-
Die Funktion create_function() wurde entfernt.
Stattdessen können anonyme Funktionen verwendet werden.
-
Die Funktion each() wurde entfernt. Stattdessen
sollte foreach
oder ArrayIterator verwendet
werden.
-
Die Möglichkeit, die Bindung von this an Closures
aufzuheben, die mittels Closure::fromCallable()
oder ReflectionMethod::getClosure() aus einer
Methode erzeugt wurden, wurde entfernt.
-
Die Möglichkeit, die Bindung von this an echte
Closures aufzuheben, die this verwenden, wurde
ebenfalls entfernt.
-
Die Möglichkeit, die Funktion array_key_exists() mit
Objekten zu verwenden, wurde entfernt. Stattdessen können
isset() oder property_exists()
verwendet werden.
-
Das Verhalten der Funktion array_key_exists()
entspricht bezüglich des Typs des Parameters key
nun dem Verhalten der Funktion isset() und dem
normalen Array-Zugriff. Alle Schlüsseltypen unterliegen nun den üblichen
Einschränkungen und Array- und Objektschlüssel lösen einen
TypeError aus.
-
Jedes Array, das eine Zahl n als ersten
numerischen Schlüssel hat, verwendet n+1 für
seinen nächsten impliziten Schlüssel, auch wenn
n negativ ist.
-
Die voreingestellte Stufe von error_reporting ist nun
E_ALL
; zuvor waren E_NOTICE
und E_DEPRECATED
ausgeschlossen.
-
display_startup_errors
ist nun standardmäßig aktiviert.
-
Die Verwendung von parent innerhalb einer Klasse, die keine
übergeordnete Klasse hat, führt nun bei der Kompilierung zu einem
schweren Fehler.
-
Der Operator @
unterdrückt nun keine schweren Fehler
(E_ERROR
, E_CORE_ERROR
,
E_COMPILE_ERROR
, E_USER_ERROR
,
E_RECOVERABLE_ERROR
und
E_PARSE
) mehr. Error-Handler, die erwarten, dass
error_reporting 0
ist, wenn @
verwendet wird, sollten so angepasst werden, dass sie stattdessen die
Fehler-Maske prüfen:
<?php
// Dies ersetzen
function my_error_handler($err_no, $err_msg, $filename, $linenum) {
if (error_reporting() == 0) {
return false;
}
// ...
}
// mit Folgendem
function my_error_handler($err_no, $err_msg, $filename, $linenum) {
if (!(error_reporting() & $err_no)) {
return false;
}
// ...
}
?>
Darüber hinaus sollte in Produktivumgebungen darauf geachtet werden,
dass keine Fehlermeldungen angezeigt werden, da dies zu
Informationslecks führen kann. Es sollte sichergestellt werden, dass in
Verbindung mit der Fehleraufzeichnung display_errors=Off
verwendet wird.
-
#[
wird nicht mehr als Beginn eines Kommentars
interpretiert, weil diese Syntax nun für Attribute verwendet wird.
-
Vererbungsfehler aufgrund von inkompatiblen Methodensignaturen
(Verletzung des Liskovschen Substitutionsprinzip, LSP) führen nun immer
zu einem schweren Fehler. Vorher wurde in manchen Fällen eine Warnung
erzeugt.
-
Die Rangfolge des Verkettungsoperators hat sich gegenüber
Bitverschiebungen sowie Addition und Subtraktion geändert.
<?php
echo "Summe: " . $a + $b;
// wurde früher wie folgt interpretiert:
echo ("Summe: " . $a) + $b;
// wird nun interpretiert als:
echo "Summe: " . ($a + $b);
?>
-
Ein Parameter mit einem Standardwert, der bei der Ausführung zu null
aufgelöst wird, wird nicht mehr implizit als nullbarer Parameter
gekennzeichnet. Stattdessen muss explizit entweder ein nullbarer Typ
oder der Standardwert null
verwendet werden.
<?php
// Dies ersetzen
function test(int $arg = CONST_RESOLVING_TO_NULL) {}
// mit
function test(?int $arg = CONST_RESOLVING_TO_NULL) {}
// oder
function test(int $arg = null) {}
?>
-
Einige Warnungen wurden in Error-Exceptions
umgewandelt:
-
Der Versuch, in eine Eigenschaft eines Nicht-Objekts zu schreiben.
Zuvor wurde dadurch implizit ein stdClass-Objekt für null, false und
leere Zeichenketten erstellt.
-
Der Versuch, ein Element an ein Array anzuhängen, für das bereits der
Schlüssel PHP_INT_MAX verwendet wird.
-
Der Versuch, einen ungültigen Typ (Array oder Objekt) als
Array-Schlüssel oder Zeichenketten-Offset zu verwenden.
-
Der Versuch, in einen Array-Index eines skalaren Wertes zu schreiben.
- Der Versuch, ein Nicht-Array/Traversable zu entpacken.
-
Der Versuch, auf unqualifizierte Konstanten zuzugreifen, die nicht
definiert sind. Zuvor führten Zugriffe auf unqualifizierte Konstanten
zu einer Warnung und wurden als Zeichenketten interpretiert.
-
Wenn die falsche Anzahl von Argumenten an eine interne Funktion
übergeben wird, die keinen Parameter mit variabler Länge hat, wird ein
ArgumentCountError geworfen.
-
Wenn ungültige zählbare Typen an count() übergeben
werden, wird ein TypeError geworfen.
Einige Hinweise wurden in Warnungen umgewandelt:
- Der Versuch, eine undefinierte Variable zu lesen.
- Der Versuch, eine undefinierte Eigenschaft zu lesen.
- Der Versuch, einen undefinierten Array-Schlüssel zu lesen.
- Der Versuch, eine Eigenschaft eines Nicht-Objekts zu lesen.
-
Der Versuch, auf einen Array-Index eines Nicht-Arrays zuzugreifen.
- Der Versuch, ein Array in eine Zeichenkette zu konvertieren.
- Der Versuch, eine Ressource als Array-Schlüssel zu verwenden.
-
Der Versuch, null, einen Boolean oder einen Float als
Zeichenketten-Offset zu verwenden.
-
Der Versuch, einen Zeichenketten-Offset zu lesen, der außerhalb des
zulässigen Bereichs liegt.
-
Der Versuch, einem Zeichenketten-Offset eine leere Zeichenkette
zuzuweisen.
-
Der Versuch, einem Zeichenketten-Offset mehrere Bytes zuzuweisen, führt
nun zu einer Warnung.
-
Unerwartete Zeichen in Quelldateien (z. B. NUL-Bytes außerhalb von
Zeichenketten) führen nun statt zu einer Warnung beim Kompilieren zu
einer ParseError-Exception.
-
Nicht abgefangene Exceptions durchlaufen nun einen "sauberen Shutdown",
was bedeutet, dass nach einer nicht abgefangenen Exception die
Destruktoren aufgerufen werden.
-
Der bei der Kompilierung auftretende schwere Fehler "Only variables can
be passed by reference" wurde in die Laufzeit verschoben und in die
Error-Exception "Argument cannot be passed by
reference" umgewandelt.
-
Einige "Only variables should be passed by reference"-Hinweise wurden
in die Exception "Argument cannot be passed by reference" umgewandelt.
-
Der für anonyme Klassen erzeugte Name hat sich geändert. Er enthält nun
den Namen des ersten Elternteils oder der ersten Schnittstelle:
<?php
new class extends ParentClass {};
// -> ParentClass@anonymous
new class implements FirstInterface, SecondInterface {};
// -> FirstInterface@anonymous
new class {};
// -> class@anonymous
?>
Auf den oben gezeigten Namen folgen noch ein NUL-Byte und ein
eindeutiges Suffix.
-
Verweise auf nicht-absolute Trait-Methoden in Anpassungen von
Trait-Aliasen müssen nun eindeutig sein:
<?php
class X {
use T1, T2 {
func as otherFunc;
}
function func() {}
}
?>
Wenn sowohl T1::func()
als auch T2::func()
existieren, wurde dieser Code bisher stillschweigend akzeptiert, und es
wurde angenommen, dass func sich auf T1::func
bezieht. Nun
erzeugt er stattdessen einen schweren Fehler und es muss explizit
entweder T1::func
oder T2::func
geschrieben
werden.
-
Die Signatur von abstrakten Methoden, die in Traits definiert sind, wird
nun anhand der Methode der implementierenden Klasse überprüft:
<?php
trait MyTrait {
abstract private function neededByTrait(): string;
}
class MyClass {
use MyTrait;
// Fehler, da der Rückgabetyp nicht übereinstimmt.
private function neededByTrait(): int { return 42; }
}
?>
-
Deaktivierte Funktionen werden nun genauso behandelt wie nicht
existierende Funktionen. Wenn eine deaktivierte Funktion aufgerufen
wird, wird sie als unbekannt gemeldet, und es ist nun möglich, eine
deaktivierte Funktion neu zu definieren.
-
data://
-Stream-Wrapper sind nicht mehr beschreibbar,
was dem dokumentierten Verhalten entspricht.
-
Die arithmetischen und bitweisen Operatoren +
,
-
, *
, /
,
**
, %
,
<<
, >>
,
&
, |
, ^
,
~
, ++
und --
lösen nun ausnahmslos einen TypeError aus, wenn
einer der der Operanden ein Array, eine Ressource oder ein nicht
überladenes Objekt ist. Die einzige Ausnahme hiervon ist die
Array-Zusammenführung Array +
Array, die weiterhin
unterstützt wird.
-
Die Umwandlung vom Typ Float in den Typ String erfolgt nun immer
unabhängig von der Locale.
<?php
setlocale(LC_ALL, "de_DE");
$f = 3.14;
echo $f, "\n";
// Vorher: 3,14
// Jetzt: 3.14
?>
Siehe printf(), number_format()
und NumberFormatter() für Möglichkeiten, die
Formatierung von Zahlen anzupassen.
-
Die Unterstützung für die veraltete Verwendung von geschweiften Klammern
für den Offset-Zugriff wurde entfernt.
<?php
// Anstelle von:
$array{0};
$array{"key"};
// schreiben Sie:
$array[0];
$array["key"];
?>
-
Wenn der final-Modifikator auf eine private Methode angewendet wird,
wird nun eine Warnung erzeugt, es sei denn, die Methode ist der
Konstruktor.
-
Wenn im Konstruktor eines Objekts exit() aufgerufen
wird, wird der Destruktor des Objekts nicht mehr aufgerufen. Dies
entspricht dem Verhalten, wenn ein Konstruktor eine Exception auslöst.
-
Namen mit Bezug auf einen Namensraum dürfen keine Leerzeichen mehr
enthalten: Während Foo\Bar
als Namensraum-Name erkannt
wird, wird Foo \ Bar
nicht erkannt. Umgekehrt sind
reservierte Schlüsselwörter nun als Namensraumsegmente erlaubt, was auch
die Interpretation des Codes verändern kann: new\x
ist nun
gleichbedeutend mit constant('new\x')
, nicht mit
new \x()
.
-
Verschachtelte ternäre Ausdrücke müssen nun explizit in Klammern gesetzt
werden.
-
Die Funktionen debug_backtrace() und
Exception::getTrace() referenzieren nun keine
Parameter mehr. Es ist nicht mehr möglich, über einen Backtrace die
Parameter einer Funktion zu ändern.
-
Die Handhabung numerischer Zeichenketten wurde geändert, damit sie
intuitiver und weniger fehleranfällig ist. Nachfolgende Leerzeichen sind
nun in numerischen Zeichenketten erlaubt, um mit der Behandlung von
führenden Leerzeichen übereinzustimmen. Dies betrifft hauptsächlich:
- Die Funktion is_numeric()
- Vergleiche zwischen Zeichenketten
- Typdeklarationen
- Inkrement- und Dekrement-Operationen
Das Konzept einer "vorangestellten numerischen Zeichenkette" wurde
größtenteils aufgegeben; die Fälle, in denen dies beibehalten wird,
dienen dazu, die Umstellung zu erleichtern. Zeichenketten, die eine
E_NOTICE
"A non well-formed numeric value
encountered" ausgaben, geben nun eine E_WARNING
"A
non-numeric value encountered" aus, und alle Zeichenketten, die eine
E_WARNING
"A non-numeric value encountered"
ausgaben, lösen nun einen TypeError aus. Dies
betrifft vor allem:
- Arithmetische Operationen
- Bitweise Operationen
Diese Änderung von E_WARNING
zu
TypeError betrifft auch die
E_WARNING
"Illegal string offset 'string'" für
unzulässige Zeichenketten-Offsets. Das Verhalten von expliziten
Umwandlungen von Zeichenketten in int/float hat sich nicht geändert.
-
Magische Methoden werden nun auf ihre Parameter und Rückgabetypen
geprüft, falls sie diese deklariert haben. Die Signaturen sollten der
folgenden Liste entsprechen:
__call(string $name, array $arguments): mixed
__callStatic(string $name, array $arguments): mixed
__clone(): void
__debugInfo(): ?array
__get(string $name): mixed
__invoke(mixed $arguments): mixed
__isset(string $name): bool
__serialize(): array
__set(string $name, mixed $value): void
__set_state(array $properties): object
__sleep(): array
__unserialize(array $data): void
__unset(string $name): void
__wakeup(): void
-
Array-Schlüssel, die an die Funktion
call_user_func_array() übergeben werden, werden nun
als Namen der Parameter interpretiert. In früheren Versionen wurden sie
stillschweigend ignoriert.
-
Die Deklaration einer Funktion namens assert()
innerhalb eines Namensraums ist nicht mehr erlaubt und erzeugt einen
E_COMPILE_ERROR
. Die Funktion
assert() unterliegt einer speziellen Verarbeitung
durch die Engine, was zu einem inkonsistenten Verhalten führen kann,
wenn eine Funktion mit demselben Namen innerhalb eines Namensraums
definiert wird.