## Nicht abwärtskompatible Änderungen

### PHP-Kern

#### Vergleich zwischen Zeichenketten und Zahlen

Einfache (nicht-strikte) Vergleiche zwischen Zahlen und nicht-numerischen Zeichenketten erfolgen nun durch Umwandlung der Zahl in eine Zeichenkette und den Vergleich der Zeichenketten. Vergleiche zwischen Zahlen und numerischen Zeichenketten funktionieren weiterhin wie bisher. Insbesondere bedeutet dies, dass `0 == "keine Zahl"` nun als falsch angesehen wird.

Vergleich | Vor der Änderung | Nach der Änderung
--- | --- | ---
`0 == "0"` | `true` | `true`
`0 == "0.0"` | `true` | `true`
`0 == "foo"` | `true` | `false`
`0 == ""` | `true` | `false`
`42 == " 42"` | `true` | `true`
`42 == "42foo"` | `true` | `false`

#### Andere inkompatible Änderungen

- `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.

### Umstellung von Ressourcen auf Objekte

Mehrere Ressourcen wurden in Objekte umgewandelt. Die Überprüfung des Rückgabewerts mit der Funktion is_resource() sollte durch eine Überprüfung auf `false` ersetzt werden.

- Die Funktion curl_init() gibt nun ein CurlHandle-Objekt statt einer Ressource zurück. Die Funktion curl_close() hat keine Wirkung mehr; stattdessen wird die CurlHandle-Instanz automatisch zerstört, wenn sie nicht mehr referenziert wird.

- Die Funktion curl_multi_init() gibt nun ein CurlMultiHandle-Objekt statt einer Ressource zurück. Die Funktion curl_multi_close() hat keine Wirkung mehr; stattdessen wird die CurlMultiHandle-Instanz automatisch zerstört, wenn sie nicht mehr referenziert wird.

- Die Funktion curl_share_init() gibt nun ein CurlShareHandle-Objekt statt einer Ressource zurück. Die Funktion curl_share_close() hat keine Wirkung mehr; stattdessen wird die CurlShareHandle-Instanz automatisch zerstört, wenn sie nicht mehr referenziert wird.

- Die Funktion enchant_broker_init() gibt nun ein EnchantBroker-Objekt statt einer Ressource zurück.

- Die Funktionen enchant_broker_request_dict() und enchant_broker_request_pwl_dict() geben nun ein EnchantDictionary-Objekt statt einer Ressource zurück.

- Die Erweiterung GD verwendet nun GdImage-Objekte statt Ressourcen als zugrundeliegende Datenstruktur für Bilder. Die Funktion imagedestroy() hat keine Wirkung mehr; stattdessen wird die GdImage-Instanz automatisch zerstört, wenn sie nicht mehr referenziert wird.

- Die Funktionen openssl_x509_read() und openssl_csr_sign() geben nun ein OpenSSLCertificate-Objekt statt einer Ressource zurück. Die Funktion openssl_x509_free() ist veraltet und hat keine Wirkung mehr; stattdessen wird die OpenSSLCertificate-Instanz automatisch zerstört, wenn sie nicht mehr referenziert wird.

- Die Funktion openssl_csr_new() gibt nun statt einer Ressource ein OpenSSLCertificateSigningRequest-Objekt zurück.

- Die Funktion openssl_pkey_new() gibt nun ein OpenSSLAsymmetricKey-Objekt statt einer Ressource zurück. Die Funktion openssl_pkey_free() ist veraltet und hat keine Wirkung mehr; stattdessen wird die OpenSSLAsymmetricKey-Instanz automatisch zerstört, wenn sie nicht mehr referenziert wird.

- Die Funktion shmop_open() gibt nun ein Shmop-Objekt statt einer Ressource zurück. Die Funktion shmop_close() hat keine Wirkung mehr und ist veraltet; stattdessen wird die Shmop-Instanz automatisch zerstört, wenn sie nicht mehr referenziert wird.

- Die Funktionen socket_create(), socket_create_listen(), socket_accept(), socket_import_stream(), socket_addrinfo_connect(), socket_addrinfo_bind() und socket_wsaprotocol_info_import() geben nun ein Socket-Objekt statt einer Ressource zurück. Die Funktion socket_addrinfo_lookup() gibt nun ein Array von AddressInfo-Objekten statt Ressourcen zurück.

- Die Funktion msg_get_queue() gibt nun ein SysvMessageQueue-Objekt statt einer Ressource zurück.

- Die Funktion sem_get() gibt nun ein SysvSemaphore-Objekt statt einer Ressource zurück.

- Die Funktion shm_attach() gibt nun ein SysvSharedMemory-Objekt statt einer Ressource zurück.

- Die Funktionen xml_parser_create() und xml_parser_create_ns() geben nun ein XMLParser-Objekt statt einer Ressource zurück. Die Funktion xml_parser_free() hat keine Wirkung mehr; stattdessen wird die XMLParser-Instanz automatisch zerstört, wenn sie nicht mehr referenziert wird.

- Die XMLWriter-Funktionen akzeptieren nun XMLWriter-Objekte statt Ressourcen und geben diese zurück.

- Die Funktion inflate_init() gibt nun ein InflateContext-Objekt statt einer Ressource zurück.

- Die Funktion deflate_init() gibt nun ein DeflateContext-Objekt statt einer Ressource zurück.

### COM und .Net (Windows)

Die Möglichkeit, Konstanten ohne Berücksichtigung der Groß-/Kleinschreibung aus Typbibliotheken zu importieren, wurde entfernt. Das zweite Argument der Funktion com_load_typelib() kann nicht mehr false sein; com.autoregister_casesensitive kann nicht mehr deaktiviert werden. Das bedeutet, dass #case_insensitive-Markierungen in com.typelib_file ignoriert werden.

### CURL

`CURLOPT_POSTFIELDS` akzeptiert keine Objekte mehr als Arrays. Um ein Objekt als Array zu interpretieren, muss eine explizite Umwandlung mittels `(array)` durchgeführt werden. Dasselbe gilt auch für andere Optionen, die Arrays akzeptieren.

### Datum und Uhrzeit

Die Funktionen mktime() und gmmktime() benötigen nun mindestens einen Parameter. Die Funktion time() kann verwendet werden, um den aktuellen Zeitstempel zu erhalten.

### DOM

Nicht implementierte Klassen aus der Erweiterung DOM, die keinerlei Funktion hatten und Testdaten enthielten, wurden entfernt. Diese Klassen wurden auch aus der neuesten Version des des DOM-Standards entfernt:

- DOMNameList
- DomImplementationList
- DOMConfiguration
- DomError
- DomErrorHandler
- DOMImplementationSource
- DOMLocator
- DOMUserDataHandler
- DOMTypeInfo
- DOMStringExtend

Nicht implementierte Methoden aus der Erweiterung DOM, die keinerlei Funktion hatten, wurden entfernt:

- DOMNamedNodeMap::setNamedItem()
- DOMNamedNodeMap::removeNamedItem()
- DOMNamedNodeMap::setNamedItemNS()
- DOMNamedNodeMap::removeNamedItemNS()
- DOMText::replaceWholeText()
- DOMNode::compareDocumentPosition()
- DOMNode::isEqualNode()
- DOMNode::getFeature()
- DOMNode::setUserData()
- DOMNode::getUserData()
- DOMDocument::renameNode()

### Enchant

- Die Funktionen enchant_broker_list_dicts(), enchant_broker_describe() und enchant_dict_suggest() geben nun ein leeres Array anstelle von `null` zurück.

### Exif

Die Funktion read_exif_data() wurde entfernt; stattdessen sollte die Funktion exif_read_data() verwendet werden.

### Filter

- Die Flags `FILTER_FLAG_SCHEME_REQUIRED` und `FILTER_FLAG_HOST_REQUIRED` für den Filter `FILTER_VALIDATE_URL` wurden entfernt. `scheme` und `host` sind (und waren) immer erforderlich.

- Die Konstanten `INPUT_REQUEST` und `INPUT_SESSION`, die u. a. für die Funktion filter_input() verwendet wurden, wurden entfernt. Sie wurden nie implementiert und ihre Verwendung löste immer eine Warnung aus.

### GD

- Die veraltete Funktion image2wbmp() wurde entfernt.

- Die veralteten Funktionen png2wbmp() und jpeg2wbmp() wurden entfernt.

- Bei der Funktion imagecropauto() akzeptiert der Standardparameter `mode` den Wert `-1` nicht mehr. Stattdessen sollte `IMG_CROP_DEFAULT` verwendet werden.

- Unter Windows wurde die Datei php_gd2.dll in php_gd.dll umbenannt.

### GMP

Die Funktion gmp_random() wurde entfernt. Stattdessen sollte eine der Funktionen gmp_random_range() und gmp_random_bits() verwendet werden.

### Iconv

iconv-Implementierungen, die errno beim Auftreten von Fehlern nicht korrekt setzen, werden nicht mehr unterstützt.

### IMAP

- Bei der Funktion imap_headerinfo() wurde der nicht verwendete Parameter `default_host` entfernt.

- Die Funktion imap_header(), die ein Alias von imap_headerinfo() ist, wurde entfernt.

### Funktionen für die Internationalisierung

- Die veraltete Konstante `INTL_IDNA_VARIANT_2003` wurde entfernt.

- Die veraltete Konstante `Normalizer::NONE` wurde entfernt.

### LDAP

- Die veralteten Funktionen ldap_sort(), ldap_control_paged_result() und ldap_control_paged_result_response() wurden entfernt.

- Die Schnittstelle der Funktion ldap_set_rebind_proc() hat sich geändert; der Parameter `callback` akzeptiert keine leeren Zeichenketten nicht mehr; stattdessen sollte `null` verwendet werden.

### MBString

- Die Direktive mbstring.func_overload wurde entfernt. Die zugehörigen Konstanten `MB_OVERLOAD_MAIL`, `MB_OVERLOAD_STRING` und `MB_OVERLOAD_REGEX` wurden ebenfalls entfernt. Außerdem wurden in der Funktion mb_get_info() die Einträge `"func_overload"` und `"func_overload_list"` entfernt.

- Die Funktion mb_parse_str() kann nicht mehr ohne Angabe eines Ergebnis-Arrays verwendet werden.

- Eine Reihe veralteter mbregex-Aliase wurde entfernt. Siehe die folgende Liste, welche Funktionen stattdessen verwendet werden sollten:

  - mbregex_encoding() → mb_regex_encoding()
  - mbereg() → mb_ereg()
  - mberegi() → mb_eregi()
  - mbereg_replace() → mb_ereg_replace()
  - mberegi_replace() → mb_eregi_replace()
  - mbsplit() → mb_split()
  - mbereg_match() → mb_ereg_match()
  - mbereg_search() → mb_ereg_search()
  - mbereg_search_pos() → mb_ereg_search_pos()
  - mbereg_search_regs() → mb_ereg_search_regs()
  - mbereg_search_init() → mb_ereg_search_init()
  - mbereg_search_getregs() → mb_ereg_search_getregs()
  - mbereg_search_getpos() → mb_ereg_search_getpos()
  - mbereg_search_setpos() → mb_ereg_search_setpos()

- Bei der Funktion mb_ereg_replace() wurde der Modifikator `e` entfernt. Stattdessen sollte die Funktion mb_ereg_replace_callback() verwendet werden.

- Wenn bei der Funktion mb_ereg_replace() der Parameter für das Suchmuster keine Zeichenkette ist, wird er nun als Zeichenkette anstelle eines ASCII-Codepunkts interpretiert. Das vorherige Verhalten kann durch einen expliziten Aufruf der Funktion chr() wiederhergestellt werden.

- Der Parameter `needle` darf bei den Funktionen mb_strpos(), mb_strrpos(), mb_stripos(), mb_strripos(), mb_strstr(), mb_stristr(), mb_strrchr() und mb_strrichr() nun leer sein.

- Bei der Funktion mb_decode_numericentity() wurde der intern nicht verwendete Parameter `is_hex` entfernt.

- Bei der Funktion mb_strrpos() wurde das alte Verhalten bei Übergabe der Kodierung anstelle eines Offsets als dritter Parameter entfernt; stattdessen sollte der Offset `0` explizit als viertes Argument angegeben werden.

- Die Aliase für die `ISO_8859-*`-Zeichenkodierungen wurden durch die `ISO8859-*`-Aliase ersetzt, um die Interoperabilität mit der Erweiterung iconv zu verbessern. Die ISO-8859-Aliase von mbregex mit Unterstrichen (`ISO_8859_*` und `ISO8859_*`) wurden ebenfalls entfernt.

- Die Funktionen mb_ereg() und mb_eregi() geben bei einer gefundenen Übereinstimmung nun den booleschen Wert `true` zurück. Zuvor gaben sie den Integerwert `1` zurück, wenn der Parameter `matches` nicht übergeben wurde. Wenn `matches` übergeben wurde, gaben sie `max(1, strlen($matches[0]))` zurück.

### OCI8

- Die Klassen OCI-Lob und OCI-Collection wurden umbenannt in OCILob bzw. OCICollection, um die Namenskonformität zu gewährleisten, die in PHP 8 durch die arginfo-Tools für Anmerkungen zum Typ (arginfo type annotation tooling) erzwungen wird.

- Mehrere Alias-Funktionen wurden als veraltet markiert.

- Die Funktion oci_internal_debug() und ihr Alias ociinternaldebug() wurden entfernt.

### ODBC

- Die Funktion odbc_connect() verwendet Verbindungen nicht mehr wieder.

- Bei der Funktion odbc_exec() wurde der nicht verwendete Parameter `flags` entfernt.

### OpenSSL

- Den Funktionen openssl_seal() und openssl_open() muss nun der Parameter `method` übergeben werden, da der bisherige Standardwert `"RC4"` als unsicher eingestuft wird.

### Reguläre Ausdrücke (Perl-kompatibel)

Wenn ungültige Escape-Sequenzen übergeben werden, werden sie nicht mehr als Literale interpretiert. Dieses Verhalten erforderte bisher den Modifikator `X`, der nun ignoriert wird.

### PHP Data Objects

- Der Standardmodus für die Fehlerbehandlung wurde von "silent" auf "exceptions" geändert. Siehe Fehler und Fehlerbehandlung für Details.

- Die Signaturen einiger PDO-Methoden haben sich geändert:

  - `PDO::query(string $query, ?int $fetchMode = null, mixed ...$fetchModeArgs)`
  - `PDOStatement::setFetchMode(int $mode, mixed ...$args)`

### PDO-ODBC

Die php.ini-Direktive pdo_odbc.db2_instance_name wurde entfernt.

### PDO-MySQL

Die Methode PDO::inTransaction() meldet nun den tatsächlichen Transaktionsstatus der Verbindung, anstatt einer ungefähren Angabe, die von PDO verwaltet wird. Wenn eine Abfrage mit einem "impliziten Commit" ausgeführt wird, gibt PDO::inTransaction() anschließend `false` zurück, da die Transaktion nicht mehr aktiv ist.

### PostgreSQL

- Die veraltete pg_connect()-Syntax mit mehreren Parametern anstelle einer Verbindungszeichenkette wird nicht mehr unterstützt.

- Die veraltete Signatur von pg_lo_import() und pg_lo_export(), die die Verbindung als letzten Parameter übergibt, wird nicht mehr unterstützt. Die Verbindung sollte stattdessen als erster Parameter übergeben werden.

- Die Funktion pg_fetch_all() gibt für Ergebnismengen mit null Zeilen nun ein leeres Array statt `false` zurück.

### Phar

Um mögliche Sicherheitslücken aufgrund von Objektinstanziierung, Autoloading usw. zu schließen, werden Metadaten, die mit phar verknüpft sind, nicht mehr automatisch deserialisiert.

### Reflection

- Die Signaturen der Methoden

  - `ReflectionClass::newInstance($args)`
  - `ReflectionFunction::invoke($args)`
  - `ReflectionMethod::invoke($object, $args)`

  wurden geändert in:

  - `ReflectionClass::newInstance(...$args)`
  - `ReflectionFunction::invoke(...$args)`
  - `ReflectionMethod::invoke($object, ...$args)`

  Code, der sowohl mit PHP 7 als auch mit PHP 8 kompatibel sein muss, kann die folgenden Signaturen verwenden, um mit beiden Versionen kompatibel zu sein:

  - `ReflectionClass::newInstance($arg = null, ...$args)`
  - `ReflectionFunction::invoke($arg = null, ...$args)`
  - `ReflectionMethod::invoke($object, $arg = null, ...$args)`

- Die Methode ReflectionType::__toString() gibt nun eine vollständige Debug-Darstellung des Typs zurück und ist nicht mehr veraltet. Insbesondere enthält das Ergebnis bei nullbaren Typen den Hinweis, der anzeigt, dass `null` zugewiesen werden kann. Das Format des Rückgabewertes ist nicht stabil und kann sich zwischen den PHP-Versionen ändern.

- Die export()-Methoden von Reflection wurden entfernt. Stattdessen können Reflection-Objekte in Zeichenketten umgewandelt werden.

- Die Methoden ReflectionMethod::isConstructor() und ReflectionMethod::isDestructor() geben nun auch für die Schnittstellenmethoden __construct() und __destruct() `true` zurück. Zuvor galt dies nur für Methoden von Klassen und Traits.

- Die Methode ReflectionType::isBuiltin() wurde in die Klasse ReflectionNamedType verschoben. Die Klasse ReflectionUnionType verfügt nicht über diese Methode.

### Sockets

- Bei der Funktion socket_addrinfo_lookup() wurden die veralteten `flags` `AI_IDN_ALLOW_UNASSIGNED` und `AI_IDN_USE_STD3_ASCII_RULES` entfernt.

### Standard-PHP-Bibliothek (SPL)

- Die Methode SplFileObject::fgetss() wurde entfernt.

- Die Methode SplFileObject::seek() sucht nun immer am Anfang der Zeile. In früheren Versionen wurde zum Anfang der nächsten Zeile gesprungen, wenn als Position `>=1` angegeben wurde.

- Die Methode SplHeap::compare() gibt nun die Signatur einer Methode an. Vererbte Klassen, die diese Methode implementieren, müssen nun eine kompatible Methodensignatur verwenden.

- Die Methoden SplDoublyLinkedList::push(), SplDoublyLinkedList::unshift() und SplQueue::enqueue() geben nun void statt `true` zurück.

- Die Funktion spl_autoload_register() löst nun bei ungültigen Parametern immer einen TypeError aus, daher wird der zweite Parameter `do_throw` ignoriert und es wird eine Meldung ausgegeben, wenn er auf `false` gesetzt ist.

- Die Klasse SplFixedArray implementiert nun IteratorAggregate anstelle von Iterator. Die Methoden SplFixedArray::rewind(), SplFixedArray::current(), SplFixedArray::key(), SplFixedArray::next() und SplFixedArray::valid() wurden entfernt. Sie wurden durch SplFixedArray::getIterator() ersetzt. Jeder Code, der explizit über SplFixedArray iteriert, muss nun die Methode SplFixedArray::getIterator() verwenden, um einen Iterator zu erhalten. Dies bedeutet, dass SplFixedArray nun problemlos in verschachtelten Schleifen verwendet werden kann.

### Standard-Bibliothek

- Die Funktion assert() wertet Zeichenketten-Parameter nicht mehr aus. Stattdessen werden sie genauso behandelt wie jeder andere Parameter. Statt `assert('$a == $b')` sollte `assert($a == $b)` verwendet werden. Außerdem wurden die INI-Direktive assert.quiet_eval und die Konstante `ASSERT_QUIET_EVAL` entfernt, weil sie keine Wirkung mehr haben.

- Die Funktion parse_str() kann nicht mehr ohne Angabe eines Ergebnis-Arrays verwendet werden.

- Der Filter string.strip_tags wurde entfernt.

- Der Parameter `needle` der Funktionen strpos(), strrpos(), stripos(), strripos(), strstr(), strchr(), strrchr() und stristr() wird nun immer als Zeichenkette interpretiert. Zuvor wurde needle als ASCII-Codepunkt interpretiert, wenn es keine Zeichenkette war. Das vorherige Verhalten kann durch einen expliziten Aufruf von chr() wiederhergestellt werden.

- Bei den Funktionen strpos(), strrpos(), stripos(), strripos(), strstr(), stristr() und strrchr() darf der Parameter `needle` nun leer sein.

- Bei den Funktionen substr(), substr_count(), substr_compare() und iconv_substr() darf der Parameter `length` nun `null` sein. Wenn `null` angegeben wird, verhalten sich die Funktionen so, als ob der Parameter für die Länge nicht angegeben worden wäre. Daher wird in diesem Fall anstelle einer leeren Zeichenkette der Rest der Zeichenkette zurückgegeben.

- Bei der Funktion array_splice() darf der Parameter `length` nun `null` sein. Wenn `null` angegeben wird, verhält sich die Funktion so, als ob der Parameter nicht angegeben worden wäre. Daher löscht die Funktion in diesem Fall alles von `offset` bis zum Ende des Arrays.

- Bei den Funktionen vsprintf(), vfprintf() und vprintf() muss der Parameter `args` nun ein Array sein. Zuvor wurde jeder Typ akzeptiert.

- Bei der Funktion password_hash() wird die Option `'salt'` nicht mehr unterstützt. Wenn die Option `'salt'` verwendet wird, wird eine Warnung erzeugt und das angegebene Salz wird ignoriert und stattdessen ein generiertes Salz verwendet.

- Die Funktion quotemeta() gibt nun eine leere Zeichenkette zurück, wenn eine leere Zeichenkette übergeben wurde. Zuvor wurde `false` zurückgegeben.

- Die folgenden Funktionen wurden entfernt:

  - hebrevc()
  - convert_cyr_string()
  - money_format()
  - ezmlm_hash()
  - restore_include_path()
  - get_magic_quotes_gpc()
  - get_magic_quotes_runtime()
  - fgetss()

- Die Konstante `FILTER_SANITIZE_MAGIC_QUOTES` wurde entfernt.

- Der Aufruf der Funktion implode() mit Parametern in umgekehrter Reihenfolge `($pieces, $glue)` wird nicht mehr unterstützt.

- Die Funktion parse_url() unterscheidet nun zwischen fehlenden und leeren Anfragen und Fragmenten:

  - `http://example.com/foo → query = null, fragment = null`
  - `http://example.com/foo? → query = "", fragment = null`
  - `http://example.com/foo# → query = null, fragment = ""`
  - `http://example.com/foo?# → query = "", fragment = ""`
  Zuvor waren query und fragment in allen oben genannten Fällen `null`.

- Die Funktionen var_dump() und debug_zval_dump() geben Gleitkommazahlen nun aus, indem sie serialize_precision statt precision verwenden. Bei einer Standardkonfiguration bedeutet dies, dass Gleitkommazahlen von diesen Debugging-Funktionen nun mit voller Genauigkeit ausgegeben werden.

- Wenn das von __sleep() zurückgegebene Array nicht existierende Eigenschaften enthält, werden diese nun stillschweigend ignoriert. Zuvor wurden solche Eigenschaften so serialisiert, als hätten sie den Wert `null`.

- Beim Start ist die Standard-Locale nun immer `"C"`. Standardmäßig werden keine Locales von der Umgebung übernommen. Zuvor war `LC_ALL` auf `"C"` gesetzt, während `LC_CTYPE` von der Umgebung übernommen wurde. Allerdings haben einige Funktionen die übernommene Locale ohne expliziten Aufruf von setlocale() nicht berücksichtigt. Ein expliziter Aufruf von setlocale() ist nun immer erforderlich, wenn eine Komponente der Locale von ihrem Standardwert abweichen soll.

- In der Funktion crypt() wurde der veraltete DES-Fallback entfernt. Wenn ein unbekanntes Salt-Format an crypt() übergeben wird, schlägt die Funktion nun mit `*0` fehl, anstatt auf einen schwachen DES-Hash zurückzugreifen.

- Die Funktion crypt() schlägt bei der Angabe von Runden, die außerhalb des Bereichs für SHA256/SHA512 liegen, nun mit `*0` fehl, anstatt auf die nächstgelegene Grenze zu setzen. Dies entspricht dem Verhalten der glibc.

- Das Ergebnis von Sortierfunktionen kann sich ändern, wenn das Array Elemente enthält, die als gleich bewertet werden.

- Alle für Callbacks geeigneten Funktionen, bei denen nicht explizit angegeben ist, dass sie per Referenz übergebene Parameter akzeptieren, geben nun eine Warnung aus, wenn eine Callback-Funktion mit Referenz-Parametern verwendet wird. Beispiele sind array_filter() und array_reduce(). Dies war bereits bei den meisten Funktionen der Fall, aber nicht bei allen.

- Der HTTP-Stream-Wrapper, der von Funktionen wie file_get_contents() verwendet wird, meldet nun HTTP/1.1 statt HTTP/1.0. Dies ändert nichts am Verhalten des Clients, kann aber dazu führen, dass Server anders reagieren. Um das alte Verhalten beizubehalten, muss die Stream-Kontext-Option `'protocol_version'` gesetzt werden, z. B.

  `<?php
  $ctx = stream_context_create(['http' => ['protocol_version' => '1.0']]);
  echo file_get_contents('http://example.org', false, $ctx);
  ?>`

- Der Aufruf der Funktion crypt() ohne explizites Salz wird nicht mehr unterstützt. Wenn ein starker Hash mit automatisch generiertem Salz erzeugt werden soll, kann stattdessen password_hash() verwendet werden.

- Die Funktionen substr(), mb_substr(), iconv_substr() und grapheme_substr() setzen Offsets, die außerhalb einer Zeichenkette liegen, nun einheitlich auf die Grenzen der Zeichenkette. Zuvor wurde in einigen Fällen `false` anstelle einer leeren Zeichenkette zurückgegeben

- Unter Windows führen die Funktionen für die Ausführung von Programmen, die die Shell verwenden (proc_open(), exec(), popen() usw.) nun konsequent den Befehl %comspec% /s /c "$commandline" aus, was den gleichen Effekt hat wie die Ausführung von $commandline (ohne zusätzliche Anführungszeichen).

### Sysvsem

- Bei der Funktion sem_get() wurde der Parameter `auto_release` geändert und akzeptiert nun boolsche Werte (bool) anstelle von ganzen Zahlen (int).

### Tidy

- Bei der Funktion tidy_repair_string() wurde der intern nicht verwendete Parameter `use_include_path` entfernt.

- tidy::repairString() und tidy::repairFile() sind nun statische Methoden.

### Tokenizer

- Das Token `T_COMMENT` enthält keinen abschließenden Zeilenumbruch mehr. Der Zeilenumbruch gehört nun zum nachfolgenden `T_WHITESPACE`-Token. Es ist wichtig zu beachten, dass auf `T_COMMENT` nicht immer ein Leerzeichen folgt. Es könnte auch ein `T_CLOSE_TAG` oder das Ende der Datei folgen.

- Die Namen innerhalb eines Namensraums werden nun durch die Token `T_NAME_QUALIFIED` (`Foo\Bar`), `T_NAME_FULLY_QUALIFIED` (`\Foo\Bar`) und `T_NAME_RELATIVE` (`namespace\Foo\Bar`) dargestellt. Das Token `T_NS_SEPARATOR` wird nur als einfaches Begrenzungszeichen für den Namensraum verwendet. Es ist syntaktisch nur zulässig, wenn es in Verbindung mit einer gruppierten use-Deklaration verwendet wird.

### XMLReader

XMLReader::open() und XMLReader::XML() sind nun statische Methoden. Sie können immer noch als Instanzmethoden aufgerufen werden, aber erbende Klassen müssen diese Methoden als statisch deklarieren, wenn sie sie überschreiben.

### XML-RPC

Die Erweiterung XML-RPC wurde nach PECL verschoben und ist nicht mehr Teil der PHP-Distribution.

### Zip

Die Konstante `ZipArchive::OPSYS_Z_CPM` wurde entfernt (dieser Name hat einen Tippfehler); stattdessen sollte `ZipArchive::OPSYS_CPM` verwendet werden.

### Zlib

- Die Funktion gzgetss() wurde entfernt.

- zlib.output_compression ist für `Content-Type: image/*` nicht mehr automatisch deaktiviert.

### PHP-Test-Suites für Windows

Das Skript zur Durchführung von Tests wurde von run-test.php in run-tests.php umbenannt, damit es dem Namen in php-src entspricht.

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