rfc:deprecate_dollar_brace_string_interpolation

PHP RFC: Deprecate ${} string interpolation

  • Date: 2021-03-13
  • Author: Ilija Tovilo, tovilo.ilija@gmail.com
  • Status: Draft
  • Target Version: PHP 8.1
  • Implementation: TBD

Proposal

PHP allows embedding variables in strings with double-quotes (") and heredoc in various ways.

1. Directly embedding variables ("$foo")
2. Braces outside the variable ("{$foo}")
3. Braces after the dollar sign ("${foo}")
4. Dynamic variable lookup ("${expr}")

All of these have their pros and cons, but in practice options 3 and 4 are easily confused (both by users and the parser) due to the similar syntax, are strictly less capable than the first two options, and are rarely used in practice. Option 3 is specifically less capable than 2, and option 4 is built on variable-variables with all the complexity and weirdness that brings with it.

This RFC proposes to deprecate options 3 and 4 in PHP 8.1 and remove them in PHP 9.0. That leaves only two string interpolation options: direct (simple variable only) and powerful (the one that does the most now).

Status quo

The first issue is that all four options support different subsets of syntax. That is needlessly confusing, both for the user and for the parser.

Simple variable interpolation

Options 1, 2, and 3 support embedding basic variables. Option 4 has no equivalent here.

$foo = 'foo';
 
var_dump("$foo");
var_dump("{$foo}");
var_dump("${foo}");

Array-offset interpolation

Options 1, 2, and 3 allow accessing an array offset. Unfortunately, the syntax is not consistent.

$foo = ['bar' => 'bar'];
var_dump("$foo[bar]");
 
var_dump("{$foo['bar']}");
var_dump("${foo['bar']}");

Object property interpolation

Only syntax 1 and 2 allow accessing properties.

$foo = (object) ['bar' => 'bar'];
 
var_dump("$foo->bar");
var_dump("{$foo->bar}");

Metehod call interpolation

Only syntax 2 allows calling methods.

class Foo {
    public function bar() {
        return 'bar';
    }
}
 
$foo = new Foo();
var_dump("{$foo->bar()}");

Compound interpolation

Only syntax 2 allows chaining all of the above.

class Bar {
    public function baz() {
        return 'baz';
    }
}
 
$foo = ['bar' => new Bar()];
var_dump("{$foo['bar']->baz()}");

Option 4

PHP has a feature called Variable variables. It allows you to get a variable by name. The name can be a string stored in another variable.

$foo = 'Hello world!';
$bar = 'foo';
var_dump(${$bar});

The same works within strings. This is the option 4 described above.

$foo = 'world!';
$bar = 'foo';
var_dump("Hello ${$bar}");

As you might notice, this syntax clashes with option 3. If the term between the two braces is not compatible with option 3 PHP will interpret it as option 4 which has completely different semantics.

const foo = 'bar';
$foo = 'foo';
$bar = 'bar';
 
var_dump("${foo}");
//> foo
 
var_dump("${(foo)}");
//> bar

The braces switch from option 3 to 4 because braces are not allowed in option 3. This means foo is no longer interpreted as a variable but as a constant, and option 4 will then try to find a local variable by the name of that constant. This is incredibly unintuitive.

Comparison to other languages

A number of other languages use ${foo} style string interpolation, most notably bash and Javascript (in template literals). However, its behavior is different from that in PHP. In PHP, that syntax means variable-variables. In Javascript, it supports arbitrary expressions (making it technically a superset of PHP's existing option 2). In its current form, options 3 and 4 are of limited use, and confusing for users from other nearby languages as they behaves quite differently.

Conclusion

Option 1 offers a simple “base case” for the most common situation and is widely used.

Option 2 offers the most robust syntax currently supported, and is widely used.

Option 3 offers a subset of the functionality of option 2, and is not widely used.

Option 4 offers functionality that is rarely if ever useful, and easily confused with option 3.

For all of the reasons above this RFC proposes to deprecate option 3 and 4 in PHP 8.1 and remove them in PHP 9.

Future scope

Options 1 and 2 are not perfect either. They only allow simple expressions on variables. A different RFC might propose to allow embedding arbitrary expressions into strings.

var_dump($"#{func()}")

If we decide to do that it would make sense to remove the less useful options first to not further add to the confusion, that's what this RFC is trying to achieve.

Vote

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

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

Deprecate ${} string interpolation in PHP 8.1 and remove them in PHP 9.0?
Real name Yes No
Final result: 0 0
This poll has been closed.
rfc/deprecate_dollar_brace_string_interpolation.txt · Last modified: 2021/03/13 18:22 by crell