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

时间:2013-08-06 11:36:54

标签: php class const 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;
    }

}

但我不能从像这样的表达式创建class constant

  

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


所以我的问题是:这种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;
    }

}

我不喜欢这样,因为$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;
    }

}

这样做更好,因为该值确实是恒定的,但缺点是RAD_TO_CIRCUM已全局定义。

一个题外话题

我不明白这是如何工作的。 (编辑:我已对其进行了测试,但确实有效。)根据Handbook of PHP Syntax

  

const修饰符创建编译时常量,因此编译器将使用其值替换常量的所有用法。相反,define创建一个运行时常量,直到运行时才设置。这就是为什么define常量可以赋予表达值的原因,而const需要在编译时已知的常量值。

使用const关键字定义的常量的手册confirms在编译时定义。“

在3年前的this bug report中,PHP团队的一名成员写道:

  

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

但是在上面的例子中,RAD_TO_CIRCUM的值在编译时是未知的。那么编译器为RADIUS_TO_CIRCUMFERENCE的值设置了什么?

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

3。创建方法

class Circle {

    ...

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

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

}

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

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

4 个答案:

答案 0 :(得分:13)

从PHP 5.6开始,您可以使用math expressions in PHP constants,这样就可以了:

const RADIUS_TO_CIRCUMFERENCE = M_PI * 2;

我遇到了这个帖子,因为我的环境没有正确配置(偶然设置为PHP 5.4),所以不要忘记查看你的PHP版本。

答案 1 :(得分:2)

我会推荐这种方法:

class Circle {

    ...

    private function RADIUS_TO_CIRCUMFERENCE() {
        static $RADIUS_TO_CIRCUMFERENCE;

        if ( null === $RADIUS_TO_CIRCUMFERENCE )
            $RADIUS_TO_CIRCUMFERENCE = M_PI * 2;

        return $RADIUS_TO_CIRCUMFERENCE;
    }

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

目标是对所有类实体只计算一次,如实常数。

答案 2 :(得分:0)

如果您同意使用标准变量而不是const关键字:

class Foo {

    public $CONST_A; // = calculation A // To let people quickly see the value.
    public $CONST_B; // = calculation B 

    public static function initClass() {
        self::$CONST_A = /* calculation A */;
        self::$CONST_B = /* calculation B */;
    }
}

Foo::initClass();

initClass()只需要一次,当需要类文件时。

答案 3 :(得分:0)

就我而言

我安装的php版本是7.1,但是在我的IDE(PhpStorm)设置中选择了php版本5.4。一旦我更改了php版本,问题就消失了。

PhpStorm设置-> PHP,并更改PHP语言级别和CLI解释器php版本。