This article is translated, original address: https://stitcher.io/blog/php-81-readonly-properties
##PHP 8.1: Read-only properties
Over the years, writing data transfer objects and value objects has become very easy in PHP. Take the DTO in PHP 5.6 as an example:class BlogData { /** @var string */ private $title; /** @var Status */ private $status; /** @var \DateTimeImmutable|null */ private $publishedAt; /** * @param string $title * @param Status $status * @param \DateTimeImmutable|null $publishedAt */ public function __construct( $title, $status, $publishedAt = null ) { $this->title = $title; $this->status = $status; $this->publishedAt = $publishedAt; } /** * @return string */ public function getTitle() { return $this->title; } /** * @return Status */ public function getStatus() { return $this->status; } /** * @return \DateTimeImmutable|null */ public function getPublishedAt() { return $this->publishedAt; } }
class BlogData { public function __construct( private string $title, private Status $status, private ?DateTimeImmutable $publishedAt = null, ) {} public function getTitle(): string { return $this->title; } public function getStatus(): Status { return $this->status; } public function getPublishedAt(): ?DateTimeImmutable { return $this->publishedAt; } }
class BlogData { public function __construct( public string $title, public Status $status, public ?DateTimeImmutable $publishedAt = null, ) {} }
class BlogData { public function __construct( public readonly string $title, public readonly Status $status, public readonly ?DateTimeImmutable $publishedAt = null, ) {} }
$blog = new BlogData( title: 'PHP 8.1: readonly properties', status: Status::PUBLISHED, publishedAt: now() ); $blog->title = 'Another title'; Error: Cannot modify readonly property BlogData::$title
#Input properties only
Read-only properties can only be used in conjunction with typed properties:class BlogData { public readonly string $title; public readonly $mixed; }
class BlogData { public readonly string $title; public readonly mixed $mixed; }
#Normal and promoted properties
You have seen examples of both: readonly can be added on both normal and promoted properties:class BlogData { public readonly string $title; public function __construct( public readonly Status $status, ) {} }
#No default value
Read-only properties cannot have default values:class BlogData { public readonly string $title = 'Readonly properties'; }
class BlogData { public function __construct( public readonly string $title = 'Readonly properties', ) {} }
class BlogData { public readonly string $title; public function __construct( string $title = 'Readonly properties', ) { $this->title = $title; } }
#Legacy
Readonly flags are not allowed to be changed during inheritance:class Foo { public readonly int $prop; } class Bar extends Foo { public int $prop; }
#Unsetting not allowed
Once a read-only property is set, you cannot change it, or even unset it:$foo = new Foo('value'); unset($foo->prop);
#Reflection
There is a new method, as well as a flag. ReflectionProperty::isReadOnly()ReflectionProperty::IS_READONLY#Clone
So if you can't change read-only properties, and can't unset them, then how do you create Make a copy of a DTO or VO and change some of its data? You can't clone them because you won't be able to overwrite their values. There was actually an idea to clone with a construct that would allow this behavior in the future, but that wouldn't solve our problem now. Well, if you rely on a little reflection magic, you can copy an object with a changed read-only property. By creating an object without calling its constructor (this can be done using reflection), and then by manually copying each property - sometimes overwriting its value - you can actually "clone" an object and change its read-only properties. I made a little package to do this and it goes like this:class BlogData { use Cloneable; public function __construct( public readonly string $title, ) {} } $dataA = new BlogData('Title'); $dataB = $dataA->with(title: 'Another title');
The above is the detailed content of A big explanation of the new features of PHP8.1: readonly properties read-only properties. For more information, please follow other related articles on the PHP Chinese website!