在某些情况下,无序定义PHP类扩展会导致致命错误,而在某些情况下则不会。我正在尝试了解潜在的行为。
例如,两者
<?php
class BaseClass {}
class FirstExt extends BaseClass {}
Run Code Online (Sandbox Code Playgroud)
和
<?php
class FirstExt extends BaseClass {}
class BaseClass {}
Run Code Online (Sandbox Code Playgroud)
很好,所以不是简单地无序定义子类就不会引起问题。
但是,当涉及到三个类时(仅在一种特定情况下),即以相反的顺序定义类链时,就会出现错误。也就是说,以下代码将导致致命错误:
<?php
class SecondExt extends FirstExt {}
class FirstExt extends BaseClass {}
class BaseClass {}
Run Code Online (Sandbox Code Playgroud)
如果您尝试从命令行运行此命令(例如main.php),则会得到
PHP Fatal error: Class 'FirstExt' not found in /path/to/main.php on line 2
Run Code Online (Sandbox Code Playgroud)
但是,三个类的其他五个顺序中的任何一个都没有错误。我很惊讶,即使
<?php
class SecondExt extends FirstExt {}
class BaseClass {}
class FirstExt extends BaseClass {}
Run Code Online (Sandbox Code Playgroud)
工作正常。区别因素是,在给出错误的情况下,所有三对可能的类对都是乱序,而在所有其他情况下,三对中的最多两对是乱序。
发生这种情况是怎么回事?
这种行为不是直观的,但我不认为这是一个错误,只是PHP加载类的方式的影响。
为了使类扩展父类,在定义子类时必须已经定义了父类。
根据我的观察,似乎在解析文件并开始执行之后,定义了以下类:
基本上,将在编译时定义任何类,并且在运行时定义(尝试)此时未定义的任何其他类。
因此,在此示例中:
<?php
echo class_exists('A') ? "Yes" : "No"; // No
echo class_exists('B') ? "Yes" : "No"; // Yes
echo class_exists('C') ? "Yes" : "No"; // Yes
class A extends B {}
class C {}
class B extends C {}
Run Code Online (Sandbox Code Playgroud)
当类A试图扩展它时就定义了类B,因为它是在解析文件时定义的,因为在文件中它是在类C之前定义的。
但是在这个例子中:
<?php
echo class_exists('A') ? "Yes" : "No"; // No
echo class_exists('B') ? "Yes" : "No"; // No
echo class_exists('C') ? "Yes" : "No"; // Yes
class A extends B {}
class B extends C {}
class C {}
Run Code Online (Sandbox Code Playgroud)
在类A尝试扩展它时未定义类B,因为在解析文件时未定义它,因为在文件中未在其之前定义类C。
PHP试图找到它,但是不会再次检入同一文件,而是试图自动加载它。那是当您得到“未找到”时。
添加第四个类,您可以看到它不仅发生在以相反顺序定义类时:
echo class_exists('A') ? "Yes" : "No"; // No
echo class_exists('B') ? "Yes" : "No"; // No
echo class_exists('C') ? "Yes" : "No"; // Yes
echo class_exists('D') ? "Yes" : "No"; // Yes
class A extends B {}
class D {}
class B extends C {}
class C extends D {}
Run Code Online (Sandbox Code Playgroud)