[Discussion] Why can't I do "{$a::class}"?

php.internals

Peter Stalman

2 years ago
Hi Internals, Obviously we can't use constants or functions directly in strings using variable parsing, I assume because it lacks the easily detectable $. However, we _can_ use methods because the object variable has the $, which I assume is the reason methods work and functions don't. I feel like it's something that _could_ have been added when dynamic access of static members support was added in 5.3.0, but maybe it was overlooked or decided against? Consider: ``` <?php $a = new A(); echo " {A::$static_property} \n"; // doesn't work (unless $static_property is a variable) echo " {$a::$static_property} \n"; // works echo " {A::static_method()} \n"; // doesn't work (just text) echo " {$a::static_method()} \n"; // works echo " {A::constant} \n"; // doesn't work echo " {$a::constant} \n"; // doesn't work either, but why? ?> ``` Also, as a side note, why does this hack below work? It seems like something that would use `eval()`, but doesn't. Take a look: https://3v4l.org/aPCSD I found it at the bottom of the manual entry for Strings[1]. Not something I would use, but it's interesting to see. Thanks, Peter [1]: https://www.php.net/manual/en/language.types.string.php#91628

Robert Landers

2 years ago
On Sun, May 19, 2024 at 10:33 AM Peter Stalman <sarkedev@gmail.com> wrote:
> > Hi Internals, > > Obviously we can't use constants or functions directly in strings using variable parsing, I assume because it lacks the easily detectable $. > > However, we _can_ use methods because the object variable has the $, which I assume is the reason methods work and functions don't. > > I feel like it's something that _could_ have been added when dynamic access of static members support was added in 5.3.0, but maybe it was overlooked or decided against? Consider: > > ``` > <?php > > $a = new A(); > > echo " {A::$static_property} \n"; // doesn't work (unless $static_property is a variable) > echo " {$a::$static_property} \n"; // works > > echo " {A::static_method()} \n"; // doesn't work (just text) > echo " {$a::static_method()} \n"; // works > > echo " {A::constant} \n"; // doesn't work > echo " {$a::constant} \n"; // doesn't work either, but why? > > ?> > ``` > > > Also, as a side note, why does this hack below work? It seems like something that would use `eval()`, but doesn't. Take a look: > > https://3v4l.org/aPCSD > > I found it at the bottom of the manual entry for Strings[1]. Not something I would use, but it's interesting to see. > > Thanks, > Peter > > [1]: https://www.php.net/manual/en/language.types.string.php#91628
In general, it would be nice to have some proper inline string templating, like other languages (js, C#, etc). At least some way to evaluate an expression and format. I'm thinking like in C#: $"Price: {price:C2}, Quantity: {quantity}, Discount: {discount:P1}, Total after discount: {(price * quantity * (1 - discount)):N2}" Price is formatted using currency with 2 decimal places, discount is formatted using percentage and one decimal, and N is a number format with 2 decimals. Robert Landers Software Engineer Utrecht NL

Tim Düsterhus

2 years ago
Hi On 5/19/24 12:39, Robert Landers wrote:
> In general, it would be nice to have some proper inline string > templating, like other languages (js, C#, etc). At least some way to > evaluate an expression and format. I'm thinking like in C#: > > $"Price: {price:C2}, Quantity: {quantity}, Discount: {discount:P1}, > Total after discount: {(price * quantity * (1 - discount)):N2}" > > Price is formatted using currency with 2 decimal places, discount is > formatted using percentage and one decimal, and N is a number format > with 2 decimals.
While I can get behind allowing arbitrary expressions for ease of use, the formatting suffixes you suggested effectively replicate what `sprintf` already does for you, just with an "incompatible syntax". In fact for proper number and currency formatting you would likely need intl's MessageFormatter anyways, which already supports those kind of placeholders in a standardized fashion. Best regards Tim Düsterhus

Ilija Tovilo

2 years ago
Hi Peter On Sun, May 19, 2024 at 10:30 AM Peter Stalman <sarkedev@gmail.com> wrote:
> > echo " {A::$static_property} \n"; // doesn't work (unless $static_property is a variable) > echo " {$a::$static_property} \n"; // works > > echo " {A::static_method()} \n"; // doesn't work (just text) > echo " {$a::static_method()} \n"; // works > > echo " {A::constant} \n"; // doesn't work > echo " {$a::constant} \n"; // doesn't work either, but why?
It would be straightforward to allow all expressions that start with a `$` in string interpolation, as I've noticed a couple of years ago [1]. This restriction seems rather arbitrary. I think I held off proposing this because I was planning on proposing a more complete form of string interpolation [2]. However, the backwards-compatible syntax was largely disliked, so I withdrew the RFC. I wasn't particularly fond of introducing more forms of strings (e.g. $"", f"", etc.) to avoid the BC break, because there are already plentiful: * '' * "" * `` (yes, these allow interpolation) * <<<HD ... HD * <<<'HD' ... HD Adding at least the two expected ones ($"" and $<<<HD ... HD) would bump that up to 7 forms. There were also suggestions to extend strings in a more generic way, akin to JavaScripts template strings [3], but I didn't have any use for this myself. Ilija [1] https://github.com/php/php-src/compare/master...iluuu1994:php-src:lift-variable-restriction-for-brace-dollar-string-interpolation [2] https://wiki.php.net/rfc/arbitrary_string_interpolation [3] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

Ilija Tovilo

2 years ago
On Sun, May 19, 2024 at 1:15 PM Ilija Tovilo <tovilo.ilija@gmail.com> wrote:
> > Hi Peter > > On Sun, May 19, 2024 at 10:30 AM Peter Stalman <sarkedev@gmail.com> wrote: > > > > echo " {A::$static_property} \n"; // doesn't work (unless $static_property is a variable) > > echo " {$a::$static_property} \n"; // works > > > > echo " {A::static_method()} \n"; // doesn't work (just text) > > echo " {$a::static_method()} \n"; // works > > > > echo " {A::constant} \n"; // doesn't work > > echo " {$a::constant} \n"; // doesn't work either, but why? > > There were also suggestions to extend strings in a more generic way, > akin to JavaScripts template strings [3], but I didn't have any use > for this myself. > > [3] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
What I actually wanted to reference were "tagged templates": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates Sorry for the confusion. Ilija

Удальцов Валентин

2 years ago
On Sun, May 19, 2024 at 10:30 AM Peter Stalman <sarkedev@gmail.com> wrote:
> Hi Internals, > > Obviously we can't use constants or functions directly in strings using > variable parsing, I assume because it lacks the easily detectable $. > > However, we _can_ use methods because the object variable has the $, which > I assume is the reason methods work and functions don't. > > I feel like it's something that _could_ have been added when dynamic > access of static members support was added in 5.3.0, but maybe it was > overlooked or decided against? Consider: > > ``` > <?php > > $a = new A(); > > echo " {A::$static_property} \n"; // doesn't work (unless $static_property > is a variable) > echo " {$a::$static_property} \n"; // works > > echo " {A::static_method()} \n"; // doesn't work (just text) > echo " {$a::static_method()} \n"; // works > > echo " {A::constant} \n"; // doesn't work > echo " {$a::constant} \n"; // doesn't work either, but why? > > ?> > ``` > > > Also, as a side note, why does this hack below work? It seems like > something that would use `eval()`, but doesn't. Take a look: > > https://3v4l.org/aPCSD > > I found it at the bottom of the manual entry for Strings[1]. Not > something I would use, but it's interesting to see. > > Thanks, > Peter > > [1]: https://www.php.net/manual/en/language.types.string.php#91628 >
Hi, Peter!
> Also, as a side note, why does this hack below work?
It's not a hack. Variables, including callable ones with any arguments are allowed to be interpolated. See another example: https://3v4l.org/BJUvL
-- Regards, Valentin Udaltsov