Thursday, April 11, 2013

Variable Expansion in PHP Strings

Check out the example below. It shows how to expand variables within souble-quoted strings. Single quoted strings do not expand variables in them.

example 1:
<?php
$foo = "bar";

// To print "bar"
echo "{$foo}";

// To print "{bar}"
echo "{{$foo}}";
?>


What will be output of the following php code?

example 2:
<?php
$a = "php";
$php = "is";
$is = "really";
$really = "good";
$good = "language";
echo "This is the TEXT :: {${${${${$a}}}}}";
?>

Answer : language

Explanation : The variables are being expanded within the string, the $a giving "php" and eventually making it to $php resulting to $is and ultimately the value of $good is evaluated and its value gets printed on screen. Checkout some more complex string statements below.

example 3:
<?php
$arr['foo'][1]['bar'][2] = "general";
$general = "PHP is great";
echo "Text is :: ${$arr['foo'][1]['bar'][2]}";
?>


Output :
Text is :: PHP is great

example 4:
<?php
function a()
{
  return "a function";
}
echo "This is {a()}";  /// Does not expand
?>


Output :
This is {a()}

PHP tokenizer looks for a dollar sign ($) inside double quoted strings when to expand.

example 5:
<?php
class a
{
  public function extra()
{
  return "Extra String";
}
}

$aa = new a();
echo "Text is :: {$aa->extra()}";  // This expands
?>


Output :
Text is :: Extra String

example 6:
<?php
echo "Text is :: {$this}";  // Error :: $this undefined
?>


Output :
Text is ::

$this is available when a method is called from within an object context. "this" pseudo-variable is not available in non-OOP structure. Check out some more examples below.

example 7:
<?php
class a
{
  public static $n = 0;
  const method = "concrete";
}
$concrete = "Sample";

echo "Text is :: {a::method}";
// Does not Expand.

echo "Text is :: {${a::method}}";
// But this expands, Output 'Text is :: Sample'
?>


"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." - from php.net. Simple constants are also not expanded within strings. Check out the example below.

example 8:
<?php
define ("fuss", "foo");   
echo "{fuss}"; // Does not expand
?>


Now check some other examples.

example 9:
<?php
$b = 100;
$a = 40 + " {$b} floating point";
echo $a;
?>


Output : 140

example 10:
<?php
function f($s)
{
  echo  $s;
}
$var = "it";
$it  = "is";
$is  = "PHP";

f( <<
<
${${$var}}
EOD
);
?>


Output : PHP


The construct
${${$var}} ultimately evaluates to "$is" . So, the f() function is called with "PHP" as argument. One thing to be noticed here is that, the heredoc ends with "EOD", not "EOD;". Giving a semi-colon would cause a syntax error. 

Another very interesting part is that PHP also allows function calls inside stings. The syntax is a little complex ... this is shown below.

<?php
$john = 'JEFF SMITH';
$young_jeff_smith = 'Mr. Henry Illinois';

print "$john's real name was ${"young_".strtolower(str_replace(" ","_","$john"))}.\n";
?>


The output is : JEFF SMITH's real name was Mr. Henry Illinois.

The print statement above is a little complex and it contains some unnatural parts, however it runs perfectly. This statement also involves function calls inside string. Notice how we have used multiple double quotes inside curly braces without breaking the string construct.

str_replace(" ","_","$john") => This replaces all spaces with underscores in variable $john. This makes the string 'JEFF SMITH' become 'JEFF_SMITH'. Next, the strtolower() function converts it to 'jeff_smith' and finally when it is appended to 'young_', it becomes 'young_jeff_smith'. Now ${young_jeff_smith} can be easily expanded. So, "$john's real name was ${young_jeff_smith}" finally becomes "JEFF SMITH's real name was Mr. Henry Illinois".


Some more examples given below.

<?php
$plum = "sweet";
echo "{${strtolower("PLUM")}}"; // sweet

$p = 'is';
$lop7 = "Cheaper";

// Below line does not expand as '$' is missing
echo "Salt {strtolower('P')}";  // Salt {strtolower('P')} 

echo " ";
echo "{${strtolower('P')}}"; // is
echo " ";

// The below line expands and evaluates to '$lop7'
echo "{${"lop" . strlen("chandan")}}";  // Cheaper
?>

Functions are expanded within string if '$' and curly braces are placed properly.  The last statement ultimately evaluates to "$lop7" which is then searched for a variable with the same name and its value is printed.

No comments: