Re: Initializing constants once, with code?

From: Date: Fri, 03 Jan 2020 00:09:31 +0000
Subject: Re: Initializing constants once, with code?
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-107965@lists.php.net to get a copy of this message
> The problem with using constants is that the value is still hardcoded > and if we later want to change to pulling the data from a config file > we have to change all the code that uses those constants.  It's possible to work around this by using a unique constant name and define('unique_name', $dynamicExpression) (and const MY_CLASS_CONST = \unique_name;) Maybe php could add something along these lines: local const X = sprintf('In %s', $dynamicValue); // Not supported in functions or loops. // Translates internally to: // if (defined('some_globally_unique_constant123af') || // !define('some_globally_unique_constant123af', X)) { throw ...; } // use some_globally_unique_constant123af as X; class MyClass { const PUBLIC = X; } - php still needs to prevent recursion such as const A = count(B); const B = array_fill(1, A, 'value');, which is why the simplest approach would be one that eagerly evaluates dynamic expressions. That's probably not the only way - maybe it could track all of the constants that are in the process of being defined and cause an uncatchable fatal error if there was recursion. - Right now, reading the value of a class constant can already emit notices or throw an Error (undeclared constants) the first time it gets evaluated - Any approach should throw for results that contain cycles, objects, or references, the same way define() warns. The below ugly proof of concept shows that the php runtime can in a sense defer evaluation of dynamic class constants to runtime (not recursively) (assume errstr/errfile control what constant gets loaded). This POC should not be used anywhere. <?php set_error_handler(function ($errno, $errstr) { echo "Ignoring $errno: $errstr\n"; define( 'SOME_GLOBALLY_UNIQUE_CONSTANT', sprintf('Hello, %s', $GLOBALS['globalVar']) ); }); class MyTest { const KEY = 'myKey'; const FOO = [ self::KEY => [[][0], SOME_GLOBALLY_UNIQUE_CONSTANT][1], ]; } $globalVar = 'world'; echo "Fetching MyTest::FOO\n"; var_dump(MyTest::FOO); /* Output: Fetching MyTest::FOO Ignoring 8: Undefined offset: 0 array(1) { ["myKey"]=> string(12) "Hello, world" } */

« previous php.internals (#107965) next »