## Sonstige Änderungen

### PHP-Kern

#### FFI

Die Methode FFI::load() kann nun während des Preloads aufgerufen werden, wenn opcache.preload_user der aktuelle Systembenutzer ist. Zuvor war der Aufruf von FFI::load() während des Preloads nicht möglich, wenn die Direktive opcache.preload_user gesetzt war.

#### FPM

Der FPM CLI-Test schlägt nun fehl, wenn der Socket-Pfad länger ist als vom Betriebssystem unterstützt.

#### Opcache

In den SAPIs CLI und phpdbg muss die Direktive opcache.preload_user nicht mehr für das Preloading gesetzt werden, wenn sie als root ausgeführt werden. In anderen SAPIs ist diese Direktive weiterhin erforderlich, wenn sie als root ausgeführt werden, weil das Preloading durchgeführt wird, bevor die SAPI zu einem unprivilegierten Benutzer wechselt.

#### Streams

Wenn die Funktion fread() auf einer Socket-Verbindung blockiert wird und gepufferte Daten vorhanden sind, gibt sie diese sofort zurück, statt auf weitere Daten zu warten.

Ein Speicherstrom schlägt nicht mehr fehl, wenn der Such-Offset über das Ende hinausgeht. Stattdessen wird der Speicher beim nächsten Schreibvorgang vergrößert und der Bereich zwischen dem alten Ende und dem Offset wird mit Nullbytes gefüllt, ähnlich wie es auch bei Dateien der Fall ist.

stat()-Zugriffsoperationen wie file_exists() und ähnliche verwenden nun den tatsächlichen Pfad statt des aktuellen Stream-Pfads, was mit dem Öffnen von Streams übereinstimmt.

### Änderungen in SAPI-Modulen

#### CLI

Die `STDOUT`-, `STDERR`- und `STDIN`-Streams werden nicht mehr geschlossen, wenn die Ressource zerstört wird, was in der Regel beim Beenden der CLI der Fall ist. Es ist jedoch immer noch möglich, diese Streams mittels fclose() und ähnlichem explizit zu schließen.

### Geänderte Funktionen

#### PHP-Kern

Bei der Funktion gc_status() wurden die folgenden 8 Felder hinzugefügt:

- `"running"` => bool
- `"protected"` => bool
- `"full"` => bool
- `"buffer_size"` => int
- `"application_time"` => float: die gesamte Ausführungszeit der Anwendung in Sekunden (einschließlich collector_time)
- `"collector_time"` =>float: die Zeit, die mit dem Sammeln von Zyklen verbracht wurde, in Sekunden (einschließlich destructor_time und free_time)
- `"destructor_time"` => float: die Zeit, die während des Sammelns von Zyklen für die Ausführung von Destruktoren benötigt wurde, in Sekunden
- `"free_time"` => float: die Zeit, die während des Sammelns von Zyklen dafür benötigt wurde, Speicher freizugeben, in Sekunden

Mit der Funktion class_alias() kann nun ein Alias einer internen Klasse erstellt werden.

Wenn open_basedir zur Laufzeit mittels `ini_set('open_basedir', ...);` gesetzt wird, werden keine Pfade mehr akzeptiert, die das übergeordnete Verzeichnis (`..`) enthalten; zuvor waren nur die Pfade unzulässig, die mit `..` beginnen. Dies konnte leicht umgangen werden, indem dem Pfad `./` vorangestellt wurde.

Benutzerdefinierte Exception-Handler fangen nun Exceptions beim Herunterfahren ab.

Die HTML-Ausgabe der Funktionen highlight_string() und highlight_file() wurde geändert. Leerzeichen zwischen äußeren HTML-Tags werden entfernt. Zeilenumbrüche und Leerzeichen werden nicht mehr in HTML-Entities umgewandelt. Der gesamte HTML-Text wird nun in `<pre>`-Tags eingeschlossen. Die äußeren `<span>`-Tags wurden mit den `<code>`-Tags verschmolzen.

#### Calendar

Die Funktion easter_date() unterstützt nun auf 64-Bit-Systemen die Jahreszahlen von 1970 bis 2.000.000.000; bisher wurden nur die Jahre im Bereich von 1970 bis 2037 unterstützt.

#### Curl

Die Funktion curl_getinfo() unterstützt nun zwei neue Konstanten: `CURLINFO_CAPATH` und `CURLINFO_CAINFO`. Wenn der Wert des Parameters option `null` ist, stehen die zwei zusätzlichen Schlüssel `"capath"` und `"cainfo"` zur Verfügung.

#### DOM

Der voreingestellte Rückgabetyp der Methode DOMCharacterData::appendData() wurde auf true geändert.

Der voreingestellte Rückgabetyp der Methoden DOMDocument::loadHTML(), DOMDocument::loadHTMLFile() und DOMDocument::loadXML() ist nun bool. Zuvor war dies mit dem Rückgabetyp `DOMDocument|bool` dokumentiert, aber seit PHP 8.0.0 kann ein Objekt der Klasse DOMDocument nicht mehr zurückgegeben werden, da es nicht mehr statisch aufgerufen werden kann.

#### Gd

Die Signatur der Funktion imagerotate() wurde geändert. Der Parameter `$ignore_transparent` wurde entfernt, da er seit PHP 5.5.0 ignoriert wurde.

#### Intl

Die Funktion datefmt_set_timezone() und ihr Alias, die Methode IntlDateformatter::setTimeZone(), geben nun bei Erfolg `true` zurück; zuvor wurde `null` zurückgegeben.

Die Methode IntlBreakiterator::setText() gibt nun bei Erfolg `true` und bei einem Fehler `false` zurück; zuvor gab sie in beiden Fällen `null` zurück.

Die Methode IntlChar::enumCharNames() gibt nun einen booleschen Wert zurück; zuvor gab sie bei Erfolg `null` und bei einem Fehler `false` zurück.

Die Methode IntlDateFormatter::__construct() wirft eine `U_ILLEGAL_ARGUMENT_ERROR`-Exception, wenn eine ungültige Locale gesetzt gesetzt wurde.

#### MBString

Die Funktionen mb_strtolower() und mb_convert_case() implementieren für den griechischen Buchstaben Sigma die Regeln der bedingten Groß- und Kleinschreibung. Bei der Funktion mb_convert_case() gilt die bedingte Groß-/Kleinschreibung nur für die Modi `MB_CASE_LOWER` und `MB_CASE_TITLE`, nicht aber für `MB_CASE_LOWER_SIMPLE` und `MB_CASE_TITLE_SIMPLE`.

Die Funktion mb_decode_mimeheader() interpretiert Unterstriche in QPrint-kodierten MIME-kodierten Wörtern gemäß RFC 2047 und wandelt sie in Leerzeichen um. Unterstriche müssen in solchen MIME-kodierten Wörtern als `"=5F"` kodiert werden.

In seltenen Fällen kodiert die Funktion mb_encode_mimeheader() die Eingabezeichenkette um, während sie in PHP 8.2 als reines ASCII durchgereicht würde.

Die Funktion mb_encode_mimeheader() entfernt keine NUL- (Null) Bytes mehr, wenn die Eingabezeichenkette in Qprint-Kodierung vorliegt. Dies führte in früheren Versionen bei bestimmten Textkodierungen, insbesondere UTF-16 und UTF-32, dazu, dass Zeichenketten von mb_encode_mimeheader beschädigt wurden.

Der "non-strict"-Modus der Funktion mb_detect_encoding() verhält sich nun wie in der Dokumentation beschrieben. Zuvor gab sie `false` zurück, wenn ein bestimmtes Byte (z. B. das Erste) der Eingabezeichenkette in allen möglichen Kodierungen ungültig war. Allgemeiner ausgedrückt: Alle in Frage kommenden Kodierungen, in denen ein solches Byte ungültig war, wurden ausgeschlossen, und wenn dasselbe Byte alle verbleibenden Kodierungen ausschloss, die noch in Frage kamen, wurde `false` zurückgegeben. Wurden hingegen alle in Frage kommenden Kodierungen bis auf eine ausgeschlossen, wurde die letzte verbleibende Kodierung zurückgegeben, ohne Rücksicht darauf, wie viele Kodierungsfehler später in der Zeichenkette auftreten könnten. Dies unterscheidet sich von dem in der Dokumentation beschriebenen Verhalten, das besagt: "Wenn strict auf false gesetzt ist, wird die am besten passende Kodierung zurückgegeben."

#### mysqli

Die Funktion mysqli_fetch_object() wirft nun einen ValueError statt einer Exception, wenn das Argument `$constructor_args` nicht leer ist, die Klasse aber keinen Konstruktor hat.

Die Funktion mysqli_poll() wirft nun einen ValueError, wenn weder das Argument `$read` noch das Argument `$error` übergeben wird.

Der Rückgabetyp der Funktion mysqli_field_seek() und der Methode mysqli_result::field_seek() wurde von bool auf true geändert.

#### ODBC

Die Funktion odbc_autocommit() akzeptiert nun `null` als Wert für den Parameter `$enable`. Die Übergabe von `null` entspricht der Übergabe von nur einem Parameter, d. h. die Funktion zeigt an, ob autocommit aktiviert ist oder nicht.

#### PGSQL

Die Funktion pg_fetch_object() wirft nun einen ValueError statt einer Exception, wenn das Argument `$constructor_args` nichtleer ist, die Klasse aber keinen Konstruktor hat.

Die Funktion pg_insert() wirft nun einen ValueError statt eine `E_WARNING`-Meldung auszugeben, wenn die angegebene Tabelle ungültig ist.

Wenn der Wert/Typ eines Feldes nicht mit dem PostgreSQL-Typ übereinstimmt, werfen die Funktionen pg_insert() und pg_convert() einen ValueError oder einen TypeError, statt eine `E_WARNING`-Meldung auszugeben.

Bei den Funktionen pg_fetch_result(), pg_field_prtlen() und pg_field_is_null() kann der Wert des Parameters `$row` nun `null` sein.

#### Random

Die Funktionen mt_srand() und srand() prüfen nun nicht mehr die Anzahl der Argumente, um festzustellen, ob ein Zufallswert (Seed) verwendet werden soll. Wenn `null` übergeben wird, wird ein Seed erzeugt, bei `0` wird Null als Seed verwendet. Damit entspricht das Verhalten dieser Funktionen dem der Methode Random\Engine\Mt19937::__construct().

#### Reflection

Der Rückgabetyp der Methode ReflectionClass::getStaticProperties() kann nicht mehr `null` sein.

#### Standard

Bei der Funktion unserialize() wurden Meldungen der Stufe `E_NOTICE` auf `E_WARNING` hochgestuft.

Die Funktion unserialize() gibt nun eine neue Meldung der Stufe `E_WARNING` aus, wenn nicht alle Bytes der Eingabe verarbeitet wurden.

Die Funktion array_pad() ist nun nur noch durch die maximale Anzahl der Elemente begrenzt, die ein Array haben kann; zuvor konnten nur maximal 1048576 Elemente auf einmal hinzugefügt werden.

Die Funktion strtok() erzeugt eine Meldung der Stufe `E_WARNING`, wenn beim Start der Tokenisierung kein Token angegeben wird.

Wenn die Erzeugung des Salt fehlschlägt, verkettet die Funktion password_hash() nun die zugrundeliegende Random\RandomException als `$previous`-Exception der ValueError-Exception.

Wenn ein Array als Parameter `$command` an die Funktion proc_open() übergeben wird, muss es nun mindestens ein nichtleeres Element enthalten; andernfalls wird ein ValueError geworfen.

Wenn das `$command`-Array ein ungültiger Befehl ist, gibt die Funktion proc_open() `false` zurück, statt ein Ressourcenobjekt, das später eine Warnung erzeugt. Dies war unter Windows bereits der Fall und ist nun auch der Fall, wenn eine posix_spawn-Implementierung verwendet wird (die meisten Linux-, BSD- und MacOS-Plattformen). Es gibt noch ein paar alte Plattformen, bei denen sich dieses Verhalten nicht geändert hat, da posix_spawn dort nicht unterstützt wird.

Die Funktionen array_sum() und array_product() geben nun eine Warnung aus, wenn Werte in einem Array nicht in int/float umgewandelt werden können. Zuvor wurden Arrays und Objekte ignoriert, während alle anderen Werte in int umgewandelt wurden. Außerdem werden Objekte, die eine Umwandlung in eine Zahl definieren (z. B. GMP), nun umgewandelt statt ignoriert.

Der Parameter `$decimals` der Funktion number_format() verarbeitet nun auch negative Zahlen korrekt. Wenn `$decimals` einen negativen Wert hat, wird `$num` auf `$decimals` signifikante Stellen vor dem Dezimaltrennzeichen gerundet. Zuvor wurden negative `$decimals` stillschweigend ignoriert und die Zahl wurde auf null Dezimalstellen gerundet.

Der Funktion strrchr() wurde der neue Parameter `$before_needle` hinzugefügt. Er verhält sich wie der entsprechende Parameter der Funktionen strstr() und stristr().

Die Funktionen str_getcsv() und fgetcsv() geben nun für das letzte Feld eine leere Zeichenkette statt einer Zeichenkette mit einem einzelnen Null-Byte zurück, wenn dieses Feld nur eine nicht terminierte Enclosure (Einschließung) enthält.

### Sonstige Änderungen bei Erweiterungen

#### Core

Die Anwendung des Inkrement/Dekrement-Operators (`++`/`--`) auf einen Wert vom Typ bool führt nun zu einer Warnung. Der Grund dafür ist, dass dieser Operator zwar derzeit keine Wirkung hat, sich aber in Zukunft wie `$bool += 1` verhalten wird.

Die Anwendung des Dekrement-Operators (`--`) auf einen Wert vom Typ null führt nun zu einer Warnung. Der Grund dafür ist, dass dieser Operator zwar derzeit keine Wirkung hat, sich aber in Zukunft wie `$null -= 1` verhalten wird.

Interne Objekte, die die _IS_NUMBER-Umwandlung implementieren, aber keinen do_operator-Handler, der die Addition und Subtraktion überschreibt, können nun inkrementiert und dekrementiert werden, als ob `$o += 1` oder `$o -= 1` ausgeführt worden wäre.

#### DOM

Der DOM-Mechanismus zur Verwaltung der Lebensdauer wurde dahingehend überarbeitet, dass implizit gelöschte Knoten weiterhin abgerufen werden können; zuvor führte dies zu einer Exception.

#### SQLite3

Die Klasse SQLite3 wirft nun eine SQLite3Exception (eine Erweiterung von Exception) statt einer Exception.

Der SQLite-Fehlercode wird nun im Fehlercode der Exception übergeben, statt in der Fehlermeldung enthalten zu sein.

### Änderungen bei der Handhabung von INI-Dateien

- Die `assert.*`-INI-Direktiven sind veraltet. Dies betrifft die folgenden Direktiven:

  - assert.active
  - assert.bail
  - assert.callback
  - assert.exception
  - assert.warning
  Wenn der Wert einer Direktive mit dem Standardwert übereinstimmt, wird keine Meldung über die Missbilligung ausgegeben. Statt dieser Direktiven sollte die INI-Direktive zend.assertions verwendet werden.

- zend.max_allowed_stack_size ist eine neue INI-Direktive, mit der die maximal erlaubte Stackgröße festgelegt werden kann; mögliche Werte sind `0` (erkennt die maximale Stackgröße des Prozesses oder Threads), `-1` (kein Limit) oder eine positive Anzahl von Bytes. Der Standardwert ist `0`. Wenn es nicht möglich ist, die maximale Stackgröße des Prozesses oder Threads zu ermitteln, wird eine bekannte Systemvorgabe verwendet. Wird dieser Wert zu hoch eingestellt, hat das den gleichen Effekt wie die Deaktivierung der Stack-Größenbegrenzung. Fibers verwenden fiber.stack_size als maximal erlaubte Stackgröße. Wenn der Stack des Prozessaufrufs zend.max_allowed_stack_size-zend.reserved_stack_size Bytes überschreitet, wird ein Error geworfen, um Segmentierungsfehler durch Stack-Überlauf zu verhindern und damit die Fehlersuche zu erleichtern. Die Stackgröße erhöht sich während unkontrollierter Rekursionen mit internen Funktionen oder den magischen Methoden __toString(), __clone(), __sleep(), __destruct(). Dies hat nichts mit Stack-Pufferüberläufen zu tun und ist somit auch keine Sicherheitsmaßnahme.

- zend.reserved_stack_size ist eine neue INI-Direktive, mit der die zu reservierende Stackgröße in Bytes festgelegt werden kann. Wenn die Stackgröße überprüft wird, wird dieser Wert als Puffer von der maximal erlaubten Stackgröße abgezogen.

### Performance

#### DOM

Beim Durchlaufen einer Schleife über eine DOMNodeList wird nun ein Zwischenspeicher verwendet. Dadurch steigt die Zeit, die für die Abfrage von Elementen benötigt wird, nicht mehr standardmäßig quadratisch an.

Wenn Textinhalte von Knoten abgerufen werden, wird nun vermieden, Speicher zuzuweisen, was zu einem Leistungsgewinn führt.

DOMChildNode::remove() läuft nun mit O(1)-Performance.

#### Standard

Die flags-Fehlerprüfung der Funktion file() ist nun etwa 7% schneller.

#### SPL

Die Klasse RecursiveDirectoryIterator führt nun weniger I/O (Ein-/Ausgabeoperationen) durch, wenn ein Verzeichnis in einer Schleife durchlaufen wird.

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open