Using array value with index as Variable Variable - php

The title may be a little confusing. This is my problem:
I know you can hold a variable name in another variable and then read the content of the first variable. This is what I mean:
$variable = "hello"
$variableholder = 'variable'
echo $$variableholder;
That would print: "hello". Now, I've got a problem with this:
$somearray = array("name"=>"hello");
$variableholder = "somearray['name']"; //or $variableholder = 'somearray[\'name\']';
echo $$variableholder;
That gives me a PHP error (it says $somearray['name'] is an undefined variable). Can you tell me if this is possible and I'm doing something wrong; or this if this is plain impossible, can you give me another solution to do something similar?
Thanks in advance.

For the moment, I could only think of something like this:
<?php
// literal are simple
$literal = "Hello";
$vv = "literal";
echo $$vv . "\n";
// prints "Hello"
// for containers it's not so simple anymore
$container = array("Hello" => "World");
$vv = "container";
$reniatnoc = $$vv;
echo $reniatnoc["Hello"] . "\n";
// prints "World"
?>
The problem here is that (quoting from php: access array value on the fly):
the Grammar of the PHP language only allows subscript notation on the end of variable expressions and not expressions in general, which is how it works in most other languages.
Would PHP allow the subscript notation anywhere, one could write this more dense as
echo $$vv["Hello"]
Side note: I guess using variable variables isn't that sane to use in production.

How about this? (NOTE: variable variables are as bad as goto)
$variablename = 'array';
$key = 'index';
echo $$variablename[$key];

Related

Add two $row together in one php echo

I'm not even sure if what I am trying to do is possible, I have a simple php echo line as below..
<?php echo $T1R[0]['Site']; ?>
This works well but I want to make the "1" in the $T1R to be fluid, is it possible to do something like ..
<?php echo $T + '$row_ColNumC['ColNaumNo']' + R[0]['Site']; ?>
Where the 1 is replaced with the content of ColNaumNo i.e. the returned result might be..
<?php echo $T32R[0]['Site']; ?>
It is possible in PHP. The concept is called "variable variables".
The idea is simple: you generate the variable name you want to use and store it in another variable:
$name = 'T'.$row_ColNumC['ColNaumNo'].'R';
Pay attention to the string concatenation operator. PHP uses a dot (.) for this, not the plus sign (+).
If the value of $row_ColNumc['ColNaumNo'] is 32 then the value stored in variable $name is 'T32R';
You can then prepend the variable $name with an extra $ to use it as the name of another variable (indirection). The code echo($$name); prints the content of variable $T32R (if any).
If the variable $T32R stores an array then the syntax $$name[0] is ambiguous and the parser needs a hint to interpret it. It is well explained in the documentation page (of the variable variables):
In order to use variable variables with arrays, you have to resolve an ambiguity problem. That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable. The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.
You can do like this
$T1R[0]['Site'] = "test";
$c = 1;
$a = "T".$c."R";
$b = $$a;
echo "<pre>";
print_r($b[0]['Site']);
Or more simpler like this
$T1R[0]['Site'] = "test";
$c = 1;
$a = "T".$c."R";
echo "<pre>";
print_r(${$a}[0]['Site']);

PHP object properties

I'm new to OOP in PHP and I find the difference between the following two expressions difficult to understand.
$object->$foo;
$object->foo;
Maybe it's my fault, but I could not find the relevant part in the manual.
The first call $obj->$foo is using a so called variable variable. Check this:
class A {
public $foo = 1;
}
$a = new A();
$foo = 'foo';
// now you can use both
echo $a->$foo;
echo $a->foo;
Follow the manual about variable variables
Well, in order to fully understand the somewhat odd-looking $object->$foo, you should understand two things about PHP:
Variable names
Most of the time variables in PHP are quite straight-forward. They begin with a $ sign, have one [a-zA-Z_] character, and then any amount of [a-z-A-Z0-9_] characters. Examples include:
$var = 'Abcdef';
$_GET = [];
$a1 = 123;
// And so on...
Now, PHP variables can actually be named pretty much anything, as long as the name is, or can be cast to, a scalar type. The way you name a variable with anything is to use curly braces ({}), like this:
${null} = 'It works'; echo ${null};
${false} = 'It works'; echo ${false};
${'!'} = 'It works'; echo ${'!'};
// Slightly weirder...
${(int)trim(' 5 ')} = 'It works'; echo ${5};
${implode(['a','b','c'])} = 'It works'; echo $abc;
Important: Just because you can do this does not mean you should, however. It is mostly just an oddity of PHP that you can do this.
Variable variables
A somewhat convoluted explanation: A variable variable is a variable that is accessed using a variable name.
A much easier way to understand variable variables is to use what we just learning about variable names in PHP. Take this example:
${"abc"} = 'Abc...';
echo $abc;
We create a variable using the string, "abc", which can also be accessed using $abc.
Now, there is no reason (or rule) that says it has to be a string.... it can also be a variable:
$abc = 'Abc...';
$varName = 'abc';
echo ${$varName}; // echo $abc
That is basically a variable variable. "Real" variable variables just do not use the curly braces:
$abc = 'Abc...';
$varName = 'abc';
echo $$varName; // echo $abc
As for the question
In the question the $object->$foo thing is basically just an "object variable variable", if you like
$object = new stdClass;
$object->abc = 'The alphabet!';
$foo = 'abc';
echo $object->$foo;
echo $object->{$foo}; // The same
echo $object->{'abc'}; // The same
Object variable variables can be somewhat useful, but they are rarely necessary. Using an associative array is usually a better choice.

Dynamically created Variables in PHP produce occasionally names like "_GET" or "_POST" instead of the variable names

I have a function from which I call many different variables, and produce another (dynamically created) return variable.
All good. (I explain my Problem below this PHP 5.3 example)
function showArrayIntersection($ar1, $ar2) {
$dynamicName = array_search($ar1, $GLOBALS) . '_' . array_search($ar2, $GLOBALS);
global ${$dynamicName};
${$dynamicName} = implode(array_values(array_intersect($ar1, $ar2)));
}
$Bankers = [6,7,0,6,5,6,2]; // `[]` is equivalent to `array()` introduced in PHP 5.4
$Bond = [6,7,0,5,0];
$Politicians = [4,6,1,6,4,6,3];
$James = [0,1,0,3,7];
showArrayIntersection($James, $Bond);
showArrayIntersection($Bankers, $Politicians);
echo "Moneysystem: $Bankers_Politicians\n";
echo "Moneypenny : $James_Bond\n";
Output:
Moneysystem: 666
Moneypenny : 007
This works most of the time well, but sometimes only instead of a variable name like $James_Bond I get a variable name like POST_POST or GET_GET, meaning instead of the name James or Bond PHP returns either a "_GET" or a "_POST".
Since AbraCadaver asked full of solicitousness: "What in the world are you doing?"
here my solution and explanation:
Einacio: I coudn't create the names on the fly because the already arrive from a first function dynamically, so the actual variable name is not the true name.
And AbraCadaver pointed out that array_search() does not accept an array; unfortunately for sake of brevity I omitted that I pass on as a first argument not an array but another dynamic created variable from the root - I didn't want to make it too complicated, but basically it works like this:
function processUsers ($userName , $request2send ){
global ${$user.'_'.$request2send};
$url2send = "http...?request=".$request2send ;
...
$returnedValue = receivedDataArray ();//example elvis ([0] => Presley );
${$user.'_'.$request2send} = $returnedValue;
}
--- now Now I get the value of the function in the root ---
$firstValue = processUsers ("cuteAnimal" , "getName");
// returns: $cuteAnimal_getName = "Mouse"
and
$secondValue = processUsers ("actorRourke" , "getFirstName");
// returns: $actorRourke_getFirstName = "Mickey";
And now the bummer - a second function which needs the first one to be completed:
function combineValues ($firstValue , $secondValue ){
global ${$firstValue.'AND'.$secondValue};
${$firstValue.'_'.$secondValue} = $firstValue." ".$secondValue;
}
// returnes $actorRourke_getFirstNameANDcuteAnimal_getName = "Mickey Mouse";
Of course the second function is much more complicated and requires first to be completed,
but I hope you can understand now that it is not an array directly which I passed on but dynamic variable names which I could not just use as "firstValue" but I needed the name "actorRourke_getFirstName".
So AbraCadaver's suggestion to use $GLOBALS[..] did not work for me since it requires arrays.
However: Thanks for all your help and I hope I could now explain the issue to you.
Argument 1 for array_search() does not accept an array.
print_r($GLOBALS); will show the empty $_GET and $_POST arrays.
What in the world are you doing?
To go with Einacio:
function showArrayIntersection($ar1, $ar2) {
$GLOBALS[$ar1 . '_' . $ar2] = implode(array_intersect($GLOBALS[$ar1], $GLOBALS[$ar2]));
}
showArrayIntersection('James', 'Bond');
echo "Moneypenny : $James_Bond\n";
You could check to make sure they exist of course isset().
how about just using the names of the variables? it would also avoid value conflicts
function showArrayIntersection($ar1, $ar2) {
$dynamicName = $ar1 . '_' . $ar2;
global ${$dynamicName};
${$dynamicName} = implode(array_values(array_intersect($_GLOBALS[$ar1], $_GLOBALS[$ar2])));
}
$Bankers = [6,7,0,6,5,6,2]; // `[]` is equivalent to `array()` introduced in PHP 5.4
$Bond = [6,7,0,5,0];
$Politicians = [4,6,1,6,4,6,3];
$James = [0,1,0,3,7];
showArrayIntersection('James', 'Bond');
showArrayIntersection('Bankers', 'Politicians');
echo "Moneysystem: $Bankers_Politicians\n";
echo "Moneypenny : $James_Bond\n";

Assigning array() before using a variable like array

I tried to find a proper and explanatory title but I couldn't and I will try to explain what I am asking here:
Normally if you don't assign an empty array to a variable, you can start assign values to indexes like this:
$hello["world"] = "Hello World";
...
echo $hello["world"];
but I always encounter such definition:
$hello = array() //assigning an empty array first
$hello["hello"] = "World";
...
echo $hello["hello"];
Why is it used a lot. Is there a performance gain or something with the second one?
Thanks.
Two reasons:
Better readability (you know the array is initialized at this point)
Security - when running on a system with register_globals enabled a user could add e.g. hello[moo]=something to the query string and the array would already be initialized with this. $hello = array(); overwrites this value though since a new array is created.
Initializing your variables is good practice.
Take for example this:
$foo = 'bar';
// 10 lines and 1 year later
$foo['baz'] = 'test';
Congratulations, you now have the string "tar".
This may happen accidentally and introduce needless bugs. It gets even worse with conditional variable creation. It's avoided easily by getting into the good habit of explicitly initializing your variables.
$hello = array();
if(someConditionIsTrue){
$hello["world"] = "Hello World";
}
foreach($hello as $val){ // this will not give you any error or warning.
echo $val;
}
But
if(someConditionIsTrue){
$hello["world"] = "Hello World";
}
foreach($hello as $val){ // this will give you error .
echo $val;
}
If I remember correctly, the first one will produce a warning by PHP if you have error_reporting as E_ALL. You should always use the second method because it explicitly initialises a new array. If you are looking through code and out of nowhere see $hello["hello"] but cannot recall seeing any reference to $hello before, it would be confusing.
The same will happen if you do $hello[] = "World", a warning will be displayed

Is there a way to get the name of a variable? PHP - Reflection

I know this is not exactly reflection, but kind of.
I want to make a debug function that gets a variable and prints a var_dump and the variable name.
Of course, when the programmer writes a call to the function, they already know the variable's name, so they could write something like:
debug( $myvar, 'myvar' );
But I want it to be quick and easy to write, just the function name, the variable, and voilĂ  !
debug( $myvar ); // quicker and easier :)
You can do it by converting the variable to a key/value set before passing it to the function.
function varName($theVar) {
$variableName = key($theVar);
$variableValue = $theVar[$variableName];
echo ('The name of the variable used in the function call was '.$variableName.'<br />');
echo ('The value of the variable used in the function call was '.$variableValue.'<br />');
}
$myVar = 'abc';
varName(compact('myVar'));
Though I don't recommend creating a reference to a nameless variable, function varName(&$theVar) works too.
Since compact() takes the variable name as a string rather than the actual variable, iterating over a list of variable names should be easy.
As to why you would want to do this -- don't ask me but it seems like a lot of people ask the question so here's my solution.
I know I'm answering a 4 year old question but what the hell...
compact() might help you is your friend here!
I made a similar function to quickly dump out info on a few chosen variables into a log for debugging errors and it goes something like this:
function vlog() {
$args = func_get_args();
foreach ($args as $arg) {
global ${$arg};
}
return json_encode(compact($args));
}
I found JSON to be the cleanest and most readable form for these dumps for my logs but you could also use something like print_r() or var_export().
This is how I use it:
$foo = 'Elvis';
$bar = 42;
$obj = new SomeFancyObject();
log('Something went wrong! vars='.vlog('foo', 'bar', 'obj'));
And this would print out like this to the logs:
Something went wrong! vars={"foo":"Elvis","bar":42,"obj":{"nestedProperty1":1, "nestedProperty2":"etc."}}
Word of warning though: This will only work for variables declared in the global scope (so not inside functions or classes. In there you need to evoke compact() directly so it has access to that scope, but that's not really that big of a deal since this vlog() is basically just a shortcut for json_encode(compact('foo', 'bar', 'obj')), saving me 16 keystrokes each time I need it.
Nope, not possible. Sorry.
Not elegantly... BUT YOU COULD FAKE IT!
1) Drink enough to convince yourself this is a good idea (it'll take a lot)
2) Replace all your variables with variable variables:
$a = 10
//becomes
$a = '0a';
$$a = 10;
3) Reference $$a in all your code.
4) When you need to print the variable, print $a and strip out the leading 0.
Addendum: Only do this if you are
Never showing this code to anyone
Never need to change or maintain this code
Are crazy
Not doing this for a job
Look, just never do this, it is a joke
I know this is very very late, but i did it in a different way.
It might honestly be a bit bad for performance, but since it's for debugging it shouldn't be a problem.
I read the file where the function is called, on the line it was called and I cut out the variable name.
function dump($str){
// Get the caller with debug backtrace
$bt = debug_backtrace();
$caller = array_shift($bt);
// Put the file where the function was called in an array, split by lines
$readFileStr = file($caller['file']);
// Read the specific line where the function was called
$lineStr = $readFileStr[$caller['line'] -1];
// Get the variable name (including $) by taking the string between '(' and ')'
$regularOutput = preg_match('/\((.*?)\)/', $lineStr, $output);
$variableName = $output[1];
// echo the var name and in which file and line it was called
echo "var: " . $variableName . " dumped in file: " . $caller['file'] . ' on line: ' . $caller['line'] . '<br>';
// dump the given variable
echo '<pre>' . var_export($str, true) . '</pre>';
}
i've had the same thought before, but if you really think about it, you'll see why this is impossible... presumably your debug function will defined like this: function debug($someVar) { } and there's no way for it to know the original variable was called $myvar.
The absolute best you could do would be to look at something like get_defined_vars() or $_GLOBALS (if it were a global for some reason) and loop through that to find something which matches the value of your variable. This is a very hacky and not very reliable method though. Your original method is the most efficient way.
No, the closer you will get is with get_defined_vars().
EDIT: I was wrong, after reading the user comments on get_defined_vars() it's possible with a little hack:
function ev($variable){
foreach($GLOBALS as $key => $value){
if($variable===$value){
echo '<p>$'.$key.' - '.$value.'</p>';
}
}
}
$lol = 123;
ev($lol); // $lol - 123
Only works for unique variable contents though.
Bit late to the game here, but Mach 13 has an interesting solution: How to get a variable name as a string in PHP
You could use eval:
function debug($variablename)
{
echo ($variablename . ":<br/>");
eval("global $". $variablename . ";");
eval("var_dump($" . $variablename . ");");
}
Usage: debug("myvar") not debug($myvar)
This is late post but I think it is possible now using compact method
so the code would be
$a=1;
$b=2;
$c=3
var_dump(compact('a','b','c'));
the output would be
array (size=3)
'a' => int 1
'b' => int 2
'c' => int 3
where variable name a, b and c are the key
Hope this helps
I believe Alix and nickf are suggesting this:
function debug($variablename)
{
echo ($variablename . ":<br/>");
global $$variablename; // enable scope
var_dump($$variablename);
}
I have tested it and it seems to work just as well as Wagger's code (Thanks Wagger: I have tried so many times to write this and the global variable declaration was my stumbling block)

Categories