PHP 8.4: Объявление параметров с неявным nullable объявлено устаревшим

Источник: «PHP 8.4: Implicitly nullable parameter declarations deprecated»
PHP поддерживает объявление типов для параметров функций, возвращаемых значений, свойств классов, констант классов и Enum. Будучи динамически типизированным языком и языком с десятилетиями истории, за прошедшие годы PHP получил ряд улучшений и возможностей.

Серьёзное устаревание в 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 и GD

Следующая Статья

Оптимизация webpack в CI