staticプロパティを self:: なしで参照すると別の変数として扱われる
クラス内からstaticプロパティにアクセスするには self::$prop のように書く必要があります。$propとだけ書くと、staticプロパティとは無関係のローカル変数として扱われ、Warningが出ます。
なぜエラーが出ないのか
出力:
(エラーなし)- PHPは何も報告しません。文法として正しいためです
出力:- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 <?php 2 class Counter { 3 public static int $count = 0; 4 public function increment() { 5 $count ++; ^ 6 } 7 } 8 $c = new Counter(); 9 $c->increment(); 10 $c->increment(); 11 echo Counter::$count;
出力:
Warning: Undefined variable $count in main.php on line 5
Warning: Undefined variable $count in main.php on line 5
0期待: 2 (Warningが出るだけで実行は止まりません)
self::を付けずに$countと書くと、staticプロパティとは無関係のローカル変数として扱われ、宣言も代入もされていないためWarningになります。Counter::$countは0のまま変わりません。
直し方: $count を self::$count にします。
広告
広告スロット(未設定)
パターン2
1 <?php 2 class Money { 3 public static int $total = 0; 4 public function add($n) { 5 $total += $n; ^ 6 } 7 } 8 $m = new Money(); 9 $m->add(100); 10 echo Money::$total;
出力:
Warning: Undefined variable $total in main.php on line 5
0期待: 100 (Warningが出るだけで実行は止まりません)
self::を付けなければ、$totalはstaticプロパティとは別のローカル変数です。Money::$totalは更新されず0のままになります。
直し方: $total を self::$total にします。
パターン3
1 <?php 2 class Registry { 3 public static array $items = []; 4 public function register($item) { 5 $items [] = $item; ^ 6 } 7 } 8 $r = new Registry(); 9 $r->register("a"); 10 echo count(Registry::$items);
出力: 0期待: 1 (Warningすら出ません。配列への追加はエラーなし・警告なしで通ってしまいます)
self::$itemsではなく$itemsと書くと、宣言されていないローカル配列への追加になります。スカラーの$count++と違い、配列への$items[] = ...という追加はPHPが警告すら出さずに黙って通してしまうため、$count++の例よりさらに気づきにくいバグになります。
直し方: $items を self::$items にします。
よくある誤解
「クラスの中で宣言したプロパティ名ならそのまま参照できるはず」という思い込みは、staticプロパティには当てはまりません。self::を付けない$countは、宣言も代入もされていない別のローカル変数です。
まとめ
staticプロパティを self:: なしで参照すると別の変数として扱われるは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。