插件窝 干货文章 PHP常量继承中self关键字的行为:为什么子类重定义父类常量后,结果会因PHP版本而异?

PHP常量继承中self关键字的行为:为什么子类重定义父类常量后,结果会因PHP版本而异?

常量 关键字 self const 266    来源:    2025-03-15

在PHP中,常量的继承和self关键字的行为在不同版本中确实存在差异,尤其是在子类重定义父类常量时。这种行为的变化主要是由于PHP在处理常量和self关键字时的内部机制发生了变化。

PHP 5.x 中的行为

在PHP 5.x 版本中,self关键字在编译时绑定到定义它的类。这意味着,如果子类重定义了父类的常量,self关键字仍然会引用父类的常量,而不是子类的常量。

class ParentClass {
    const MY_CONST = 'Parent';

    public static function getConst() {
        return self::MY_CONST;
    }
}

class ChildClass extends ParentClass {
    const MY_CONST = 'Child';
}

echo ChildClass::getConst(); // 输出: Parent

在上面的例子中,ChildClass::getConst() 返回的是 Parent,因为 self::MY_CONSTParentClass 中定义,并且在编译时绑定到了 ParentClass

PHP 7.x 中的行为

在PHP 7.x 版本中,self关键字的行为发生了变化。self关键字现在在运行时绑定到调用它的类。这意味着,如果子类重定义了父类的常量,self关键字会引用子类的常量。

class ParentClass {
    const MY_CONST = 'Parent';

    public static function getConst() {
        return self::MY_CONST;
    }
}

class ChildClass extends ParentClass {
    const MY_CONST = 'Child';
}

echo ChildClass::getConst(); // 输出: Child

在这个例子中,ChildClass::getConst() 返回的是 Child,因为 self::MY_CONST 在运行时绑定到了 ChildClass

为什么会有这种差异?

这种差异主要是由于PHP在处理常量和self关键字时的内部机制发生了变化。在PHP 5.x 中,self关键字在编译时绑定到定义它的类,而在PHP 7.x 中,self关键字在运行时绑定到调用它的类。

这种变化是为了使PHP的行为更加一致和可预测,尤其是在面向对象编程中。在PHP 7.x 中,self关键字的行为更符合大多数开发者的预期,即它应该引用当前类的常量,而不是定义它的类的常量。

如何解决这个问题?

如果你希望代码在PHP 5.x 和 PHP 7.x 中都能正常工作,可以使用static关键字代替self关键字。static关键字在PHP 5.x 和 PHP 7.x 中都会在运行时绑定到调用它的类。

class ParentClass {
    const MY_CONST = 'Parent';

    public static function getConst() {
        return static::MY_CONST;
    }
}

class ChildClass extends ParentClass {
    const MY_CONST = 'Child';
}

echo ChildClass::getConst(); // 输出: Child

在这个例子中,ChildClass::getConst() 在PHP 5.x 和 PHP 7.x 中都会返回 Child,因为 static::MY_CONST 在运行时绑定到了 ChildClass

总结

  • 在PHP 5.x 中,self关键字在编译时绑定到定义它的类,因此子类重定义父类常量后,self关键字仍然引用父类的常量。
  • 在PHP 7.x 中,self关键字在运行时绑定到调用它的类,因此子类重定义父类常量后,self关键字引用子类的常量。
  • 为了兼容PHP 5.x 和 PHP 7.x,可以使用static关键字代替self关键字,以确保在运行时绑定到调用它的类。