Note that there are some explanatory texts on larger screens.

plurals
  1. POBest workaround to create a PHP class constant from an expression?
    primarykey
    data
    text
    <p>I'd like to be able to do something like this:</p> <pre class="lang-php prettyprint-override"><code>class Circle { const RADIUS_TO_CIRCUMFERENCE = M_PI * 2; // Not allowed private $radius; public function __construct( $radius ) { $this-&gt;radius = $radius; } ... public function getCircumference() { return $this-&gt;radius * self::RADIUS_TO_CIRCUMFERENCE; } } </code></pre> <p>But I can't create a <a href="http://php.net/manual/en/language.oop5.constants.php" rel="noreferrer">class constant</a> from an expression like that:</p> <blockquote> <p>The value must be a constant expression, not (for example) a variable, a property, a result of a mathematical operation, or a function call.</p> </blockquote> <p><br/> 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? <br/><br/></p> <h2>1. Create a property</h2> <pre class="lang-php prettyprint-override"><code>class Circle { private static $RADIUS_TO_CIRCUMFERENCE; private $radius; public function __construct( $radius ) { $this-&gt;radius = $radius; $this-&gt;RADIUS_TO_CIRCUMFERENCE = M_PI * 2; } ... public function getCircumference() { return $this-&gt;radius * $this-&gt;RADIUS_TO_CIRCUMFERENCE; } } </code></pre> <p>I don't like this, because the value of <code>$RADIUS_TO_CIRCUMFERENCE</code> can be changed, so it's not really a "constant". <br/><br/></p> <h2>2. Use <code>define()</code></h2> <pre class="lang-php prettyprint-override"><code>define( 'RAD_TO_CIRCUM', M_PI * 2 ); class Circle { const RADIUS_TO_CIRCUMFERENCE = RAD_TO_CIRCUM; ... public function getCircumference() { return $this-&gt;radius * self::RADIUS_TO_CIRCUMFERENCE; } } </code></pre> <p>This is better, since the value is truly constant, but the drawback is that <code>RAD_TO_CIRCUM</code> has been globally defined.</p> <p><strong>A digression</strong></p> <p>I don't understand how this can work. <em>(Edit: I've tested it, and it does work.)</em> According to the <a href="http://www.pvtuts.com/php/php-static#const-define" rel="noreferrer">Handbook of PHP Syntax</a>:</p> <blockquote> <p>The <code>const</code> modifier creates a compile-time constant and so the compiler will replace all usage of the constant with its value. In contrast, <code>define</code> creates a run-time constant which is not set until run-time. This is the reason why <code>define</code> constants may be assigned with expressional values, whereas <code>const</code> requires constant values which are known at compile-time.</p> </blockquote> <p>The manual <a href="http://php.net/manual/en/language.constants.syntax.php" rel="noreferrer">confirms</a> that "constants defined using the <code>const</code> keyword ... are defined at compile-time".</p> <p>In <a href="https://bugs.php.net/bug.php?id=51765" rel="noreferrer">this bug report</a> from 3 years ago, a member of the PHP team wrote:</p> <blockquote> <p>For the class constant we need a constant value at compile time and can't evaluate expressions. <code>define()</code> is a regular function, evaluated at run time and can therefore contain any value of any form.</p> </blockquote> <p>But in my example above, the value of <code>RAD_TO_CIRCUM</code> is not known at compile-time. So what is the compiler putting for the value of <code>RADIUS_TO_CIRCUMFERENCE</code>?</p> <p>I'm guessing that the compiler creates some kind of placeholder for the value of <code>RADIUS_TO_CIRCUMFERENCE</code>, and at run-time, that placeholder gets replaced with the value of <code>RAD_TO_CIRCUM</code>. Might this placeholder be a kind of <a href="http://php.net/manual/en/language.types.resource.php" rel="noreferrer">resource</a>? If so, maybe this technique should be avoided? The manual <a href="http://php.net/manual/en/language.constants.syntax.php" rel="noreferrer">says</a>: "It is possible to define constants as a resource, but it should be avoided, as it can cause unexpected results." <br/><br/></p> <h2>3. Create a method</h2> <pre class="lang-php prettyprint-override"><code>class Circle { ... private static function RADIUS_TO_CIRCUMFERENCE() { return M_PI * 2; } public function getCircumference() { return $this-&gt;radius * $this-&gt;RADIUS_TO_CIRCUMFERENCE(); } } </code></pre> <p>This is my favourite workaround that I'm aware of. The value is constant, and it doesn't affect the global space.</p> <p>Is there another workaround which is even better?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload