## Изменения, которые ломают обратную совместимость

Каждая новая функция, класс, интерфейс, перечисление или константа станет причиной ошибки Error о повторном объявлении, которую выбросит PHP, если встретит в коде объявление с тем же названием, хотя раздел не указывает это в явной форме.

### Ядро PHP

#### Изменение поведения языковой конструкции exit()

Поведение языковой конструкции exit() и её псевдонима die() теперь больше похоже на функции: их разрешили передавать как значения с типом callable, на поведение функций теперь влияет директива `strict_types` управляющей конструкции `declare` и теперь они выполняют стандартные преобразования типов вместо приведения нецелочисленных значений к строке.

Поэтому передача недопустимых типов в функции exit() и die() теперь выбрасывает ошибку TypeError.

#### Рекурсия при сравнении

Появление рекурсии при сравнении теперь выбрасывает ошибку Error вместо ошибки уровня `E_ERROR`.

#### Непрямая модификация доступных только для чтения свойств

Непрямую модификацию доступных только для чтения свойств внутри магического метода `__clone()` запретили, например, присваивание по ссылке `$ref = &$this->readonly` вызовет фатальную ошибку. Инициализацию доступных только для чтения свойств запретили раньше и упустили в реализации «повторной инициализации доступных только для чтения свойств при клонировании».

#### Изменение типа констант

Константы `PHP_DEBUG` и `PHP_ZTS` теперь принадлежат логическому типу bool. Раньше константы принадлежали целочисленному типу int.

#### Длина имени временного файла

Длину имён файлов, которые загрузили, и файлов, которые создали функцией tempnam(), увеличили на 13 байтов. Общая длина по-прежнему зависит от платформы.

#### Удаление уровня ошибки `E_STRICT`

Уровень ошибки `E_STRICT` удалили, поскольку движок PHP больше с ним не работает. Константа `E_STRICT` устарела.

### Типизация констант в классах модулей

Следующие модули теперь объявляют тип для констант своих классах:

- Date
- Intl
- PDO
- Reflection
- SPL
- Sqlite
- XMLReader

### Миграция ресурсов в объекты

Ряд ресурсов (resource) перенесли в объекты (object). Значения, которые возвращали функции-создатели ресурсов и которые проверяли функцией is_resource(), потребуется заменить проверками значений возврата таких функций на принадлежность типу `false`, если только в описании функции не указали иное.

#### Модуль DBA

Функции модуля DBA теперь принимают и возвращают объекты Dba\Connection вместо ресурсов (resource) `dba_connection`.

#### Драйвер ODBC

Функции драйвера ODBC теперь принимают и возвращают объекты Odbc\Result вместо ресурсов (resource) `odbc_result`.

Функции драйвера ODBC теперь принимают и возвращают объекты Odbc\Connection вместо ресурсов (resource) `odbc_connection`.

#### SOAP

Разработчики представили свойство SoapClient::$httpurl объектом Soap\Url, а не ресурсом (resource) `soap_url`. Проверки функцией is_resource() наподобие `is_resource($client->httpurl)`) потребуется заменить проверками на `null` вроде `$client->httpurl !== null`.

Разработчики представили свойство SoapClient::$sdl объектом Soap\Sdl, а не ресурсом (resource) `soap_sdl`. Проверки функции is_resource() наподобие `is_resource($client->sdl)` потребуется заменить проверками на `null` вроде `$client->sdl !== null`.

### Новые предупреждения и исключения

Разработчики добавили новые предупреждения и исключения, которые срабатывают при ошибках программирования, — когда в аргументах передают недопустимые значения.

#### Модуль Curl

Функция curl_multi_select() теперь выбрасывает ошибку ValueError, если аргумент `timeout` меньше `0` или больше значения константы `PHP_INT_MAX`.

#### Модуль Gd

Функции imagejpeg(), imagewebp(), imagepng(), imageavif() теперь выбрасывают ошибку ValueError, если в параметр `quality` передали недопустимое значение.

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

Функция imagescale() теперь выбрасывает ошибку ValueError, если ширина `width` или высота `height` выходит за пределы допустимых значений: недополнено или переполнено.

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

Функция imagefilter() с фильтром `IMG_FILTER_SCATTER` теперь выбрасывают ошибку ValueError, если значение вычитания `sub` или добавления `plus` эффекта выходит за пределы допустимых значений: недополнено или переполнено.

#### Модуль Gettext

Функции bind_textdomain_codeset(), textdomain(), d*gettext теперь выбрасывают ошибку ValueError, если в аргументе `domain` передали пустую строку.

#### Модуль Intl

Функции resourcebundle_get(), ResourceBundle::get() и обращение к смещениям объекта ResourceBundle теперь выбрасывают исключение:

- TypeError при недопустимых типах смещения
- ValueError при передаче пустой строки (string)
- ValueError, если целочисленный индекс не помещается в 32-битное целое число со знаком

Метод IntlDateFormatter::__construct() теперь выбрасывает ошибку ValueError, если в параметр `locale` передали недопустимое значение.

Метод NumberFormatter::__construct() теперь выбрасывает ошибку ValueError, если в параметр `locale` передали недопустимое значение.

#### Модуль MBString

Теперь функции mb_encode_numericentity() и mb_decode_numericentity() проверяют, что значение параметра `map` состоит только из целых числел (int), иначе выбрасывают ошибку ValueError.

Теперь функция mb_http_input() выбрасывает ошибку ValueError при каждом вызове, если в параметр `type` передали недопустимое значение.

Теперь функция mb_http_output() проверяет, что значение параметра `encoding` не содержит нулевых байтов, иначе выбрасывает ошибку ValueError.

#### ODBC

Функция odbc_fetch_row() раньше возвращала значение `false`, если значение аргумента `row` оказывалось меньше или равно `0`. Теперь функция выдаёт предупреждение.

#### Модуль PCNTL

Функции pcntl_sigprocmask(), pcntl_sigwaitinfo() и pcntl_sigtimedwait() теперь выбрасывают исключение:

- ValueError, если массив `signals` оказался пустым (за исключением функции pcntl_sigprocmask(), если для параметра `mode` установили режим `SIG_SETMASK`)
- TypeError, если массив `signals` содержит значение, которое не принадлежит типу int
- ValueError, если массив `signals` содержит значение, которое оказалось недопустимым номером сигнала

Функция pcntl_sigprocmask() теперь выбрасывает ошибку ValueError, если в аргументе `mode` передали значение, которое не входит в список: `SIG_BLOCK`, `SIG_UNBLOCK` или `SIG_SETMASK`.

Функция pcntl_sigtimedwait() теперь выбрасывает ошибку:

- ValueError, если значение аргумента `seconds` меньше `0`
- ValueError, если значение аргумента `nanoseconds` меньше `0` или больше `1e9`
- ValueError, если значения аргументов `seconds` и `nanoseconds` равны `0`

#### Модуль Session

Установка неположительного значения в директиве session.gc_divisor или отрицательного значения в директиве session.gc_probability теперь выдаёт предупреждение.

#### Модуль SimpleXML

Вызов функции simplexml_import_dom() не с XML-объектом теперь вместо исключения ValueError выбрасывает ошибку TypeError.

#### Новые исключения и ошибки в стандартных функциях

Функция round() теперь проверяет значение параметра `mode` и выбрасывает ошибку ValueError для недопустимых режимов. Раньше функция интерпретировала недопустимые режимы округления как режим `PHP_ROUND_HALF_UP`.

Функция str_getcsv() теперь выбрасывает ошибку ValueError, когда длина разделителя `separator` и ограничителя полей `enclosure` не равна одному байту, или если в аргументе символа экранирования `escape` не передали однобайтовый символ или пустую строку. Это выравнивает поведение функции, чтобы оно было идентично поведению функций fputcsv() и fgetcsv().

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

Опция `"allowed_classes"` функции unserialize() теперь выбрасывает исключения TypeError и ValueError, если в аргументе передали не массив (array) имён классов.

#### Класс XMLReader

Передача недопустимой кодировки символов в метод XMLReader::open() или XMLReader::XML() теперь выбрасывает ошибку ValueError.

Передача строки (string), которая содержит нулевые байты, раньше выдавала предупреждение, а теперь выбрасывает ошибку ValueError.

#### Класс XMLWriter

Передача строки (string), которая содержит нулевые байты, раньше выдавала предупреждение, а теперь выбрасывает ошибку ValueError.

#### Модуль XSL

Метод XSLTProcessor::setParameter() теперь выбрасывает ошибку ValueError, если значения аргументов содержат нулевые байты. Метод никогда не работал корректно, поэтому теперь такое поведение приводит к исключению.

Вызов метода XSLTProcessor::importStyleSheet() не с XML-объектом теперь вместо исключения ValueError выбрасывает ошибку TypeError.

Невозможность вызвать callback-функцию во время оценки теперь выбрасывает исключение, а не выдаёт предупреждение.

### Date

Синтаксис относительных форматов снова принимает в символах `number` множественные знаки числа: `+-2`.

### Модуль DOM

Отдельные методы модуля DOM раньше возвращали значение `false` или выбрасывали исключение DOMException с кодом `DOM_PHP_ERR`, если не получалось выделить новый узел. Теперь методы постоянно выбрасывают исключение DOMException с кодом `DOM_INVALID_STATE_ERR`. Такая ситуация в крайней степени маловероятна и вряд ли затронет прежний код. В итоге вместо типа `DOMDocument|false` методу DOMImplementation::createDocument() назначили предварительный тип возврата DOMDocument.

Раньше объекты DOMXPath разрешали клонировать, но в итоге получался непригодный объект. Клонирование объекта DOMXPath больше невозможно и теперь выбрасывает ошибку Error.

Метод DOMImplementation::getFeature() удалили.

### Класс GMP

Класс GMP сделали окончательным и поэтому расширение класса теперь невозможно.

### Модуль MBString

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

Для строк в кодировке SJIS-Mac, или её псевдониме MacJapanese, индексы символов, которые передают в функцию mb_substr(), теперь ссылаются на индексы кодовых точек кодировки Unicode, которые получаются при преобразовании строки в Unicode. Это важно, поскольку около 40 символов кодировки SJIS-Mac преобразовываются в последовательность из нескольких кодовых точек Unicode.

### Модуль MySQLi

Невостребованную и незадокументированную константу `MYSQLI_SET_CHARSET_DIR` удалили.

Константу `MYSQLI_STMT_ATTR_PREFETCH_ROWS` удалили. Функция недоступна в драйвере mysqlnd.

Константы `MYSQLI_CURSOR_TYPE_FOR_UPDATE` и `MYSQLI_CURSOR_TYPE_SCROLLABLE` удалили. Этот функционал никогда не реализовывали ни в драйвере mysqlnd, ни в библиотеке libmysql.

Невостребованную константу `MYSQLI_TYPE_INTERVAL` — заглушку и псевдоним константы `MYSQLI_TYPE_ENUM` — удалили.

### Драйвер MySQLnd

Код ошибки, которым сообщают о превышении времени ожидания сервера MySQL, изменили с `2006` на `4031` для серверов MySQL версии 8.0.24 и выше.

### Модуль Opcache

Максимальное значение директивы opcache.interned_strings_buffer в 64-разрядных архитектурах теперь составляет `32767` МБ. Раньше значение составляло `4095` мегабайтов.

#### Компилятор JIT

Значения конфигурации по умолчанию для JIT-компилятора изменились с `opcache.jit=tracing` на `opcache.jit=disable` и с `opcache.jit_buffer_size=0` на `opcache.jit_buffer_size=64M`.

Это не влияет на поведение наблюдаемых объектов по умолчанию, поскольку JIT по-прежнему отключён по умолчанию. Однако теперь JIT-компиляция отключается параметром opcache.jit, а не opcache.jit_buffer_size. Изменение затронет пользователей, которые раньше включали JIT только директивой opcache.jit_buffer_size, но не указывали режим JIT-компиляции в директиве opcache.jit. Поэтому чтобы включить JIT-компиляцию потребуется указать значение конфигурации для директивы opcache.jit.

Теперь при включённой JIT-компиляции PHP будет завершаться с критической ошибкой при запуске, если инициализация JIT-компилятора по какой-либо причине не удалась.

### Модуль PCNTL

Функции pcntl_sigprocmask(), pcntl_sigwaitinfo() и pcntl_sigtimedwait() теперь при каждом вызове возвращают значение `false`, если возникла ошибка. Раньше в отдельных случаях функции иногда возвращали значение `-1`.

### Модуль PCRE

Библиотеку pcre2lib, которая идёт в комплекте поставки, обновили до версии 10.44. Поэтому запись `{,3}` теперь распознается как квантификатор, а не как текст. Кроме того, изменилось значение отдельных классов символов в режиме UCP. Полный перечень изменений приводит » список изменений PCRE2.

### Драйвер PDO_DBLIB

Атрибуты `Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER` и `Pdo\Dblib::ATTR_DATETIME_CONVERT` теперь действуют как логические атрибуты вместо целочисленных. Поэтому установка атрибута методом PDO::setAttribute() и получение атрибута методом PDO::getAttribute() ожидает и возвращает логическое значение (bool).

### Драйвер PDO_FIREBIRD

Атрибут `PDO::ATTR_AUTOCOMMIT` теперь действует как логический атрибут вместо целочисленного. Поэтому установка атрибута методом PDO::setAttribute() и получение атрибута методом PDO::getAttribute() ожидает и возвращает логическое значение (bool).

Модуль теперь раскрывает отдельные API-интерфейсы СУБД Firebird на языке C++, поэтому для сборки модуля теперь требуется компилятор C++. Более того, теперь модуль потребуется скомпилировать с библиотекой fbclient 3.0 или выше.

### Драйвер PDO_MYSQL

Атрибуты `PDO::ATTR_AUTOCOMMIT`, `PDO::ATTR_EMULATE_PREPARES` и `PDO::MYSQL_ATTR_DIRECT_QUERY` теперь действуют как логические атрибуты вместо целочисленных. Поэтому установка атрибута методом PDO::setAttribute() и получение атрибута методом PDO::getAttribute() ожидает и возвращает логическое значение (bool).

### Драйвер PDO_PGSQL

Приоритет учётных данных, которые указали в DSN-строке подключения конструктора класса PDO, выше, чем приоритет учётных данных, которые указали во втором и третьем аргументах конструктора, поскольку учётные данные в DSN-строке подключения ближе к положениям документации.

### Модуль SimpleXML

Объект класса SimpleXMLElement — представляет не только элемент в XML-документе, но и интерфейс RecursiveIterator. До PHP 8.4.0 отдельные методы класса наподобие SimpleXMLElement::asXML() или SimpleXMLElement::getName() и приведение таких экземпляров к строке (string) неявно сбрасывали итератор.

Такое поведение иногда делало циклы бесконечными, поскольку итератор отматывался к первому элементу. Приведём пример. Следующий код:

    <?php

    $xmlString = "<root><a><b>1</b><b>2</b><b>3</b></a></root>";
    $xml = simplexml_load_string($xmlString);

    $nodes = $xml->a->b;
    foreach ($nodes as $nodeData) {
        echo "Данные узла: " . $nodeData . "\n";

        $xml = $nodes->asXml();
    }

…вызовет бесконечный цикл.

    Данные узла: 1
    Данные узла: 2
    Данные узла: 2
    Данные узла: 2
    Данные узла: 2
    Данные узла: 2
    Данные узла: 2
    // ...

Это поведение исправили, и элемент SimpleXMLElement больше не будет неявно сбрасывать данные итератора, если только итератор не отмотают вручную. Поэтому приведённый пример теперь будет выводить следующие данные:

    Данные узла: 1
    Данные узла: 2
    Данные узла: 3

### Модуль SOAP

Разработчики представили свойство SoapClient::$typemap массивом (array), а не ресурсом (resource). Проверки функцией is_resource() наподобие `is_resource($client->typemap)` потребуется заменить проверкой на `null` вроде `$client->typemap !== null`.

Модуль SOAP получил необязательную зависимость от модуля session. Теперь при запуске будут возникать ошибки, если включить модуль SOAP, а PHP собрать без модуля session, но с флагом конфигурации --enable-rtld-now. Проблему решают двумя способами: либо не включают режим rtld-now, либо загружают модуль сессий.

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

Теперь при вызове функции strcspn() с передачей в аргументе `characters` пустой строки вместо неправильной остановки на первом нулевом байте возвращается длина строки.

Функция http_build_query() теперь корректно обрабатывает типизированные перечисления.

Функции stream_bucket_make_writeable() и stream_bucket_new() теперь возвращают экземпляр класса StreamBucket, а не класса stdClass.

### Модуль Tidy

Теперь вместо предупреждений и повреждения объекта сбои в конструкторе выбрасывают исключение.

### Парсер XML

Функции семейства xml_set_*_handler теперь объявляют и проверяют сигнатуру callable|string|null параметров `handler`. Больше того, значения с типом string, которые соответствуют названиям методов, которые задали функцией xml_set_object(), теперь проверяются на существование метода в классе объекта, который передали прежде. Поэтому теперь перед установкой названий методов, которые устанавливаются как callable-обработчики, требуется каждый раз вызывать функцию xml_set_object(). Передача пустой строки для отключения обработчика по-прежнему разрешается, но устарела.

Однако, поскольку функция xml_set_object() и передача строк, которые не принадлежат типу callable, устарели, рекомендуют заменить такие экземпляры callable-обработчиками, которые ссылаются непосредственно на метод.

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