Rumah >pembangunan bahagian belakang >PHP8 >Penjelasan besar tentang ciri baharu PHP8.1: sifat baca sahaja sifat baca sahaja
Artikel ini ialah terjemahan, alamat asal: https://stitcher.io/blog/php-81-readonly-properties
PHP 8.1: Baca sahaja properties
Menulis objek pemindahan data dan objek nilai dalam PHP telah menjadi sangat mudah selama ini. Ambil DTO dalam PHP 5.6 sebagai contoh:
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; } }
dan bandingkan dengan yang setara dalam PHP 8.0:
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; } }
Ia agak berbeza, walaupun saya fikir ia masih Satu yang besar masalah: semua getter ini. Secara peribadi, saya tidak menggunakannya lagi sejak PHP 8.0 dan sifatnya yang dipertingkatkan. Saya hanya lebih suka menggunakan sifat awam daripada menambah pengambil:
class BlogData { public function __construct( public string $title, public Status $status, public ?DateTimeImmutable $publishedAt = null, ) {} }
Tulen berorientasikan objek tidak menyukai pendekatan ini: keadaan dalaman objek tidak boleh didedahkan secara langsung, dan pastinya tidak boleh diubah daripada luar.
Dalam projek kami di Spatie, kami mempunyai peraturan panduan gaya dalaman bahawa DTO dan VO dengan harta awam tidak boleh diubah secara luaran; amalan yang nampaknya berfungsi dengan baik dan kami telah melakukannya sejak sekian lama seketika dan saya tidak mempunyai sebarang masalah.
Walau bagaimanapun, ya; saya bersetuju adalah lebih baik jika bahasa memastikan bahawa harta awam tidak ditindih sama sekali. Nah, PHP 8.1 menyelesaikan semua masalah ini dengan memperkenalkan kata kunci baca sahaja:
class BlogData { public function __construct( public readonly string $title, public readonly Status $status, public readonly ?DateTimeImmutable $publishedAt = null, ) {} }
Kata kunci ini pada asasnya melakukan apa yang dimaksudkan oleh namanya: sebaik sahaja harta ditetapkan, ia tidak boleh Ditindih lagi:
$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
Mengetahui bahawa apabila objek dibina, ia tidak boleh berubah lagi, memberikan tahap kepastian dan ketenangan fikiran semasa menulis kod: satu siri perubahan data yang tidak dijangka tidak akan Berlaku lagi.
Sudah tentu, anda masih mahu dapat menyalin data ke objek baharu dan mungkin menukar beberapa sifat dalam proses. Kami akan membincangkan cara melakukan ini menggunakan sifat baca sahaja kemudian dalam artikel ini. Pertama, mari kita lihat lebih dekat pada mereka.
Adakah anda ingin mengetahui lebih lanjut tentang PHP 8.1? Terdapat laluan ke PHP 8.1. Untuk 10 hari seterusnya, anda akan menerima e-mel harian tentang ciri baharu dan sedia ada PHP 8.1, anda kemudiannya akan dinyahlanggan secara automatik supaya anda tidak akan menerima e-mel spam atau susulan. Langgan sekarang!
#Sifat input sahaja
Sifat baca sahaja hanya boleh digunakan dengan sifat yang ditaip:
class BlogData { public readonly string $title; public readonly $mixed; }
Walau bagaimanapun, anda boleh mencampurkannya Digunakan sebagai pembayang jenis:
class BlogData { public readonly string $title; public readonly mixed $mixed; }
Sebab sekatan ini ialah dengan mengetepikan jenis sifat, PHP akan secara automatik menetapkan nilai harta itu kepada null jika tiada nilai eksplisit disediakan dalam pembina. Tingkah laku ini, digabungkan dengan baca sahaja, boleh menyebabkan kekeliruan yang tidak perlu.
#Atribut biasa dan dinaikkan pangkat
Anda telah melihat contoh kedua-duanya: baca sahaja boleh ditambah pada atribut biasa dan dinaikkan pangkat:
class BlogData { public readonly string $title; public function __construct( public readonly Status $status, ) {} }
#Tiada nilai lalai
Sifat baca sahaja tidak boleh mempunyai nilai lalai:
class BlogData { public readonly string $title = 'Readonly properties'; }
Iaitu, melainkan ia adalah sifat yang dinaikkan pangkat:
class BlogData { public function __construct( public readonly string $title = 'Readonly properties', ) {} }
Sebab ia dibenarkan untuk mempromosikan sifat adalah kerana nilai lalai harta digalakkan tidak digunakan sebagai nilai lalai atribut kelas, tetapi hanya digunakan pada parameter pembina. Di sebalik tabir, kod di atas akan diterjemahkan kepada:
class BlogData { public readonly string $title; public function __construct( string $title = 'Readonly properties', ) { $this->title = $title; } }
Anda boleh melihat bagaimana harta sebenar tidak diberikan nilai lalai. Ngomong-ngomong, sebab nilai lalai untuk sifat baca sahaja tidak dibenarkan ialah ia tidak berbeza daripada pemalar bentuk itu.
#Heritage
Bendera baca sahaja tidak dibenarkan ditukar semasa pewarisan:
class Foo { public readonly int $prop; } class Bar extends Foo { public int $prop; }
Peraturan ini berlaku dua hala: baca sahaja tidak dibenarkan semasa pewarisan Membolehkan menambah atau mengalih keluar bendera.
# Tiada penyahtetapan dibenarkan
Setelah sifat baca sahaja ditetapkan, anda tidak boleh mengubahnya atau menyahsetnya:
$foo = new Foo('value'); unset($foo->prop);
#Reflection
Terdapat kaedah baharu, serta bendera. ReflectionProperty::isReadOnly()ReflectionProperty::IS_READONLY
#Clone
Jadi jika anda tidak boleh menukar sifat baca sahaja dan tidak boleh menyahsetnya, maka bagaimana anda membuat Buat salinan DTO atau VO dan menukar beberapa datanya? Anda tidak boleh mengklonkannya kerana anda tidak akan dapat menimpa nilainya. Sebenarnya terdapat idea untuk mengklon dengan binaan yang akan membenarkan tingkah laku ini pada masa hadapan, tetapi itu tidak akan menyelesaikan masalah kita sekarang.
Nah, jika anda bergantung pada sedikit sihir pantulan, anda boleh menyalin objek dengan sifat baca sahaja yang diubah. Dengan mencipta objek tanpa memanggil pembinanya (ini boleh dilakukan menggunakan refleksi), dan kemudian dengan menyalin setiap harta secara manual - kadangkala menimpa nilainya - anda sebenarnya boleh "mengklon" objek dan menukar sifat baca sahajanya.
Saya membuat pakej kecil untuk melakukan ini dan ia berlaku seperti ini:
class BlogData { use Cloneable; public function __construct( public readonly string $title, ) {} } $dataA = new BlogData('Title'); $dataB = $dataA->with(title: 'Another title');
Saya sebenarnya menulis catatan blog khusus yang menerangkan mekanisme di sebalik semua ini, anda boleh membacanya di sini.
Jadi, itu semua tentang sifat baca sahaja. Saya fikir ia adalah ciri yang hebat jika anda sedang mengusahakan projek yang berkaitan dengan banyak DTO dan VO dan memerlukan anda mengurus aliran data dengan teliti sepanjang kod anda. Objek tidak berubah dengan sifat baca sahaja banyak membantu dalam hal ini.
Atas ialah kandungan terperinci Penjelasan besar tentang ciri baharu PHP8.1: sifat baca sahaja sifat baca sahaja. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!