1

I'm trying to use a variable variable as follows:

function keyValMyArray($nameofmyarray) {
  foreach(${$nameofmyarray} as $key => $val) {
    print "$key: $val<br>";
  } 
}

$bookPrices = Array('Catcher in the Rye' => '$2', 'Curious George' => '$4.25', 'Dracula' => '$8');

keyValMyArray('bookPrices')

This doesn't work. The error I get is: Invalid argument supplied for foreach();

Anyone know how I can use a variable variable in this instance?

Rob
  • 6,109
  • 7
  • 32
  • 38
Amanda
  • 23
  • 3
  • are you using smarty or something??? `${$nameofmyarra}` – KJYe.Name 葉家仁 Mar 09 '11 at 15:29
  • 1
    @kjy112: Read http://php.net/manual/en/language.variables.variable.php – Lightness Races in Orbit Mar 09 '11 at 15:31
  • 1
    That's a variable variable. IMO an awful thing that is as bad as GOTO. – ThiefMaster Mar 09 '11 at 15:31
  • I fail to think of any good reason not to pass the array itself as the argument instead of the array name... – acm Mar 09 '11 at 15:56
  • @andrematos: That's easy to say when you have a contrived testcase in front of you. Perhaps the name of the array to use comes from user input (or a separate part of the application); this feature would function as a mapping of names to arrays, then. I'm not necessarily advocating this approach, but I don't think you can write it off for this scenario when we don't really _know_ the scenario. – Lightness Races in Orbit Mar 10 '11 at 00:47

4 Answers4

5

The function doesn't have access to the array.

function keyValMyArray($nameofmyarray) {
  global ${$nameofmyarray};
  foreach(${$nameofmyarray} as $key => $val) {
    print "$key: $val<br>";
  } 
}

or:

function keyValMyArray($nameofmyarray) {
  foreach($GLOBALS[$nameofmyarray] as $key => $val) {
    print "$key: $val<br>";
  } 
}

Bear in mind, though, that variable variables are typically considered "bad form" (though there is not so much rationale out there explaining precisely why, other than that it feels kind of messy a bit like using eval in Javascript).

See this SO question about whether people think PHP globals are "bad".

Community
  • 1
  • 1
Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
1
foreach($GLOBALS[$nameofmyarray] as $key => $val) {

But seriously.. don't use variable variables. Especially not when passing the variable name to another function. They not only make your code hard to read but also impossible to analyze by programs (ask someone interested in theoretical computer science if you want to know why).

Besides that, usually an array (which could be global or passed as a function parameter) is much better and cleaner.

By the way, if you just want a way to debug-print an array, use print_r($array);

ThiefMaster
  • 285,213
  • 77
  • 557
  • 610
1

The problem is not a variable variable but the fact, that you are accessing a variable which is out of the function scope. From inside of function you can access only the parameters of the function, so called superglobals and global variables (with statement global $global_variable;).

Pleae read about variable scope

If the $bookPrices is a global variable then you might try:

function keyValMyArray($nameofmyarray) { 
    global ${$nameofmyarray};
    foreach(${$nameofmyarray} as $key => $val) { 
        print "$key: $val"; 
    } 
}

But this is not good practice, as it will only work in the special cases where you use global variables.

Maybe you can just pass keyValMyArray the actual variable, and not its name? It would be more general. That way if you can access the variable in the place where you call the funciton it would work also for local variables:

function keyValMyArray($myarray) {      
    foreach($myarray as $key => $val) { 
        print "$key: $val"; 
    } 
}

//then use:
keyValMyArray($bookPrices);
//or
$nameOfArray = 'bookPrices');
keyValMyArray(${$nameOfArray});

Best regards, SWilk

SWilk
  • 2,789
  • 7
  • 24
  • 50
0

$bookPrices will not exist inside of your function. See the manual on variable scope. http://www.php.net/manual/en/language.variables.scope.php

As others pointed out, if you need to do it this way you must use global or $GLOBALS. This is not considered a best practice though.

Rob
  • 6,109
  • 7
  • 32
  • 38