插件窝 干货文章 PHP常量继承中self::X的行为:为什么PHP 7前后输出结果不同?

PHP常量继承中self::X的行为:为什么PHP 7前后输出结果不同?

常量 引用 PHP 子类 551    来源:    2025-03-15

在PHP中,常量的继承行为在PHP 7前后确实发生了变化,尤其是在使用self::static::时。这种变化主要与PHP 7引入的“后期静态绑定”(Late Static Binding)有关。

PHP 5.x 中的行为

在PHP 5.x中,self::关键字总是引用定义它的类,而不是运行时调用的类。这意味着,如果你在一个父类中定义了一个常量,并在子类中重写了这个常量,使用self::引用该常量时,PHP 5.x会始终引用父类中的常量,而不是子类中的常量。

class A {
    const X = 'A';
    public static function getX() {
        return self::X;
    }
}

class B extends A {
    const X = 'B';
}

echo B::getX(); // 输出 'A'

在上面的例子中,B::getX()调用的是A::getX(),而self::XA类中定义,因此输出的是A

PHP 7 中的行为

在PHP 7中,self::的行为发生了变化。self::现在会引用调用它的类,而不是定义它的类。这意味着如果你在子类中重写了常量,self::会引用子类中的常量。

class A {
    const X = 'A';
    public static function getX() {
        return self::X;
    }
}

class B extends A {
    const X = 'B';
}

echo B::getX(); // 输出 'B'

在这个例子中,B::getX()调用的是A::getX(),但self::X现在引用的是B类中的常量,因此输出的是B

使用 static:: 的行为

如果你希望在PHP 5.x和PHP 7中都能引用子类中的常量,可以使用static::关键字。static::实现了“后期静态绑定”,它会根据调用时的类来决定引用哪个常量。

class A {
    const X = 'A';
    public static function getX() {
        return static::X;
    }
}

class B extends A {
    const X = 'B';
}

echo B::getX(); // 输出 'B' (在PHP 5.x和PHP 7中都是如此)

在这个例子中,static::X会根据调用时的类来决定引用哪个常量。因此,无论是在PHP 5.x还是PHP 7中,B::getX()都会输出B

总结

  • 在PHP 5.x中,self::总是引用定义它的类中的常量。
  • 在PHP 7中,self::会引用调用它的类中的常量。
  • 如果你希望在不同版本的PHP中都能引用子类中的常量,建议使用static::

这种变化是为了使PHP的行为更加一致和可预测,尤其是在涉及继承和重写时。