rfc:arbitrary_string_interpolation

PHP RFC: Arbitrary string interpolation

Proposal

PHP has four types of string interpolation. The two most common forms are “$foo” and “{$foo}”. For details on the two other forms of string interpolation see the deprecate ${} string interpolation RFC.

All the current forms of string interpolation are limited to variables or variable chains (array access, properties, method calls, etc). This probably covers 80% of use cases for string interpolation (unverified figure). However, there are times when this is not enough, namely you might want to embed any of the following in your string:

  • Function calls
  • Constants
  • Class constants
  • Static method calls
$world = 'world';
echo "Hello {strtoupper($world)}!";
// Hello {strtoupper(world)}
// :(

This RFC proposes to add a new form for string interpolation that works for arbitrary expressions.

$world = 'world';
echo "Hello {$:strtoupper($world)}!";
// Hello WORLD!
// :)
 
echo "{$:T_PAAMAYIM_NEKUDOTAYIM}";
echo "{$:Foo::class}";
echo "{$:self::doSomething()}";

The proposed syntax works in all cases where existing string interpolation is allowed, namely double quoted strings (“”), heredoc (<<<TXT TXT) and the execution operator (``).

Motivation

Of course, this can already be achieved in two other ways:

  • By creating a temporary local variable
  • By stopping the string and concatenating the value with .

Creating local variables is not a terrible option. It does pollute the variable symbol table a bit and it requires more visual jumping to see what value is being embedded.

Concatenation is a fair bit worse. The quotes and . symbols lead to a symbol soup, and the approach will not work nicely with heredoc at all.

echo <<<TXT
    Hello 
TXT /* <-- Must be on a new line */ . strtoupper('world') . <<<TXT
TXT;

Syntax choice

The primary advantage of the syntax “{$:expr}” is that is it is fully backwards compatible as it leads to a syntax error in PHP 8.1 rather than being interpreted literally. It also looks familiar while being distinctly different from other forms of string interpolation to avoid confusion. The : could be swapped with another character or even white space, but I believe that white space has a bigger chance of leading to confusion.

A different syntax could be chosen with a given BC break.

echo "Hello #{strtoupper('world')}";

This could be mitigated by adding a prefix to the string itself.

echo $"Hello #{strtoupper('world')}";

I think this is unfortunate because:

  • Converting an existing string to $ will potentially alter its behavior and require escaping of other parts of the string (similar to switching from ' to )
  • The prefix will need to work for all existing string types that allow interpolation (, heredoc, execute operator), doubling the types of interpolated string we have

Escaping

Escaping works by adding a backslash \ after the brace {.

echo "{\$:foo}";
// {$:foo}

If you're thinking why not before the {, PHPs existing escaping of \{$foo} could be considered buggy. While it escapes the {}, it also gets printed itself.

$foo = 'bar';
echo "\{$foo}";
// \{bar}

https://3v4l.org/oEWFC

That said, escaping the proposed string interpolation {$: should be very rare in practice.

Backwards incompatible changes

None

Comparison to other languages

Most modern languages have string interpolation that allow arbitrary expressions.

Language Syntax
C# $“x + y = {x + y}”
Dart 'x + y = ${x + y}'
JavaScript `x + y = ${x + y}`
Kotlin “x + y = ${x + y}”
Python f'x + y = {x + y}'
Raku (Perl6) “\$x + \$y = { $x + $y }”
Ruby “x + y = #{x + y}”
Scala s“x + y = ${$x + $y}”
Swift “x + y = \(x + y)”

Credits

Credits to Rowan Tommins (IMSoP) for the syntax suggestion and comparison to other languges.

Vote

Voting starts 2022-xx-x and ends 2022-xx-xx.

As this is a language change, a 2/3 majority is required.

Accept arbitrary string interpolation in PHP 8.2?
Real name Yes No
Final result: 0 0
This poll has been closed.
rfc/arbitrary_string_interpolation.txt · Last modified: 2022/06/25 21:47 by ilutov