Files
archived-php-langspec/tests/variables/variable_variables.phpt
2018-09-21 02:44:25 +02:00

267 lines
5.4 KiB
PHP

--TEST--
PHP Spec test generated from ./variables/variable_variables.php
--FILE--
<?php
/*
+-------------------------------------------------------------+
| Copyright (c) 2014 Facebook, Inc. (http://www.facebook.com) |
+-------------------------------------------------------------+
*/
error_reporting(-1);
///*
echo "================== simple cases ====================\n";
$color = "red";
echo "\$color = $color\n";
$$color = 123; // 2 consecutive $s
echo "\$red = $red\n"; // ==> $red = 123
var_dump($$color);
echo "================== multiple expansion ====================\n";
$x = 'ab';
$ab = 'fg';
$fg = 'xy';
$$$$x = 'Hello'; // looks like a unary operator, and associates R->L
//$$$($x) = 'Hello'; // However, CAN'T use grouping parens to document that!!!
echo "\$xy = $xy\n"; // ==> $xy = Hello
$ // can have arbitrary white space separators
$
$ $x = 'Hello';
echo "\$xy = $xy\n";
${${${$x}}} = 'Hello';
echo "\$xy = $xy\n";
var_dump($x);
var_dump($ $x);
var_dump($ $ $x);
var_dump($ $ $ $x);
//*/
///*
echo "================== Using non-variable operands to $ ====================\n";
const CON = 'v';
//$CON = 5; // seen as 1 token ($CON), not as $ and CON
//$ CON = 5; // syntax error, unexpected 'CON' (T_STRING),
// expecting variable (T_VARIABLE) or '$'
// Without the {}, the operand of $ must begin with a variable name (which
// excludes constants) // or another $
//*/
///*
echo "================== Use various scalar types as $'s operand ====================\n";
// $'s operand can be a value of any scalar type, but NOT a literal
// string operand
$v1 = 'abc';
$$v1 = '$v1 = \'abc\'';
echo "\$abc = $abc\n";
var_dump($$v1);
// int operand
$v2 = 3;
$$v2 = '$v2 = 3';
var_dump($$v2);
${$v2} = '$v2 = 3';
var_dump(${$v2});
//$3 = '$v2 = 3';
$ { 3 } = '$v2 = 3';
var_dump(${3});
// float operand
$v3 = 9.543;
$$v3 = '$v3 = 9.543';
var_dump($$v3);
// bool operand
$v4 = TRUE;
$$v4 = '$v4 = TRUE';
var_dump($$v4);
$v5 = FALSE;
$$v5 = '$v5 = FALSE';
var_dump($$v5);
// null operand
$v6 = NULL;
$$v6 = '$v6 = NULL';
var_dump($$v6);
//var_dump($GLOBALS);
function f()
{
// the following work, but the name $'abc' is created in the local scope;
// it certainly isn't in the Globals array. However, given the global declaration,
// the name $'3' does designated the global by that name.
$v11 = 'abc';
$$v11 = '$v11 = \'abc\'';
echo "\$abc = $abc\n";
var_dump($$v11);
global ${3};
$v12 = 3;
$$v12 = '$v12 = 3'; // changes the global
var_dump($$v12);
}
f();
//var_dump($GLOBALS);
//*/
///*
echo "================== complex cases, [] ====================\n";
$v = array(10, 20);
$a = 'v';
$$a[0] = 5;
var_dump($v);
unset($v, $a);
$v = array(10, 20);
$a = 'v';
${$a[0]} = 5;
var_dump($v);
unset($v, $a);
$v = array(10, 20);
$a = 'v';
${$a}[0] = 5;
var_dump($v);
unset($v, $a);
//*/
class C1
{
public static $pr1 = 'v';
public $pr2;
public function __toString()
{
return 'w';
}
}
///*
echo "================== complex cases, :: ====================\n";
var_dump(C1::$pr1);
${C1::$pr1} = 5; // okay with {}
//$C1::$pr1 = 5; // error: Undefined variable: C1, as longest token that can be formed
// is $C1
//$ C1::$pr1 = 5; // insert space so sees 2 tokens: $ and C1. error: syntax error,
// unexpected 'C1' (T_STRING), expecting variable (T_VARIABLE) or '$'
// Doesn't seem to accept a qualified name here (which would exclude a
// namespace prefix as well)
var_dump($v);
unset($v);
//*/
///*
echo "================== complex cases, -> ====================\n";
$c1 = new C1;
$c1->pr2 = 'v';
var_dump($c1->pr2);
var_dump($c1);
$$c1->pr2 = 6; // $w => stdClass { ["pr2"]=>int(6) }
//var_dump($GLOBALS);
${$c1}->pr2 = 7; // $w => stdClass { ["pr2"]=>int(7) }
//var_dump($GLOBALS);
// The 2 cases above are equivalent. Here's what's happening:
// $c1 is converted to a string via __toString, which gives 'w'.
// The designated variable becomes $w, which does not exist, so it looks like
// it has a value of NULL. Then, when the -> is applied, we get a instance of stdClass.
// The problem then is that the $ operator takes precedence over the ->, which wasn't
// what I expected.
${$c1->pr2} = 8; // $v = 8
//var_dump($GLOBALS);
unset($v, $w);
//*/
///*
echo "----------------------\n";
function ff() { return "xxx"; }
$res = ff();
$$res = 777;
echo "\$xxx = $xxx\n";
//*/
--EXPECTF--
================== simple cases ====================
$color = red
$red = 123
int(123)
================== multiple expansion ====================
$xy = Hello
$xy = Hello
$xy = Hello
string(2) "ab"
string(2) "fg"
string(2) "xy"
string(5) "Hello"
================== Using non-variable operands to $ ====================
================== Use various scalar types as $'s operand ====================
$abc = $v1 = 'abc'
string(11) "$v1 = 'abc'"
string(7) "$v2 = 3"
string(7) "$v2 = 3"
string(7) "$v2 = 3"
string(11) "$v3 = 9.543"
string(10) "$v4 = TRUE"
string(11) "$v5 = FALSE"
string(10) "$v6 = NULL"
$abc = $v11 = 'abc'
string(12) "$v11 = 'abc'"
string(8) "$v12 = 3"
================== complex cases, [] ====================
array(2) {
[0]=>
int(5)
[1]=>
int(20)
}
int(5)
array(2) {
[0]=>
int(5)
[1]=>
int(20)
}
================== complex cases, :: ====================
string(1) "v"
int(5)
================== complex cases, -> ====================
string(1) "v"
object(C1)#1 (1) {
["pr2"]=>
string(1) "v"
}
Warning: Creating default object from empty value in %s/variables/variable_variables.php on line 183
----------------------
$xxx = 777