I'd like to be able to do something like this:
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;
}
}
But I can't create a class constant from an expression like that:
The value must be a constant expression, not (for example) a variable, a property, a result of a mathematical operation, or a function call.
So my question is: What's the best workaround for this limitation of PHP? I'm aware of the following workarounds, but are there any others which are better?
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;
}
}
I don't like this, because the value of $RADIUS_TO_CIRCUMFERENCE
can be changed, so it's not really a "constant".
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;
}
}
This is better, since the value is truly constant, but the drawback is that RAD_TO_CIRCUM
has been globally defined.
A digression
I don't understand how this can work. (Edit: I've tested it, and it does work.) According to the Handbook of PHP Syntax:
The
const
modifier creates a compile-time constant and so the compiler will replace all usage of the constant with its value. In contrast,define
creates a run-time constant which is not set until run-time. This is the reason whydefine
constants may be assigned with expressional values, whereasconst
requires constant values which are known at compile-time.
The manual confirms that "constants defined using the const
keyword ... are defined at compile-time".
In this bug report from 3 years ago, a member of the PHP team wrote:
For the class constant we need a constant value at compile time and can't evaluate expressions.
define()
is a regular function, evaluated at run time and can therefore contain any value of any form.
But in my example above, the value of RAD_TO_CIRCUM
is not known at compile-time. So what is the compiler putting for the value of RADIUS_TO_CIRCUMFERENCE
?
I'm guessing that the compiler creates some kind of placeholder for the value of RADIUS_TO_CIRCUMFERENCE
, and at run-time, that placeholder gets replaced with the value of RAD_TO_CIRCUM
. Might this placeholder be a kind of resource? If so, maybe this technique should be avoided? The manual says: "It is possible to define constants as a resource, but it should be avoided, as it can cause unexpected results."
class Circle {
...
private static function RADIUS_TO_CIRCUMFERENCE() {
return M_PI * 2;
}
public function getCircumference() {
return $this->radius * $this->RADIUS_TO_CIRCUMFERENCE();
}
}
This is my favourite workaround that I'm aware of. The value is constant, and it doesn't affect the global space.
Is there another workaround which is even better?
As of PHP 5.6, you can use math expressions in PHP constants, so this would work:
const RADIUS_TO_CIRCUMFERENCE = M_PI * 2;
I encountered this thread because my environment wasn't configured properly (was set to PHP 5.4 by accident), so don't forget to check your PHP version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With