diff --git a/appendices/tokens.xml b/appendices/tokens.xml index dfe206d1ade8..5b283399c0a2 100644 --- a/appendices/tokens.xml +++ b/appendices/tokens.xml @@ -204,8 +204,10 @@ defined('T_FN') || define('T_FN', 10001); T_CURLY_OPEN {$ - complex - variable parsed syntax + + advanced + variable string interpolation + T_DEC @@ -255,8 +257,10 @@ defined('T_FN') || define('T_FN', 10001); T_DOLLAR_OPEN_CURLY_BRACES ${ - complex - variable parsed syntax + + basic + variable string interpolation + T_DOUBLE_ARROW @@ -799,8 +803,10 @@ defined('T_FN') || define('T_FN', 10001); T_STRING_VARNAME "${a - complex - variable parsed syntax + + variable variables + to interpolate in a string + T_SWITCH diff --git a/language/types/string.xml b/language/types/string.xml index 53c4c356b310..f4955a7a1d28 100644 --- a/language/types/string.xml +++ b/language/types/string.xml @@ -199,7 +199,7 @@ echo 'Variables do not $expand $either'; The most important feature of double-quoted strings is the fact that variable names will be expanded. See - string parsing for + string interpolation for details. @@ -592,7 +592,7 @@ FOOBAR; Nowdocs are to single-quoted strings what heredocs are to double-quoted strings. A nowdoc is specified similarly to a heredoc, but no - parsing is done inside a nowdoc. The construct is ideal for + String interpolation is done inside a nowdoc. The construct is ideal for embedding PHP code or other large blocks of text without the need for escaping. It shares some features in common with the SGML <![CDATA[ ]]> construct, in that it declares a @@ -684,37 +684,29 @@ EOT; - Variable parsing + String interpolation When a string is specified in double quotes or with heredoc, - variables are parsed within it. + variables can be substituted within it. There are two types of syntax: a - simple one and a - complex one. - The simple syntax is the most common and convenient. It provides a way to + basic one and an + advanced one. + The basic syntax is the most common and convenient. It provides a way to embed a variable, an array value, or an object property in a string with a minimum of effort. - - The complex syntax can be recognised by the - curly braces surrounding the expression. - - - - Simple syntax - + + Basic syntax - If a dollar sign ($) is encountered, the parser will - greedily take as many tokens as possible to form a valid variable name. - Enclose the variable name in curly braces to explicitly specify the end of - the name. + If a dollar sign ($) is encountered, the characters + that follow it which can be used in a variable name will be interpreted + as such and substituted. - ]]> @@ -736,43 +722,131 @@ echo "He drank some juice made of {$juice}s."; - Similarly, an array index or an object property - can be parsed. With array indices, the closing square bracket - (]) marks the end of the index. The same rules apply to - object properties as to simple variables. + Formally, the structure for the basic variable substitution syntax is + as follows: + + +Simple syntax example - +offset-or-property:: + offset-in-string + | property-in-string + +offset-in-string:: + [ name ] + | [ variable-name ] + | [ integer-literal ] + +property-in-string:: + -> name + +variable-name:: + $ name + +name:: + [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]* + +]]> + + + + + + The ${ expression } syntax is deprecated as of + PHP 8.2.0, as it can be interpreted as + variable variables: + + "purple"); +const foo = 'bar'; +$foo = 'foo'; +$bar = 'bar'; +var_dump("${foo}"); +var_dump("${(foo)}"); +?> +]]> + + &example.outputs.82; + + + + &example.outputs; + + + + + The advanced + string interpolation syntax should be used instead. + + + + + + If it is not possible to form a valid name the dollar sign remains + as verbatim in the string: + + + + +]]> + + &example.outputs; + + + + + -echo "He drank some $juices[0] juice.".PHP_EOL; -echo "He drank some $juices[1] juice.".PHP_EOL; -echo "He drank some $juices[koolaid1] juice.".PHP_EOL; + + Interpolating the value of the first dimension of an array or property + + "purple"); -class people { - public $john = "John Smith"; - public $jane = "Jane Smith"; - public $robert = "Robert Paulsen"; +echo "He drank some $juices[0] juice."; +echo PHP_EOL; +echo "He drank some $juices[1] juice."; +echo PHP_EOL; +echo "He drank some $juices[string_key] juice."; +echo PHP_EOL; - public $smith = "Smith"; +class A { + public $s = "string"; } -$people = new people(); +$o = new A(); -echo "$people->john drank some $juices[0] juice.".PHP_EOL; -echo "$people->john then said hello to $people->jane.".PHP_EOL; -echo "$people->john's wife greeted $people->robert.".PHP_EOL; -echo "$people->robert greeted the two $people->smiths."; // Won't work +echo "Object value: $o->s."; ?> ]]> @@ -782,14 +856,20 @@ echo "$people->robert greeted the two $people->smiths."; // Won't work He drank some apple juice. He drank some orange juice. He drank some purple juice. -John Smith drank some apple juice. -John Smith then said hello to Jane Smith. -John Smith's wife greeted Robert Paulsen. -Robert Paulsen greeted the two . +Object value: string. ]]> + + + The array key must be unquoted, and it is therefore not possible to + refer to a constant as a key with the basic syntax. Use the + advanced + syntax instead. + + + As of PHP 7.1.0 also negative numeric indices are supported. @@ -816,20 +896,23 @@ Changing the character at index -3 to o gives strong. - For anything more complex, you should use the complex syntax. + For anything more complex, the + advanced + syntax must be used. - - Complex (curly) syntax + + Advanced (curly) syntax - This isn't called complex because the syntax is complex, but because it - allows for the use of complex expressions. + The advanced syntax permits the interpolation of + variables with arbitrary accessors. - Any scalar variable, array element or object property with a + Any scalar variable, array element or object property + (static or not) with a string representation can be included via this syntax. The expression is written the same way as it would appear outside the string, and then wrapped in { and @@ -843,10 +926,18 @@ Changing the character at index -3 to o gives strong. 'Indexed value', + 'const-key' => 'Key with minus sign', + 'foo' => ['foo1', 'foo2', 'foo3'] +]; // Won't work, outputs: This is { fantastic} echo "This is { $great}"; @@ -854,8 +945,16 @@ echo "This is { $great}"; // Works, outputs: This is fantastic echo "This is {$great}"; +class Square { + public $width; + + public function __construct(int $width) { $this->width = $width; } +} + +$square = new Square(5); + // Works -echo "This square is {$square->width}00 centimeters broad."; +echo "This square is {$square->width}00 centimeters wide."; // Works, quoted keys only work using the curly brace syntax @@ -865,29 +964,15 @@ echo "This works: {$arr['key']}"; // Works echo "This works: {$arr[4][3]}"; -// This is wrong for the same reason as $foo[bar] is wrong outside a string. -// PHP first looks for a constant named foo, and throws an error if not found. -// If the constant is found, its value (and not 'foo' itself) would be used -// for the array index. -echo "This is wrong: {$arr[foo][3]}"; +echo "This works: {$arr[DATA_KEY]}"; -// Works. When using multi-dimensional arrays, always use braces around arrays +// When using multidimensional arrays, always use braces around arrays // when inside of strings echo "This works: {$arr['foo'][3]}"; -// Works. -echo "This works: " . $arr['foo'][3]; - -echo "This works too: {$obj->values[3]->name}"; - -echo "This is the value of the var named $name: {${$name}}"; +echo "This works: {$obj->values[3]->name}"; -echo "This is the value of the var named by the return value of getName(): {${getName()}}"; - -echo "This is the value of the var named by the return value of \$object->getName(): {${$object->getName()}}"; - -// Won't work, outputs: This is the return value of getName(): {getName()} -echo "This is the return value of getName(): {getName()}"; +echo "This works: {$obj->$staticProp}"; // Won't work, outputs: C:\folder\{fantastic}.txt echo "C:\folder\{$great}.txt" @@ -895,82 +980,16 @@ echo "C:\folder\{$great}.txt" echo "C:\\folder\\{$great}.txt" ?> ]]> - - - It is also possible to access class properties using variables - within strings using this syntax. - - - - -$bar}\n"; -echo "{$foo->{$baz[1]}}\n"; -?> -]]> - - &example.outputs; - - - - - - - The value accessed from functions, method calls, static class variables, - and class constants inside - {$} will be interpreted as the name - of a variable in the scope in which the string is defined. Using - single curly braces ({}) will not work for - accessing the return values of functions or methods or the - values of class constants or static class variables. - + + As this syntax allows arbitrary expressions it is possible to use + variable variables + within the advanced syntax. + - - - - -]]> - - -