staticを付け忘れると、インスタンス間でプロパティが共有されない
インスタンスをまたいで値を共有したい場合はstaticプロパティが必要です。staticを付け忘れると、そのプロパティは各インスタンスに独立して属するため、期待した共有ができません。
エラーメッセージの読み方
Fatal error: Uncaught Error: Access to undeclared static property Counter::$count in main.php:5
main.php- ファイル名
5- 行番号 — 実際にクラッシュした行
Error- 例外クラス — 何が起きたか。ここを検索するのが最短です
Access to undeclared static property Counter::$count- 内容 — どの値が問題だったか
このエラーが出る典型パターン
パターン1
1 <?php 2 class Counter { 3 public int $count = 0; ^ 4 public function increment() { 5 self::$count++; 6 } 7 } 8 $a = new Counter(); 9 $b = new Counter(); 10 $a->increment(); 11 $a->increment(); 12 $b->increment(); 13 echo Counter::$count;
staticを付けずに宣言すると$countはインスタンスごとの通常のプロパティになります。それをself::$countという静的な書き方でアクセスしようとすると、静的プロパティとして宣言されていないため致命的エラーになります。
直し方: (空) を static にします。
パターン2
1 <?php 2 class Registry { 3 public int $total = 0; ^ 4 public function add($n) { 5 self::$total += $n; 6 } 7 } 8 $a = new Registry(); 9 $b = new Registry(); 10 $a->add(10); 11 $b->add(5); 12 echo Registry::$total;
staticの無い$totalをself::$totalとして扱おうとすると、静的プロパティが宣言されていないため致命的エラーになります。全インスタンスで共有したい値にはstaticが必要です。
直し方: (空) を static にします。
パターン3
1 <?php 2 class Logger { 3 public int $entries = 0; ^ 4 public function log() { 5 self::$entries++; 6 } 7 } 8 $a = new Logger(); 9 $b = new Logger(); 10 $a->log(); 11 $b->log(); 12 $b->log(); 13 echo Logger::$entries;
$entriesにstaticが無いままself::$entriesとしてアクセスすると、静的プロパティとして宣言されていないため致命的エラーになります。
直し方: (空) を static にします。
パターン4
1 <?php 2 class Cache { 3 public int $hits = 0; ^ 4 public function hit() { 5 self::$hits++; 6 } 7 } 8 $a = new Cache(); 9 $b = new Cache(); 10 $a->hit(); 11 $b->hit(); 12 $b->hit(); 13 echo Cache::$hits;
staticを付けずに宣言すると$hitsはインスタンスごとの通常のプロパティになります。それをself::$hitsという静的な書き方でアクセスしようとすると致命的エラーになります。
直し方: (空) を static にします。
パターン5
1 <?php 2 class Pool { 3 public int $used = 0; ^ 4 public function consume() { 5 self::$used++; 6 } 7 } 8 $a = new Pool(); 9 $b = new Pool(); 10 $a->consume(); 11 $a->consume(); 12 $b->consume(); 13 echo Pool::$used;
$usedにstaticが無いままself::$usedとしてアクセスすると、静的プロパティとして宣言されていないため致命的エラーになります。
直し方: (空) を static にします。
よくある誤解
「クラスに書いたプロパティはクラス全体で1つのはず」という思い込みは誤りです。staticを付けない限り、プロパティはnewするたびに新しく作られる、インスタンスごとに独立した値になります。
実務での勘所
静的プロパティは、明示的に子クラス側で再宣言しない限り、親クラスと全ての子クラスで同じ1つの実体を共有します。ParentClassでstaticなカウンタを宣言し、ChildAとChildBがそれを継承してそれぞれ操作すると、実は同じ1つの値を奪い合っていることになります。サブクラスごとに独立したカウンタが欲しい場合は、それぞれの子クラスで同名のstaticプロパティを再宣言する必要があり、そうして初めてそのサブクラス系統専用の別の実体として扱われます。