Code Fix

上級

Cannot modify readonly property の原因と直し方

readonlyを付けたプロパティは、コンストラクタの中で一度初期化した後は二度と値を変更できません。クラスの外からはもちろん、クラスの中のメソッドからの再代入も拒否されます。

エラーメッセージの読み方

Fatal error: Uncaught Error: Cannot modify readonly property Point::$x in main.php:9
main.php
ファイル名
9
行番号 — 実際にクラッシュした行
Error
例外クラス — 何が起きたか。ここを検索するのが最短です
Cannot modify readonly property Point::$x
内容 — どの値が問題だったか

このエラーが出る典型パターン

パターン1

 1  <?php
 2  class Point {
 3      public function __construct(
 4          public readonly int $x,
 5          public int $y
 6      ) {}
 7  }
 8  $p = new Point(1, 2);
 9  $p->x  = 99;
         ^
Fatal error: Uncaught Error: Cannot modify readonly property Point::$x in main.php:9

$xはreadonlyなので、コンストラクタで初期化した後は二度と代入できません。書き換えたい値はreadonlyを付けていない$yのようなプロパティにする必要があります。

直し方: xy にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  <?php
 2  class Account {
 3      public function __construct(
 4          public readonly string $id,
 5          public int $balance
 6      ) {}
 7  }
 8  $acc = new Account("AC1", 1000);
 9  $acc->id        = 2000;
              ^
Fatal error: Uncaught Error: Cannot modify readonly property Account::$id in main.php:9

$idはreadonlyなので再代入できません。変更したい値は$balanceのようなreadonlyでないプロパティに限られます。

直し方: idbalance にします。

この問題を解いてみる →

パターン3

 1  <?php
 2  class Config {
 3      public function __construct(
 4          public readonly string $key,
 5          public string $value
 6      ) {}
 7  }
 8  $cfg = new Config("env", "dev");
 9  $cfg->key   = "prod";
            ^
Fatal error: Uncaught Error: Cannot modify readonly property Config::$key in main.php:9

$keyはreadonlyのため書き換えできません。更新したいのは$valueのようなreadonlyでないプロパティです。

直し方: keyvalue にします。

この問題を解いてみる →

よくある誤解

「readonlyでもクラスの内部からなら書き換えられるはず」という思い込みは誤りです。readonlyは初期化済みかどうかだけを見るため、クラスの内外を問わず2回目の代入は必ずエラーになります。

まとめ

Cannot modify readonly propertyは上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)