本文系翻譯,原文地址:https://stitcher.io/blog/php-81-readonly-properties
PHP 8.1:只讀屬性
多年來,用 PHP 編寫數(shù)據(jù)傳輸對(duì)象和值對(duì)象變得非常容易。以 PHP 5.6 中的 DTO 為例:
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; } }
并將其與PHP 8.0的等價(jià)物進(jìn)行比較:
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; } }
這已經(jīng)很不一樣了,盡管我認(rèn)為仍然存在一個(gè)大問題:所有這些吸氣劑。就個(gè)人而言,自 PHP 8.0 及其提升的屬性以來,我不再使用它們。我只是更喜歡使用公共屬性而不是添加 getter:
class BlogData { public function __construct( public string $title, public Status $status, public ?DateTimeImmutable $publishedAt = null, ) {} }
面向?qū)ο蟮募兇庵髁x者不喜歡這種方法:對(duì)象的內(nèi)部狀態(tài)不應(yīng)該直接暴露,并且絕對(duì)不能從外部改變。
在我們?cè)?Spatie 的項(xiàng)目中,我們有一個(gè)內(nèi)部風(fēng)格指南規(guī)則,即不應(yīng)從外部更改具有公共屬性的 DTO 和 VO;一種似乎效果很好的做法,我們已經(jīng)做了很長一段時(shí)間了,沒有遇到任何問題。
然而,是的;我同意如果語言確保公共屬性根本不會(huì)被覆蓋會(huì)更好。好吧,PHP 8.1通過引入readonly關(guān)鍵字解決了所有這些問題:
class BlogData { public function __construct( public readonly string $title, public readonly Status $status, public readonly ?DateTimeImmutable $publishedAt = null, ) {} }
這個(gè)關(guān)鍵字基本上就像它的名字所暗示的那樣:一旦設(shè)置了一個(gè)屬性,它就不能再被覆蓋:
$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
知道當(dāng)一個(gè)對(duì)象被構(gòu)造時(shí),它不會(huì)再改變,在編寫代碼時(shí)提供了一定程度的確定性和平靜:一系列不可預(yù)見的數(shù)據(jù)更改根本不會(huì)再發(fā)生。
當(dāng)然,您仍然希望能夠?qū)?shù)據(jù)復(fù)制到新對(duì)象,并可能在此過程中更改某些屬性。我們將在本文后面討論如何使用只讀屬性來做到這一點(diǎn)。首先,讓我們深入了解一下它們。
您想要了解