## Другие изменения

### Изменения в ядре

#### Класс FFI

Метод FFI::load() теперь разрешён в режиме предварительной загрузки, когда опция opcache.preload_user — это текущий пользователь системы. Ранее вызов метода FFI::load() не был возможен во время предзагрузки, если настройка директивы opcache.preload_user была установлена.

#### Менеджер процессов FPM

Проверка FPM CLI теперь завершается неудачей, если путь к сокету длиннее, чем поддерживает операционная система.

#### Модуль Opcache

В CLI и phpdbg SAPIs предварительная загрузка больше не требует настройки директивы opcache.preload_user при запуске от имени пользователя root. В других SAPIs эта директива нужна при запуске от имени пользователя root, потому что предзагрузка выполнялась до того, как SAPI переключится на непривилегированного пользователя.

#### Потоки

Блокировка функцией fread() при подключении к сокету возвращается немедленно, если есть любые буферизованные данные, вместо ожидания дополнительных данных.

Поток памяти больше не завершается сбоем, если смещение поиска превысило конечное значение. Вместо этого память будет увеличена при следующей записи, а данные между старым концом и смещением заполнятся нулевыми байтами, аналогично работе файлов.

Операции доступа функции stat() наподобие функции file_exists() и похожие теперь пользуются реальным путём вместо фактического пути потока. Это соответствует открытию потока.

### Изменения в модулях SAPI

#### Командная строка (CLI)

Потоки `STDOUT`, `STDERR` и `STDIN` больше не закрываются при уничтожении ресурсов, что обычно случается при завершении работы CLI. Однако всё ещё можно явно закрыть эти потоки через функцию fclose() и похожие.

### Изменённые функции

#### Ядро

В функцию gc_status() добавлено 8 следующих полей:

- `running` => bool
- `protected` => bool
- `full` => bool
- `buffer_size` => int
- `application_time` => float: Полное время работы приложения в секундах (включая время, затраченное полем collector_time)
- `collector_time` => float: Время в секундах, затраченное циклами сборки (включая время, затраченное полями destructor_time и free_time)
- `destructor_time` => float: Время в секундах, затраченное деструкторами в течение цикла сборки
- `free_time` => float: Время в секундах, затраченное на освобождение значений во время цикла сборки

Функция class_alias() теперь поддерживает создание псевдонимов внутреннего класса.

Настройка open_basedir с вызовом во время выполнения функции `ini_set('open_basedir', ...);` больше не принимает пути, содержащие родительскую директорию (`..`). Ранее запрещались только пути, начинающиеся с `..`. Это можно легко обойти, добавив `./` к пути.

Обработчики пользовательских исключений теперь перехватывают их во время завершения работы.

Результирующий HTML в функциях highlight_string() и highlight_file() был изменён. Пробел между внешними HTML-тегами удалены. Новые строки и пробелы больше не преобразовываются в HTML-сущности. Полный HTML теперь обёрнут тегом `<pre>`. Внешний тег `<span>` был слит с тегом `<code>`.

#### Модуль Calendar

Функция easter_date() теперь поддерживает годы с 1970 по 2 000 000 000 на 64-битных системах, ранее она поддерживала только годы в диапазоне 1970—2037.

#### Модуль Curl

Функция curl_getinfo() теперь поддерживает две новых константы: `CURLINFO_CAPATH` и `CURLINFO_CAINFO`. Если параметр option принимает значение `null`, будут представлены два следующих дополнительных ключа: `capath` и `cainfo`.

#### Модуль DOM

У метода DOMCharacterData::appendData() предопределённый тип возвращаемого значения изменился на true.

У методов DOMDocument::loadHTML(), DOMDocument::loadHTMLFile() и DOMDocument::loadXML() предварительный тип возвращаемого значения был изменён на bool. Раньше это было задокументировано как `DOMDocument|bool`, но начиная с PHP 8.0.0 объект класса DOMDocument не может быть возвращён, поскольку он больше не может быть вызван статически.

#### Модуль Gd

Сигнатура функции imagerotate() изменилась. Параметр `$ignore_transparent` был удалён, поскольку он игнорировался с версии PHP 5.5.0.

#### Модуль интернационализации Intl

Функция datefmt_set_timezone() (и её псевдоним — метод IntlDateformatter::setTimeZone()) теперь возвращают значение `true` при успешном выполнении, ранее они возвращали значение `null`.

Метод IntlBreakiterator::setText() теперь возвращает значение `false` при сбое, ранее он возвращал значение `null`. Теперь он возвращает значение `true` при успешном выполнении, ранее возвращалось значение `null`.

Метод IntlChar::enumCharNames() теперь возвращает логическое значение. Ранее он возвращал значение `null` при успешном выполнении и значение `false` при неудачном завершении.

Метод IntlDateFormatter::__construct() выбрасывает исключение `U_ILLEGAL_ARGUMENT_ERROR` при установке недопустимого языкового стандарта (локали).

#### Модуль MBString

Функции mb_strtolower() и mb_convert_case() соблюдают правила условного регистра для греческой буквы сигма (Σ → σ). В функции mb_convert_case() условный регистр применяется только для режимов `MB_CASE_LOWER` и `MB_CASE_TITLE`, но не для `MB_CASE_LOWER_SIMPLE` и `MB_CASE_TITLE_SIMPLE`.

Функция mb_decode_mimeheader() интерпретирует подчёркивание в QPrint-кодированной MIME-кодировке слов так, как требует стандарт RFC 2047; они преобразовываются в пробелы. Подчёркивания должны быть закодированы в `«=5F»` с таких MIME-кодированных словах.

В редких случаях функция mb_encode_mimeheader() будет применять кодировку передачи к своей входной строке, чтобы она могла передать её как необработанный ASCII в PHP 8.2.

Функция mb_encode_mimeheader() больше не сбрасывает NUL-байты при QPrint-кодировании входной строки. Ранее это иногда приводило к повреждению функцией mb_encode_mimeheader строк в ряде текстовых кодировок, особенно UTF-16 и UTF-32.

«Нестрогий» режим функции mb_detect_encoding() теперь ведёт себя как описано в документации. Ранее она возвращала значение `false`, если тот же байт (например, первый) входной строки был недопустимым во всех проверяемых кодировках. В общем смысле, она исключала предложенные кодировки из рассмотрения, если был обнаружен недопустимый байт, и если тот же входной байт исключил все оставшиеся кодировки, всё ещё находящиеся на рассмотрении, она могла вернуть значение `false`. С другой стороны, если все предложенные кроме одной кодировки были исключены из рассмотрения, она возвращала последнюю оставшуюся, без учёта того, сколько ошибок кодирования может встретиться позже в строке. Это отличается от поведения, описанного в документации, которое говорило: «Если параметр strict установлен в значение false, будет возвращена первая совпадающая кодировка».

#### Модуль mysqli

Функция mysqli_fetch_object() теперь выбрасывает исключение ValueError вместо исключения Exception, когда в параметр `$constructor_args` передан непустой аргумент, а в классе не определён конструктор.

Функция mysqli_poll() теперь выбрасывает исключение ValueError, когда не переданы ни аргументы параметра `$read`, ни аргументы параметра `$error`.

В функции mysqli_field_seek() и методе mysqli_result::field_seek() возвращаемый тип теперь определён как true вместо bool.

#### Программный интерфейс ODBC

Теперь для параметра `$enable` функция odbc_autocommit() принимает значение `null`. При передаче значения `null` функция будет вести себя так же, как и при передаче значения только для одного параметра, то есть — укажет, включена ли автофиксация или нет.

#### Модуль PGSQL

Функция pg_fetch_object() теперь выбрасывает исключение ValueError вместо исключения Exception, когда в параметр `$constructor_args` передаётся непустой аргумент, а в классе не определён конструктор.

Функция pg_insert() теперь выбрасывает исключение ValueError вместо ошибки уровня `E_WARNING`, когда указанная таблица недопустима.

Функции pg_insert() и pg_convert() выбрасывают исключения ValueError или TypeError вместо ошибки уровня `E_WARNING`, когда значение/тип поля правильно не совпадает с типом PostgreSQL.

Параметр `$row` функций pg_fetch_result(), pg_field_prtlen() и pg_field_is_null() теперь может принимать значение `null`.

#### Модуль Random

Изменены функции mt_srand() и srand(), чтобы не проверять количество аргументов для определения, надо ли использовать случайное начальное число. Передача значения `null` сгенерирует случайное начальное число, при передаче значения `0` оно и будет выбрано случайным числом. Работа функции теперь согласована с методом Random\Engine\Mt19937::__construct().

#### Класс Reflection

Возвращаемый тип метода ReflectionClass::getStaticProperties() больше не может принимать значение `null`.

#### Стандартные функции

Вызов ошибки уровня `E_NOTICE` в функции unserialize() был повышен до `E_WARNING`.

Функция unserialize() теперь выдаёт ошибку уровня `E_WARNING`, если входные данные содержат неиспользованные байты.

Функция array_pad() теперь ограничена только максимальным количеством элементов, которые может содержать массив. Раньше за один раз она могла добавить только 1 048 576 элементов.

Функция strtok() выдаёт ошибку уровня `E_WARNING`, если токен не предоставлен при запуске токенизации.

Функция password_hash() теперь будет связывать в цепочку базовое исключение Random\RandomException как исключение Exception свойства `$previous` исключения ValueError, когда генерация соли завершится неудачей.

Передаваемый в параметр `$command` функции proc_open() массив теперь должен содержать хотя бы один непустой элемент. Или будет выброшено исключение ValueError.

Функция proc_open() возвращает значение `false`, если переданный в параметр `$command` массив — это не допустимая команда, а объект ресурса, который выдаёт предупреждение позже. Это уже было в Windows, но теперь это также имеет место, если выбрана реализация posix_spawn (бо́льшая часть платформ Linux, BSD и MacOS). Всё ещё существуют старые платформы, на которых это поведение не изменено, поскольку posix_spawn на них не поддерживается.

Функции array_sum() и array_product() теперь предупреждают, когда значения в массиве не могут быть преобразованы в целое число/число с плавающей точкой. Раньше массивы и объекты игнорировались, тогда как все остальные значения приводились к целым числам (int). Больше того, объекты, определяющие числовое приведение (например, GMP), теперь приводятся, а не игнорируются.

Параметр `$decimals` функции number_format() теперь правильно обрабатывает отрицательные целые числа. Округление с отрицательным значением для параметра `$decimals` означает, что значение параметра `$num` округляется до установленных в параметре `$decimals` значащих цифр перед десятичной точкой. Ранее отрицательные значения параметра `$decimals` молча игнорировались и число округлялось до нуля десятичных знаков.

Новый параметр `$before_needle` был добавлен в функцию strrchr(). Он ведет себя так же, как его аналог в функциях strstr() или stristr().

Функции str_getcsv() и fgetcsv() теперь возвращают пустую строку вместо строки с одним нулевым байтом для последнего поля, которое содержит только незавершенное вложение.

### Другие изменения в модулях

#### Ядро

Указание операторов инкремента/декремента (`++`/`--`) на логических значениях (bool) теперь выдаёт предупреждения. Это потому, что пока это не даёт эффекта, но в будущем будет вести себя как `$bool += 1`.

Указание оператора декремента (`--`) на значения null теперь выдаёт предупреждения. Это потому, что пока это не даёт эффекта, но в будущем будет вести себя как `$null -= 1`.

Внутренние объекты, которые реализуют приведение _IS_NUMBER, но не обработчик do_operator, который переопределяет сложение и вычитание, теперь можно увеличивать или уменьшать на единицу, как если бы выполнялись выражения `$o += 1` или `$o -= 1`.

#### Модуль DOM

Механизм жизненного цикла модуля DOM был переработан так, чтобы неявно удалённые узлы по-прежнему можно было получить. Ранее это приводило к исключению.

#### Класс SQLite3

Класс SQLite3 теперь вместо исключения Exception выбрасывает исключение SQLite3Exception (расширяя класс исключения Exception).

Код ошибки класса SQLite теперь передаётся в коде ошибки исключения, а не включается в сообщение об ошибке.

### Изменения обработки INI-файла

- INI-директивы `assert.*` устарели для настроек конфигурации. Сюда входят следующие настройки INI:

  - assert.active
  - assert.bail
  - assert.callback
  - assert.exception
  - assert.warning
  Если значение настройки равно значению по умолчанию, уведомления об устаревании не будет выдано. Вместо них нужно пользоваться INI-директивой zend.assertions.

- zend.max_allowed_stack_size — это новая INI-директива, которая устанавливает максимальный размер стека. Возможные значения — это `0` (определяет максимальный размер стека процессов или потоков), `-1` (без ограничений) или положительное целое число байтов. Значение по умолчанию — `0`. Когда она не может определить максимальный размер стека процессов или потоков, будет выбрано известное системное значение по умолчанию. Установка чрезмерно большого значения даст тот же эффект, что и отключение ограничения размера стека. Максимальный размер стека для файберов устанавливают директивой fiber.stack_size. Выбрасывается ошибка Error когда стек вызовов процессов превышает установленный директивой zend.max_allowed_stack_size-zend.reserved_stack_size размер байтов, для предотвращения ошибок сегментации, вызванных переполнением стека, для упрощения процесса отладки. Размер стека увеличивается во время неконтролируемых рекурсий с участием внутренних функций, или магических методов __toString(), __clone(), __sleep(), __destruct(). Это не связано с переполнением буфера стека и не связано с безопасностью.

- zend.reserved_stack_size — это новая INI-директива, которая устанавливает зарезервированный размер стека в байтах. Это значение вычитается из максимального размера стека в качестве буфера при проверке размера стека.

### Производительность

#### Модуль DOM

При циклическом просмотре списка узлов в объекте DOMNodeList теперь работает кеширование. Поэтому запрос элементов по умолчанию больше не занимает квадратичное время.

Получение текстового содержимого из узлов теперь избегает выделения памяти, что даёт прирост производительности.

Метод DOMChildNode::remove() теперь работает с производительностью O(1).

#### Standard

Проверка ошибок флагов в функции file() теперь примерно на 7 % быстрее.

#### Библиотека SPL

Класс RecursiveDirectoryIterator теперь выполняет меньше операций ввода-вывода при циклическом переборе каталога.

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