从表达式创建PHP类常量的最佳解决方法?

Tac*_*tex 15 php const class constants

我希望能够做到这样的事情:

class Circle {

    const RADIUS_TO_CIRCUMFERENCE = M_PI * 2;  // Not allowed

    private $radius;

    public function __construct( $radius ) {
        $this->radius = $radius;
    }

    ...

    public function getCircumference() {
        return $this->radius * self::RADIUS_TO_CIRCUMFERENCE;
    }

}
Run Code Online (Sandbox Code Playgroud)

但我不能从这样的表达式创建一个类常量:

该值必须是常量表达式,而不是(例如)变量,属性,数学运算的结果或函数调用.


所以我的问题是:这种PHP限制的最佳解决方法是什么?我知道以下变通方法,但还有其他更好的方法吗?

1.创建一个属性

class Circle {

    private static $RADIUS_TO_CIRCUMFERENCE;

    private $radius;

    public function __construct( $radius ) {
        $this->radius = $radius;
        $this->RADIUS_TO_CIRCUMFERENCE = M_PI * 2;
    }

    ...

    public function getCircumference() {
        return $this->radius * $this->RADIUS_TO_CIRCUMFERENCE;
    }

}
Run Code Online (Sandbox Code Playgroud)

我不喜欢这个,因为价值$RADIUS_TO_CIRCUMFERENCE可以改变,所以它不是真正的"常数".

2.使用 define()

define( 'RAD_TO_CIRCUM', M_PI * 2 );

class Circle {

    const RADIUS_TO_CIRCUMFERENCE = RAD_TO_CIRCUM;

    ...

    public function getCircumference() {
        return $this->radius * self::RADIUS_TO_CIRCUMFERENCE;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是更好的,因为该值是真正恒定的,但缺点是RAD_TO_CIRCUM已经全局定义.

一个题外话

我不明白这是如何工作的.(编辑:我已经测试了它,它确实有效.)根据PHP语法手册:

const功能键可以创建一个编译时间常数,所以编译器将取代它的价值不断的所有使用.相反,define创建一个运行时常量,直到运行时才设置.这就是为什么define可以为常量赋予表达值,而const需要在编译时已知的常数值.

该手册确认 "使用const关键字定义的常量......在编译时定义".

在3年前的这个错误报告中,PHP团队的一名成员写道:

对于类常量,我们在编译时需要一个常量值,并且不能计算表达式.define()是一个常规函数,在运行时进行评估,因此可以包含任何形式的任何值.

但在上面的例子中,RAD_TO_CIRCUM编译时不知道值.那么编译器的价值是RADIUS_TO_CIRCUMFERENCE什么?

我猜测编译器会为其值创建某种占位符RADIUS_TO_CIRCUMFERENCE,并且在运行时,该占位符将替换为值RAD_TO_CIRCUM.这个占位符可能是一种资源吗?如果是这样,也许应该避免这种技术?手册:"可以将常量定义为资源,但应该避免,因为它可能会导致意外的结果."

3.创建一个方法

class Circle {

    ...

    private static function RADIUS_TO_CIRCUMFERENCE() {
        return M_PI * 2;
    }

    public function getCircumference() {
        return $this->radius * $this->RADIUS_TO_CIRCUMFERENCE();
    }

}
Run Code Online (Sandbox Code Playgroud)

这是我最喜欢的解决方法,我知道.该值是常量,不会影响全局空间.

还有其他解决方法甚至更好吗?

kei*_*sar 15

从PHP 5.6开始,您可以在PHP常量中使用数学表达式,这样就可以了:

const RADIUS_TO_CIRCUMFERENCE = M_PI * 2;
Run Code Online (Sandbox Code Playgroud)

我遇到了这个线程,因为我的环境配置不正确(偶然设置为PHP 5.4),所以不要忘记检查你的PHP版本.