Menu
Coddy logo textTech

Readonly プロパティ (PHP 8.1)

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 19/91。

PHP 8.1では、一度だけ値を代入することができ、その後は変更できないreadonlyプロパティが導入されました。定数とは異なり、readonlyプロパティはクラスの定義時ではなく、オブジェクトの初期化時に設定されます。

型宣言の前に readonly キーワードを追加することで、読み取り専用プロパティを宣言します:

<?php
class User {
    public readonly string $id;
    public readonly string $name;
    
    public function __construct(string $id, string $name) {
        $this->id = $id;
        $this->name = $name;
    }
}

$user = new User("U001", "Alice");
echo $user->id . "\n";
echo $user->name;

出力:

U001
Alice

一度割り当てられると、readonly プロパティを変更しようとするとエラーが発生します。これにより、IDや作成タイムスタンプなど、オブジェクトの生存期間を通じて一定であるべき値に最適です。

readonly プロパティは型宣言を持つ必要があり、コンストラクタ内または宣言時のいずれかで一度だけ初期化できます。これらは、どの可視性修飾子とも組み合わせて使用できます。

<?php
class Product {
    public function __construct(
        public readonly string $sku,
        private readonly float $cost
    ) {}
    
    public function getCost(): float {
        return $this->cost;
    }
}

$product = new Product("ABC123", 29.99);
echo $product->sku;

出力:

ABC123

重要なポイント: Readonlyプロパティは、プロパティレベルでの不変性を提供します。これらは、オブジェクトを識別するデータや、作成後に変更すべきではないデータに最適であり、実行時の初期化という柔軟性と、誤った変更を防ぐ安全性というメリットを兼ね備えています。

challenge icon

チャレンジ

簡単

初期化後に重要な設定が誤って変更されないように、readonlyプロパティを使用して不変(イミュータブル)な設定システムを構築しましょう。

アプリケーションの設定を管理するために、連携して動作する2つのファイルを作成します:

  • Config.php — 不変の設定を持つアプリケーション構成を表す Config クラスを定義します。このクラスには、3つのpublicなreadonlyプロパティ string $appNamestring $version、および int $maxConnections を持たせる必要があります。コンストラクタのプロパティ昇格(constructor promotion)を使用して、これら3つのreadonlyプロパティを単一の簡潔なコンストラクタ定義で宣言および初期化してください。さらに、"[appName] v[version] (max: [maxConnections] connections)" という形式の文字列を返す getInfo() メソッドを追加してください。
  • main.php — Configクラスファイルをインクルードします。アプリ名、バージョン、最大接続数(整数に変換する必要がある文字列として)の3つの入力を受け取ります。これらの値を使用して Config オブジェクトを作成してください。最初の行に getInfo() の結果を出力します。次に、アプリ名、バージョン、最大接続数の各readonlyプロパティに直接アクセスして、それぞれを個別の行に出力してください。

readonlyプロパティを使用することで、一度設定が作成されるとその値が固定されることが保証されます。これは、アプリケーションの実行中ずっと一定であるべき設定に最適です。コンストラクタのプロパティ昇格とreadonlyを組み合わせることで、不変のバリューオブジェクトを非常に簡潔に定義できることに注目してください。

出力には、フォーマットされた情報文字列に続いて各プロパティの値が表示され、readonlyプロパティがクラスの外部から引き続き読み取り可能であることを示す必要があります。

チートシート

PHP 8.1 では readonly プロパティが導入されました。これは一度だけ値を代入でき、その後は変更することができません:

<?php
class User {
    public readonly string $id;
    public readonly string $name;
    
    public function __construct(string $id, string $name) {
        $this->id = $id;
        $this->name = $name;
    }
}

$user = new User("U001", "Alice");
echo $user->id; // U001

Readonly プロパティには型宣言が必要であり、一度しか初期化できません。これらは任意の可視性修飾子で使用でき、コンストラクタのプロパティ昇格(constructor promotion)と組み合わせることも可能です:

<?php
class Product {
    public function __construct(
        public readonly string $sku,
        private readonly float $cost
    ) {}
}

$product = new Product("ABC123", 29.99);
echo $product->sku; // ABC123

Readonly プロパティは、ID、タイムスタンプ、設定値など、オブジェクトの生存期間を通じて一定であるべき値に最適です。

自分で試してみよう

<?php

require_once 'Config.php';

// 入力を読み込む
$appName = trim(fgets(STDIN));
$version = trim(fgets(STDIN));
$maxConnections = intval(trim(fgets(STDIN)));

// TODO: 入力値を使用してConfigオブジェクトを作成する

// TODO: getInfo()の結果を出力する

// TODO: 各読み取り専用プロパティをそれぞれの行に出力する:
// - アプリ名
// - バージョン
// - 最大接続数

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン