これに何度も出くわしましたが、理由がわからないので、興味をそそられました。宣言される前に動作するクラスもあれば、動作しないクラスもあります。
例 1
$test = new TestClass(); // top of class
class TestClass {
function __construct() {
var_dump(__METHOD__);
}
}
出力
string 'TestClass::__construct' (length=22)
例 2
クラスが別のクラスを拡張するか、インターフェイスを実装する場合
$test = new TestClass(); // top of class
class TestClass implements JsonSerializable {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return json_encode(rand(1, 10));
}
}
出力
Fatal error: Class 'TestClass' not found
例 3
上記の同じクラスを試してみましょうが、位置を変更します
class TestClass implements JsonSerializable {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return json_encode(rand(1, 10));
}
}
$test = new TestClass(); // move this from top to bottom
出力
string 'TestClass::__construct' (length=22)
例 4 ( class_exists でもテストしました)
var_dump(class_exists("TestClass")); //true
class TestClass {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return null;
}
}
var_dump(class_exists("TestClass")); //true
実装するとすぐにJsonSerializable
(またはその他)
var_dump(class_exists("TestClass")); //false
class TestClass implements JsonSerializable {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return null;
}
}
var_dump(class_exists("TestClass")); //true
オペコードもチェックwithout
済み
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > SEND_VAL 'TestClass'
1 DO_FCALL 1 $0 'class_exists'
2 SEND_VAR_NO_REF 6 $0
3 DO_FCALL 1 'var_dump'
4 4 NOP
14 5 > RETURN 1
オペコードもチェックwith
済み
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > SEND_VAL 'TestClass'
1 DO_FCALL 1 $0 'class_exists'
2 SEND_VAR_NO_REF 6 $0
3 DO_FCALL 1 'var_dump'
4 4 ZEND_DECLARE_CLASS $2 '%00testclass%2Fin%2FaDRGC0x7f563932f041', 'testclass'
5 ZEND_ADD_INTERFACE $2, 'JsonSerializable'
13 6 ZEND_VERIFY_ABSTRACT_CLASS $2
14 7 > RETURN 1
質問
Example 3
クラスが開始される前に宣言されたために機能したことはわかっていますがExample 1
、そもそもなぜ機能するのでしょうか?- この拡張またはインターフェースのプロセス全体が PHP でどのように機能し、一方を有効にし、他方を無効にするのでしょうか?
- 例 4 では正確に何が起こっているのでしょうか?
Opcodes
class_exists
は物事を明確にするはずでしたが、以前に呼び出されたため、より複雑にTestClass
しましたが、その逆です。