В PHP 7.4, вышедшем без малого год назад, появились typed properties. Вообще мы и раньше могли контролировать типы свойств классов через геттеры и сеттеры, но контроль был не полный. Теперь если свойство объявлено как int, то теперь в нем строка уже никак не окажется.
Но вместе с новыми возможностями приходят новые проблемы. Появилось новая ошибка Typed property must not be accessed before initialization , которая возникает при попытке обратиться к типизированному свойству, в котором не задано значение. Ранее такое обращение вернуло бы null. Сейчас поведение изменилось. Даже nullable свойства кинут ошибку, если их попытаются считать до того как заполнят. Смотрим новое поведение:
<?php
declare(strict_types=1);
class MyClass
{
protected int $first;
protected ?int $second;
protected ?int $third = null;
function testProperties()
{
// Causes "Typed property MyClass::$first must not be accessed before initialization"
// $this->first;
// Causes "Typed property MyClass::$second must not be accessed before initialization"
// $this->second;
// Ok
$this->third;
}
}
Теперь типизируя свойства надо быть уверенными в том, что они задаются до использования. Больше всего проблем это сулит при работе с сериализуемыми DTO. Например попробуем сериализовать объект с типизированными свойствами:
<?php
declare(strict_types=1);
use JMS\Serializer\Annotation as Serializer;
class Test
{
/**
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
private string $code;
/**
* @Serializer\SerializedName("message")
* @Serializer\Type("string")
*/
private string $message;
// getters + setters
}
// Добавляем в MyClass
function testSerialize()
{
/** @var ArrayTransformerInterface $arrayTransformer */
$test = new Test();
// Causes "Typed property Test::$code must not be accessed before initialization"
$arrayTransformer->toArray($test);
}
Таким образом все типизированные свойства в Dto объектах должны быть заданы, потому что в противном случае сериалайзер, сканируя объект, натолкнется на пустое свойство и произойдет описанное выше исключение. При переходе на PHP 7.4 мы поймали большое количество таких ошибок. Так что если тоже собираетесь повышать версию php и внедрять типизированные свойства там, где их не было, убедитесь, что приложение хорошо протестировано. Ну и не забывайте инициализировать свои свойства 🙂
Дополнительные материалы – отличный разбор типизированных свойств: https://stitcher.io/blog/typed-properties-in-php-74