Hi everyone
Since https://wiki.php.net/rfc/new_in_initializers we can store
objects in global constants. However, we may not actually read or
write to the properties of those objects without first fetching the
constant into a local variable.
const a = new stdClass;
a->b = 42; // Fatal error: Cannot use temporary expression in write context
$a = a;
$a->b = 42; // Works fine
This issue was reported twice, so it seems like this code is generally
expected to work.
https://github.com/php/php-src/issues/10497
https://github.com/php/php-src/issues/11781
I have created a patch here to add support for this syntax:
https://github.com/php/php-src/pull/11788
Since this is a language change I would like to ask for feedback
before merging. As always, if there are concerns I will create a small
RFC instead. I will also only merge this for 8.4, as feature freeze
for 8.3 has long passed.
Ilija
Hi everyone
Since https://wiki.php.net/rfc/new_in_initializers we can store
objects in global constants. However, we may not actually read or
write to the properties of those objects without first fetching the
constant into a local variable.const a = new stdClass;
a->b = 42; // Fatal error: Cannot use temporary expression in write context
$a = a;
$a->b = 42; // Works fineThis issue was reported twice, so it seems like this code is generally
expected to work.
https://github.com/php/php-src/issues/10497
https://github.com/php/php-src/issues/11781I have created a patch here to add support for this syntax:
https://github.com/php/php-src/pull/11788Since this is a language change I would like to ask for feedback
before merging. As always, if there are concerns I will create a small
RFC instead. I will also only merge this for 8.4, as feature freeze
for 8.3 has long passed.Ilija
I totally understand that people are trying to do this, but this still
very much feels like scope creep.
IIRC the new in initializers feature was intended only for enums
(which can't take properties). Now suddenly a "constant" would no longer
be constant... In which case, what's the point of declaring it as a
constant ?
Smile,
Juliette
Hi Juliette
Since https://wiki.php.net/rfc/new_in_initializers we can store
objects in global constants. However, we may not actually read or
write to the properties of those objects without first fetching the
constant into a local variable.const a = new stdClass;
a->b = 42; // Fatal error: Cannot use temporary expression in write context
$a = a;
$a->b = 42; // Works fineThis issue was reported twice, so it seems like this code is generally
expected to work.
https://github.com/php/php-src/issues/10497
https://github.com/php/php-src/issues/11781I have created a patch here to add support for this syntax:
https://github.com/php/php-src/pull/11788I totally understand that people are trying to do this, but this still
very much feels like scope creep.IIRC the new in initializers feature was intended only for enums
(which can't take properties). Now suddenly a "constant" would no longer
be constant... In which case, what's the point of declaring it as a
constant ?
This patch doesn't change the mutability of objects in constants, as
they already don't offer interior immutability. https://3v4l.org/s7rHE
This is analogous to const
in JavaScript or readonly
properties in
PHP, where we can't change the value of the variable (or const in this
case), but we can modify the properties of the object it's pointing
to.
I believe the main motivation for new
in constant expressions was to
support nested attributes. Enums have their own mechanism for
instantiating cases. Since it was decided to expand the support for
new
to global constants, I would expect it to work with other
language constructs, unless there's a good reason for it not to.
Ilija
Le 19 août 2023 à 02:18, Juliette Reinders Folmer php-internals_nospam@adviesenzo.nl a écrit :
I totally understand that people are trying to do this, but this still very much feels like scope creep.
IIRC the new in initializers feature was intended only for enums (which can't take properties). Now suddenly a "constant" would no longer be constant... In which case, what's the point of declaring it as a constant ?
Smile,
Juliette
Hi,
It might not be the original intended use. But people are entitled to use features if they find them handy for their purpose. (It was the reason I end up using PHP rather than Java: because it solved problems https://www.npopov.com/2012/06/29/PHP-solves-problems-Oh-and-you-can-program-with-it-too.html.)
At the time I filed https://github.com/php/php-src/issues/10497, I was merely exploring the potential of the new ability to have an object in a constant. The potential use I had back in my head was the following. Currently, I store some settings in global constants. I was contemplating replacing those by properties of a readonly object stored in a global constant. (A fatal issue I discovered later in my journey is that readonly properties can only be initialised by code inside the class itself.)
But in any case, it is good to have regularity in the language. The fact that an object is stored in a constant is completely orthogonal with the fact that the object is mutable, and the proposed patch does not add new capability. (Conversely, the current limitation does not remove any capability.)
—Claude
At the time I filed https://github.com/php/php-src/issues/10497, I was
merely exploring the potential of the new ability to have an object in
a constant. The potential use I had back in my head was the following.
Currently, I store some settings in global constants. I was
contemplating replacing those by properties of a readonly object stored
in a global constant. (A fatal issue I discovered later in my journey
is that readonly properties can only be initialised by code inside the
class itself.)
As a tangent here, that has a workaround:
https://peakd.com/hive-168588/@crell/php-tricks-access-control-bypass
Which I make use of in Crell/Serde, which is then used by my own config library to produce exactly what you describe:
https://github.com/Crell/Config
--Larry Garfield