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

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 Strings1. Not something I would use, but it’s interesting to see.

Thanks,
Peter

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:

Online PHP editor | output for 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]: PHP: Strings - Manual

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

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] Comparing php:master...iluuu1994:lift-variable-restriction-for-brace-dollar-string-interpolation · php/php-src · GitHub

[2] PHP: rfc:arbitrary_string_interpolation

[3] Template literals (Template strings) - JavaScript | MDN

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] Template literals (Template strings) - JavaScript | MDN

What I actually wanted to reference were "tagged templates":

Sorry for the confusion.

Ilija

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 Strings1. Not something I would use, but it’s interesting to see.

Thanks,
Peter

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

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