📘
PHP8.2から8.3で変更となった「staticプロパティと一緒にトレイトを使う場合」の挙動
概要
PHP8.2から8.3への移行ガイドを見ていたところ以下の記載があったが、ぱっと見理解できなかったため検証してみた。
static プロパティと一緒にトレイトを使うと、親クラスから継承する static プロパティを再宣言するようになりました。つまり、現在のクラスのために別の static プロパティを作成するということです。これは、トレイトを使わずに直接 static プロパティを追加する操作に似ています。
環境
PHP検証用テンプレートリポジトリのDockerfileを8.2と8.3にして検証
検証
クラスでstaticプロパティを使用し継承する場合
各クラスのstaticプロパティへ値を入れても、クラスごとに独立している。
<?php
class A {
static $test;
}
class B {
static $test;
}
A::$test = 'A';
B::$test = 'B';
var_dump(A::$test, B::$test);
// string(1) "A"
// string(1) "B"
各クラスが同一のトレイトを使用する場合
各クラスで同一のトレイトを導入しstaticプロパティへ値を代入すると、クラスAのstaticプロパティも"B"となってしまう。
<?php
trait Foo {
static $test;
}
class A {
use Foo;
}
class B extends A {
use Foo;
}
A::$test = 'A';
B::$test = 'B';
var_dump(A::$test, B::$test);
// string(1) "B"
// string(1) "B"
ちなみにクラスCを追加しても同様。最終的に代入した値が反映されてしまう。
trait Foo {
static $test;
}
class A {
use Foo;
}
class B extends A {
use Foo;
}
class C extends B {
use Foo;
}
A::$test = 'A';
B::$test = 'B';
C::$test = 'C';
var_dump(A::$test, B::$test, C::$test);
PHP8.3にして確認
それぞれ独立した値となっている。
<?php
trait Foo {
static $test;
}
class A {
use Foo;
}
class B extends A {
use Foo;
}
class C extends B {
use Foo;
}
A::$test = 'A';
B::$test = 'B';
C::$test = 'C';
var_dump(A::$test, B::$test, C::$test);
まとめ
そもそもトレイトのstaticプロパティへ値を追加する機会はあるんだろうか?
参考
Discussion