9

I am trying to understand what is the difference between the two possible syntax variations in complex variable syntax. PHP allows for both variants:

$foo = 'bar';
$bar = "${foo}bar is allowed"; //or
$bar = "{$foo}bar is allowed";

There is no error/warning/notice generated when using either syntax. I have noticed no difference between the two, however PHP manual shows only the {$foo} variant.
Is it wrong to use the other variant? Would it ever cause me any problems?

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • Personally the middle line of your example is misleading, I'd expect it to be interpreted as `$foobar` rather than `barbar` – scrowler Feb 24 '19 at 23:19
  • User comment on the manual entry indicates the `{$..}` is minimally faster, http://php.net/manual/en/language.types.string.php#120160. – user3783243 Feb 24 '19 at 23:27
  • 2
    @Cutwow that's a good link to add but I don't think this is a dupe because the specific case OP is asking about is not addressed (at least not in any depth) – Phil Feb 24 '19 at 23:28
  • @Phil After re-reading the answer in the other post I see where my mistake was. As you mentioned the OP's question is not explained in depth in the other post. I will delete the previous comment of mine. – CootMoon Feb 24 '19 at 23:30
  • @Cutwow still a great reference. Thanks for adding the link. _Edit: this link_ ~ [Curly braces in string in PHP](https://stackoverflow.com/questions/2596837/curly-braces-in-string-in-php) – Phil Feb 24 '19 at 23:31

2 Answers2

12

${...} is a syntax for another purpose. It is used to indirectly reference variable names. Without string interpolation, literal names in curly braces or brackets are written as string literals, thus enclosed in quotes. However, inside interpolation quotes are not used outside curly braces:

$bar = 'baz';

echo $bar , PHP_EOL;
echo ${'bar'} , PHP_EOL;

$arr = ['a' => 1, 'b' => ['x' => 'The X marks the point.']];
echo $arr['a'] , PHP_EOL;

// interpolation:
echo "$arr[a] / {$arr['a']}" , PHP_EOL;

Instead of literals you can use functions as well:

function foo(){return "bar";}

// Here we use the function return value as variable name.
// We need braces since without them the variable `$foo` would be expected
// to contain a callable

echo ${foo()} , PHP_EOL;

When interpolating, you need to enclose into curly braces only when the expression otherwise would be ambiguous:

echo "$arr[b][x]", PHP_EOL;       // "Array[x]"     
echo "{$arr['b']['x']}", PHP_EOL; // "The X marks the point."

Now we understand that ${...} is a simple interpolation "without braces" similar to "$arr[a]" since the curly braces are just for indirect varable name referencing. We can enclose this into curly braces nevertheless.

Interpolated function call forming the variable name:

echo "${foo()} / {${foo()}}", PHP_EOL;
// "baz / baz" since foo() returns 'bar' and $bar contains 'baz'.

Again, "${bar}" is equivalent to ${'bar'}, in curly braces: "{${'bar'}}".


As asked in comments,

there is another curly brace syntax to reference array keys.

$someIdentifier{'key'}

This is just an alternative syntax to PHP's common array syntax $array['key'].

In opposit to the latter, on indirect variable name references the curly braces follow immediately after the $ or the object member operator ->. To make it even more cryptic we can combine both:

$bar['baz'] = 'array item';
echo ${'ba' . 'r'}{'ba'.'z'};

which is equivalent to echo $bar['baz'];

Really weird in PHP's string interpolation: "${bar}" is valid and "${'bar'}" as well but not "$array['key']", "$array[key]" is valid instead, but both, "$array{key}" and "$array{'key'}", do not work at all.

Conclusion

It should be made a habit to use braced interpolation syntax all the time. Braced array key syntax should be avoided at all.
Always use:

"{$varname} {$array['key']} {${funcname().'_array'}['key']}"

See also PHP documentation:

(to distinguish from)

  • Variable variables (also known as indirect variable name referencing)

  • Accessing array elements

    Both square brackets and curly braces can be used interchangeably for accessing array elements (e.g. $array[42] and $array{42} will both do the same thing in the example above).

Pinke Helga
  • 6,378
  • 2
  • 22
  • 42
  • Are you saying that `$bar['ba'.'z']` is equivalent to `$bar{'ba'.'z'}`? Because `"$bar[baz]"` is not equivalent to `"$bar{baz}"`. Is the curly syntax documented in the PHP Manual anywhere? – Dharman Feb 25 '19 at 20:51
  • Also I have found this article on the internet, but it is no official information: https://cowburn.info/2008/01/12/php-vars-curly-braces/ – Dharman Feb 25 '19 at 20:56
  • 1
    @Dharman No, that's a complete different topic, I did not mean, however, yes, your examples actually are equivalent. `$array{'key'}` is just an alternative syntax to the PHP's common one `$array['key']`. [array syntax](http://php.net/manual/en/language.types.array.php#language.types.array.syntax.accessing) in opposit to indirect referencing or "variable variables" as called in PHP doc: http://php.net/manual/en/language.variables.variable.php – Pinke Helga Feb 25 '19 at 21:18
  • @Dharman I've extended my explainations in the hope it could reduce confusions. – Pinke Helga Feb 25 '19 at 21:30
5

It seems PHP is able to expand either format to reference the correct value in almost all cases.

The only difference I can find is when accessing object properties, eg

$foo = (object) ['a' => 'bar'];
echo "{$foo->a}bar"; // barbar
echo "${foo->a}bar"; // Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR)

So with that in mind, I would avoid using ${...}.

See also Curly braces in string in PHP for more reference material on PHP strings.

Phil
  • 157,677
  • 23
  • 242
  • 245
  • 3
    `"${...}"` is *not* the syntax for braced interpolation, but only `"{$...}"`. It's an indirect variable name reference. See my answer for further details. The reason for less performance is the overhead of dynamic referencing. – Pinke Helga Feb 25 '19 at 01:36
  • This is good, but only empirical evidence. I am looking for some hard facts or explanations which would prove it safe or not. I don't want to discover in far future that the syntax I used was deprecated or misused. – Dharman Feb 25 '19 at 20:39