Нашли это так много раз, и я не уверен, почему так мне стало любопытно. Некоторые классы работают до того, как они объявлены, а другие - нет;
Пример 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
Также проверенные Opcodes without
JsonSerializable
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
Также проверено Opcodes with
JsonSerializable
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
, но обратное дело.