【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【WordPress 専用】クラウドサーバー『ウェブスピード』

【WordPress 専用】クラウドサーバー『ウェブスピード』

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【予約システム開発】EDISONE カスタマイズ開発サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【200ヶ国以上に対応】グローバル eSIM「ビヨンドSIM」

【200ヶ国以上に対応】グローバル eSIM「ビヨンドSIM」

【中国法人に対応】中国クラウド / サーバー構築・運用保守

【中国法人に対応】中国クラウド / サーバー構築・運用保守

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

PHP 8.2 で追加された ReadOnly Class を触ってみた!

こんにちは!システム開発部の小出です!

12月8日に PHP 8.2 がリリースされました!

本日は、PHP 8.2 で追加された読み取り専用クラスに関して書いていきます。

それでは早速みていきましょう。

読み取り専用クラス(readonly class)

PHP 8.1 ではプロパティに対して readonly 修飾子を設定することが可能になりましたが、

PHP 8.2 ではクラスに対して readonly 修飾子を設定することが可能になりました。


<?php

readonly class SekarakuBlog
{ 
  public string $title; 
}

上記によって、クラス内の全てのプロパティが readonly になります。


<?php

readonly class SekarakuBlog
{
  public string $title;

  public function __construct()
  {
    $this->title = 'test Title';
  }
}

$test = new SekarakuBlog();
$test->title = 'Change Title'; // Fatal error: Uncaught Error: Cannot modify readonly property SekarakuBlog::$title
$test->content = 'content'; // Fatal error: Uncaught Error: Cannot create dynamic property SekarakuBlog::$content

readonly クラス内のプロパティを書き換えようとすると下記のエラーがでることが確認できます。


Fatal error: Uncaught Error: Cannot modify readonly property SekarakuBlog::$title

さらには、動的プロパティの作成も禁止されます。

動的プロパティを作成しようとすると下記のようなエラーが発生します。


Fatal error: Uncaught Error: Cannot create dynamic property SekarakuBlog::$content

また、PHP 8.2 から動的プロパティが非推奨になりました。

#[AllowDynamicProperties] 属性を記述することで、動的プロパティを引き続き使用することができます。

しかし、readonly クラス内で #[AllowDynamicProperties] を使用することは禁止されており、readonly クラスで #[AllowDynamicProperties] を使用しようとすると、下記のようなエラーが発生します。


<?php
#[AllowDynamicProperties]
readonly class SekarakuBlog {}

// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class SekarakuBlog

<?php readonly class SekarakuBlog 
{ 
  public $title;

  public function __construct() 
  { 
   $this->title = 'test Title'; 
  } 
} 

$test = new SekarakuBlog(); 
// Fatal error: Readonly property SekarakuBlog::$title must have type

プロパティに型を定義していない場合にもエラーが発生するので注意しましょう。

継承

readonly クラスを readonly クラスで継承をすることは可能ですが、

readonly クラスを readonly ではないクラスで継承をしたり、readonly ではないクラスを readonly のクラスで継承をすることは禁止されております。


# 下記は OK

readonly class SekarakuBlog {}
readonly class ExtendSekaraku extends SekarakuBlog {}

# 下記はNG
class SekarakuBlog {}
readonly class ExtendSekaraku extends SekarakuBlog {}
// Fatal error: Readonly class ExtendSekaraku cannot extend non-readonly class SekarakuBlog

readonly class SekarakuBlog {}
class ExtendSekaraku extends SekarakuBlog {}
// Fatal error: Non-readonly class ExtendSekaraku cannot extend readonly class SekarakuBlog

下記メソッドを使用することで、readonly クラスか否かも確認できるようになりました。


readonly class SekarakuBlog
{}

$refrectionClass = new ReflectionClass('SekarakuBlog');
$refrection->isReadOnly(); // true

final クラス修飾子との違い

read only クラスと final クラス修飾子の違いに関しても少し触れます。

read only クラスは上記で説明してきた通り、read only クラス同士の継承は可能でしたが、final クラス修飾子をしたクラスは

クラスの拡張を行うことができません。

ちなみに、クラスの拡張も、値の書き換えも行いたく無い場合は下記の記述をすることができます。


<?php
final readonly class Sekaraku
{
  public string $hoge;

  public function __construct()
  {
    $this->hoge = 'hoge';
  }
}

$test = new Sekaraku();
$test->hoge = 'test';
// Fatal error: Uncaught Error: Cannot modify readonly property Sekaraku::$hoge in /var/www/html/docker/php/finalreadonly.php:17

readonly class Lab extends Sekaraku
{}

$test2 = new Lab();
// Fatal error: Class Lab cannot extend final class Sekaraku in /var/www/html/docker/php/finalreadonly.php on line 20

メリット

readonly クラスを使用することで、プロパティ毎に readonly 修飾子を設定する必要がなく手間が省けます。

一度設定した値は書き換えることができなくなり、動的プロパティも禁止することができるのでより堅牢なコードを書くことができそうですね。

まとめ

今回は PHP 8.2 で追加された機能は他にもありましたが、全体的に細かい追加機能が多かった印象です。

個人的には動的プロパティが非推奨になった点は、今後の PHP ではかなり大きいと思いました。

(クラスのプロパティをクラス外で宣言したときに、どこでそのプロパティが宣言されているか分からなくなりますし

デバッグの効率が落ちると考えているからです。)

使用している方も多いかと思いますので、バージョンを上げる際には注意が必要そうです。

また、紹介できればと思います!

それでは良い PHP ライフを!

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
7
読み込み中...
7 票, 平均: 1.00 / 17
1,085
X facebook はてなブックマーク pocket
【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【2025.6.30 Amazon Linux 2 サポート終了】Amazon Linux サーバー移行ソリューション

【2025.6.30 Amazon Linux 2 サポート終了】Amazon Linux サーバー移行ソリューション

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

この記事をかいた人

About the author

小出将伍

大阪府出身。サウナ好きエンジニア。休日になるとサウナに行き宇宙と交信をしている。社内では朝もく会という会を平日の朝8:30 ~ 9:30 で開催し、朝もく会会長をしている。業務では主にPHPでの開発を中心に担当している。