How to string interpolate output of a method in PHP? [duplicate] - php

PHP supports variable interpolation in double quoted strings, for example,
$s = "foo $bar";
But is it possible to interpolate function call results in the double quoted string?
For example,
$s = "foo {bar()}";
Something like that? It doesn't seem not possible, right?

It is absolutely possible using the string-to-function-name calling technique as Overv's answer indicates. In many trivial substitution cases it reads far better than the alternative syntaxes such as
"<input value='<?php echo 1 + 1 + foo() / bar(); ?>' />"
You need a variable, because the parser expects the $ to be there.
This is where the identity transform works well as a syntactic hack. Just declare an identity function, and assign the name to a variable in scope:
function identity($arg){return $arg;}
$interpolate = "identity";
Then you can pass any valid PHP expression as the function argument:
"<input value='{$interpolate(1 + 1 + foo() / bar() )}' />"
The upside is that you can eliminate a lot of trivial local variables and echo statements.
The downside is that the $interpolate variable falls out of scope, so you would have to repeatedly declare it global inside of functions and methods.

The double quote feature in PHP does not evaluate PHP code, it simply replaces variables with their values. If you want to actually evaluate PHP code dynamically (very dangerous), you should use eval:
eval( "function foo() { bar() }" );
Or if you just want to create a function:
$foo = create_function( "", "bar()" );
$foo();
Only use this if there really is no other option.

Unless interpolation is absolutely necessary (please comment and let me know why), concatenate the function output with the string.
$s = "foo " . bar();
Source: 1.8. Interpolating Functions and Expressions Within Strings

Related

PHP - Difference in creating variable variables with brackets or double dollar signs?

From what I can tell in the PHP Manual, it doesn't seem like there is much difference between defining a variable variable with double brackets or double dollar signs.
$foo = 'hello';
$$foo = 'hi';
echo $hello; // 'hi'
$baz = 'goodbye';
${$baz} = 'bye';
echo $goodbye; // 'bye'
The only difference it mentions in the manual is when using arrays. Is there any other noticeable difference between the two? Which one is better for which situations?
Both versions are basically the same.
The curly braces notation is used in cases where there could be ambiguity:
$foo = 'bar';
$bar = [];
${$foo}[] = 'foobar';
var_dump($bar); // foobar
If you'd omit the braces in the above example, you'd get a fatal error, with the braces, it works fine.
However, I would recommend avoiding dynamic variable names altogether. They are funny to use and may save some space. But in the end, your code will become less readable and you will have trouble debugging.
In this case, there is no difference. It is like using parentheses to group operators, even when they are not necessary.

What does { } do within a string?

$name = "jason";
$p = "hello-{hello2}-$name-{$name}";
echo $p;
output :
hello-{hello2}-jason-jason
Came across some examples of prepared statements and noticed this. If its encompassing a variable, it removes them, otherwise it keeps them. Why is this behavior necessary when
echo "$name";
gets you the same result as
echo "{$name}";
or is it just readability?
It's used as a delimiter for variables in strings. This is necessary in some cases, as PHP's string parser isn't Greedy aand will mis-interpret many common structs.
e.g.
$foo = array();
$foo['bar'] = array();
$foo['bar']['baz'] = 'qux';
echo "Hello $foo[bar][baz]";
will actually print
Hello Array[baz]
Because it's parsed as
echo "Hello ", $foo['bar'], "[baz]";
^ ^ ^
string array string
Using {} forces PHP to consider the array reference as single entity:
echo "Hello, {$foo['bar']['baz']}"; // prints "Hello, qux"
It also helps differentiate ambiguous stuff
$foo = 'bar';
echo "$foos" // undefined variable 'foos'
echo "{$foo}s" // variable containing 'bar' + string 's'
It's something called "complex syntax"
From php.net you can go to Complex (curly) syntax section and see many examples.
Complex (curly) syntax
This isn't called complex because the syntax is complex, but because it allows for the use of complex expressions.
Any scalar variable, array element or object property with a string representation can be included via this syntax. Simply write the expression the same way as it would appear outside the string, and then wrap it in { and }. Since { can not be escaped, this syntax will only be recognised when the $ immediately follows the {. Use {\$ to get a literal {$.
Functions, method calls, static class variables, and class constants inside {$} work since PHP 5. However, the value accessed 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.
It does not necessarily generate the same output:
$name = 'foo';
$names = 'bar';
echo "Output1: $names";
echo "Output2: {$name}s";
Output
Output1: bar
Output2: foos
Also you can access complex structures via the curly syntax like {$foo->bar}.
This syntax is useful when you want to display variable following some string and you don't want any space between them.
Compare the following:
<?php
$name='John';
echo "My name is $nameathan. I'm twenty years old<br />";
echo "My name is {$name}athan. I'm twenty years old<br />";
It will give you result:
Notice: Undefined variable: nameathan in ... on line 5
My name is . I'm twenty years old
My name is Johnathan. I'm twenty years old
For first echo it will generate notice and won't work as expected because PHP doesn't know that you want to use variable $name in the string and not $nameathan. Using curly braces in second case solves the issue.
Of course you can concatenate string this way:
echo "My name is $name"."athan. I'm twenty years old<br />";
and it also solves the issue but if you have many such variables in string it will be much more convenient to use curly braces.

PHP interpolating string for function output

PHP supports variable interpolation in double quoted strings, for example,
$s = "foo $bar";
But is it possible to interpolate function call results in the double quoted string?
For example,
$s = "foo {bar()}";
Something like that? It doesn't seem not possible, right?
It is absolutely possible using the string-to-function-name calling technique as Overv's answer indicates. In many trivial substitution cases it reads far better than the alternative syntaxes such as
"<input value='<?php echo 1 + 1 + foo() / bar(); ?>' />"
You need a variable, because the parser expects the $ to be there.
This is where the identity transform works well as a syntactic hack. Just declare an identity function, and assign the name to a variable in scope:
function identity($arg){return $arg;}
$interpolate = "identity";
Then you can pass any valid PHP expression as the function argument:
"<input value='{$interpolate(1 + 1 + foo() / bar() )}' />"
The upside is that you can eliminate a lot of trivial local variables and echo statements.
The downside is that the $interpolate variable falls out of scope, so you would have to repeatedly declare it global inside of functions and methods.
The double quote feature in PHP does not evaluate PHP code, it simply replaces variables with their values. If you want to actually evaluate PHP code dynamically (very dangerous), you should use eval:
eval( "function foo() { bar() }" );
Or if you just want to create a function:
$foo = create_function( "", "bar()" );
$foo();
Only use this if there really is no other option.
Unless interpolation is absolutely necessary (please comment and let me know why), concatenate the function output with the string.
$s = "foo " . bar();
Source: 1.8. Interpolating Functions and Expressions Within Strings

PHP variable variables in {} symbols

I get the basics of variable variables, but I saw a syntax just know, which bogles my mind a bit.
$this->{$toShow}();
I don't really see what those {} symbols are doing there. Do they have any special meaning?
PHP's variable parser isn't greedy. The {} are used to indicate what should be considered part of a variable reference and what isn't. Consider this:
$arr = array();
$arr[3] = array();
$arr[3][4] = 'Hi there';
echo "$arr[3][4]";
Notice the double quotes. You'd expect this to output Hi there, but you actually end up seeing Array[4]. This is due to the non-greediness of the parser. It will check for only ONE level of array indexing while interpolating variables into the string, so what it really saw was this:
echo $arr[3], "[4]";
But, doing
echo "{$arr[3][4]}";
forces PHP to treat everything inside the braces as a variable reference, and you end up with the expected Hi there.
They tell the parser, where a variable name starts and ends. In this particular case it might not be needed, but consider this example:
$this->$toShow[0]
What should the parser do? Is $toShow an array or $this->$toShow ? In this case, the variable is resolved first and the array index is applied to the resulting property.
So if you actually want to access $toShow[0], you have to write:
$this->{$toShow[0]}
These curly braces can be used to use expressions to specify the variable identifier instead of just a variable’s value:
$var = 'foo';
echo ${$var.'bar'}; // echoes the value of $foobar
echo $$var.'bar'; // echoes the value of $foo concatenated with "bar"
$this->{$toShow}();
Break it down as below:
First this is a object oriented programming style as you got to see $this and ->. Second, {$toShow}() is a method(function) as you can see the () brackets.
So now {$toShow}() should somehow be parsed to a name like 'compute()'. And, $toShow is just a variable which might hold a possible function name. But the question remains, why is {} used around.
The reason is {} brackets substitues the value in the place. To clarify,
$toShow="compute";
so,
{$toShow}(); //is equivalent to compute();
but this is not true:
$toShow(); //this is wrong as a variablename is not a legal function name

Constants inside quotes are not printed?

This prints apple:
define("CONSTANT","apple");
echo CONSTANT;
But this doesn't:
echo "This is a constant: CONSTANT";
Why?
Because "constants inside quotes are not printed". The correct form is:
echo "This is a constant: " . CONSTANT;
The dot is the concatenation operator.
define('QUICK', 'slow');
define('FOX', 'fox');
$K = 'strval';
echo "The {$K(QUICK)} brown {$K(FOX)} jumps over the lazy dog's {$K(BACK)}.";
If you want to include references to variables inside of strings you need to use special syntax. This feature is called string interpolation and is included in most scripting languages.
This page describes the feature in PHP. It appears that constants are not replaced during string interpolation in PHP, so the only way to get the behavior you want is to use the concatenation that Artefacto suggested.
In fact, I just found another post saying as much:
AFAIK, with static variables, one has
the same 'problem' as with constants:
no interpolation possible, just use
temporary variables or concatenation.
Concatenation has been suggested as the only solution here, but that doesn't work when using syntax like:
define("MY_CONSTANT", "some information");
$html = <<< EOS
<p>Some html, **put MY_CONSTANT here**</p>
EOS;
Of course, the above just puts the text 'MY_CONSTANT' in $html.
Other options include:
define a temporary variable to hold the constant:
$myConst = MY_CONSTANT;
$html = <<< EOS
<p>Some html, {$myConst} </p>
EOS;
if there are many constants, you can get an array of them all and use that:
$constants = get_defined_constants();
$html = <<< EOS
<p>Some html, {$constants["MY_CONSTANT"]} </p>
EOS;
Of course, in such a trivially short example, there's no reason to use the <<< operator, but with a longer block of output the above two may be much clearer and easier to maintain than a bunch of string concatenation!
The question was already answered, but I'd like to provide a more generic insight on this.
In double quotes, PHP recognizes anything starting with a $ as a variable to be interpolated. Further more, it considers array and object access ([] and ->) but only up to a single level. E.g. "$foo->bar" interpolates $foo->bar and $foo->bar->baz does the same thing and treats ->baz as a string literally. Also, the quotes in [] must be ommited for string keys. E.g. "$foo[bar]" interpolates $foo['bar'] while "$foo['bar']" is a syntax error. AFAIK, that's it. To get more functionality, you need the "{$...}" syntax.
The $ here is actually a part of the syntax and it doesn't work without it. E.g. "{FOO}" will not interpolate a constant FOO, it's simply a syntax error. However, other than some strange syntactical restrictions, this construct is actually quite strong and may contain any valid PHP expression, as long as it starts with a $ and is an array access, object access, or a function call. (Maybe some other cases are permitted to. Please let me know, if anyone has a better understanding of this.) The most general solution to your problem would be to define something like the following function somewhere in your code base:
$id = function ($x) {
return $x;
}
It's simply the identity function - it returns whatever you give it. It must be defined as an anonymous function, so you can refer to it as $id with the $.
Now you can use this function to interpolate any PHP expression:
echo "{$id(CONSTANTS)}"
echo "{$id($some + $operators - $as . $well)}"
// etc...
Alternative for PHP versions < 5.3 where you can't use anonymous functoins:
class Util {
function id ($x) { return $x; }
}
$u = new Util;
echo "{$u->id(ANY + $expression . $here)}"
// or...
function id ($x) { return $x; };
$id = 'id';
echo "{$id(ANY + $expression . $here)}"
The native interpolation does not support constants. Still not up to PHP 8.2 (and maybe later on). An alternative to echo is to use printf() or sprintf() for getting the interpolation result as string.
const MY_CONSTANT = "foo";
printf("Hello %s bar!", MY_CONSTANT);

Categories