PHP 8.4: Объявление параметров с неявным nullable объявлено устаревшим
Серьёзное устаревание в PHP 8.4.
В PHP 8.4 это серьёзное изменение, и старые PHP-приложения, скорее всего, будут получать уведомления об устаревании из-за этого изменения. Рекомендуемая замена проста, безопасна и работает в PHP 7.1 и более поздних версиях.
С появлением таких функций, как скалярные типы (PHP 7.0), nullable типы (7.1), типизированные свойства (7.4), union типы (8.0), intersection типы (8.1), DNF типы (8.2) и типизированные свойства классов (8.3), PHP всегда был на пути к тому, чтобы сделать объявления типов выразительными.
Начиная с PHP 5.1, можно было объявить тип со значением по умолчанию null
, и даже если тип был объявлен, это делало его неявным и эффективно допускающим null
:
function test(string $test = null) {}
test('PHP'); // Допустимо
test(null); // Допустимо
В PHP 7.1 была добавлена поддержка nullable типов, что позволило использовать синтаксис ?TYPE
для объявления типов как nullable:
-function test(string $test = null) {}
+function test(?string $test = null) {}
test('PHP'); // Допустимо
test(null); // Допустимо
С появлением объединения типов в PHP 8.0 стало возможным объявлять типы как одного типа (например, string
), так и других типов (не только null
, но и int
, и т.д.).
Nullable типы также могут быть объявлены как объединение с null
. Например:
function test_with_default(string|null $test = null) {}
Хотя PHP получил несколько улучшений типов, таких как устаревание обязательных параметров после необязательных в PHP 8.0, поддержка неявных nullable типов параметров не была объявлена устаревшей в предыдущих версиях PHP, учитывая большое количество потенциальных проблем обратной совместимости в существующих PHP-приложениях и проектах.
Nullable типы разрешены только в типах функций/методов. Типизированные свойства (добавлены в PHP 7.4) не позволяют неявно объявлять nullable типы. Возвращаемые типы не поддерживают значения по умолчанию. Перечисления (добавлены в PHP 8.1) поддерживают в качестве типов только string
и int
. Кроме того, объявление свойств в конструкторе, не поддерживают синтаксис с неявным nullable.
В PHP 8.4 отказались от неявных nullable типов. PHP-приложениям рекомендуется явно объявлять тип как nullable. Все объявления типов, которые имеют значение по умолчанию null
, но без объявления null
в объявлении типа, выдают уведомление об устаревании:
function test(array $value = null) {}
Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead
Предупреждение об устаревании выдаётся, когда PHP встречает объявление с неявным nullable типом. Но не при вызове таких функций.
Рекомендуемые изменения
Измените неявное объявление типа nullable на объявление типа nullable:
-function test(string $test = null) {}
+function test(?string $test = null) {}
test('PHP'); // Допустимо
test(null); // Допустимо
Кроме того, PHP-приложения, работающие на PHP 8.0 и более поздних версиях, могут использовать объединение типов, чтобы сделать это более наглядным:
-function test(string $test = null) {}
+function test(string|null $test = null) {}
test('PHP'); // Допустимо
test(null); // Допустимо
Оба объявления типов эквивалентны, даже при использовании Reflection API. Второй пример более многословен и работает только на PHP 8.0 и более поздних версиях. Выбирайте вариант, исходя из требований к версии PHP, стилю кода и с учётом чистоты кода.
Для методов классов замена неявных nullable параметров на явные не является нарушением обратной совместимости. Родительские и дочерние классы могут заменять объявления неявных параметров с nullable на явные независимо друг от друга.
Рассмотрим следующий фрагмент:
class ParentClass {
public function tester(string $value = null) {}
}
class SubClass extends ParentClass {
public function tester(?string $value = null) {}
}
Метод ParentClass::tester
вызывает уведомление об устаревании. Метод SubClass::tester
корректно объявляет nullable в явном виде и не вызывает уведомления об устаревании. Можно обновить родительский класс без проблем с совместимостью методов:
class ParentClass {
- public function tester(string $value = null) {}
+ public function tester(?string $value = null) {}
}
class SubClass extends ParentClass {
public function tester(?string $value = null) {}
}
Влияние на обратную совместимость
Данное устаревание способствует более наглядному и выразительному объявлению типов. Рекомендуемая замена совместима с PHP 7.1 и более поздними версиями.
Автоматические исправления
Следующие инструменты могут отмечать и автоматически исправлять неявные объявления nullable типов.
- PHP-CS-Fixer с правилом
nullable_type_declaration_for_default_null_value
- PHP CodeSniffer с
SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue
- Rector
- PHP RFC: Deprecate implicitly nullable parameter types
- [RFC] Deprecate implicitly nullable parameter type
- Реализация