tags:

views:

436

answers:

2

Here's a piece of code:

$obj = new myClass();
$obj->{$_GET["func"]}($_GET["param"])

It works based on variable variables, but I don't really understand how. As far as I know, variable variables are used for stuff like this:

require "dbsettings.php"
$member_id = $_GET['id'];
$db = new DBconnector();
$vars = array('username','passw','email','info','datejoined','dateofbirth');

foreach ($vars as $var) {
  $$var = $db->getUserInfo($member_id,$var);
}
echo $username;
echo $passw;
echo $email;
echo $info;
echo $datejoined;
echo $dateofbirth;

So, in the first piece of code, what's happening? Also, what function do the braces serve? What do they tell the compiler to think?

+9  A: 
$obj->{$_GET["func"]}($_GET["param"])

Simply calls the method whose name is stored in $_GET["func"], and pass as a parameter $_GET["param"].

The parentheses serve to disambiguate the method name (you also use parentheses in strings for similar purposes, e.g. echo "calling {$_GET['func']}";

See the PHP manual page on variable variables for more, e.g.

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.

A note on security

As this is the accepted answer, I'm going to add that you shouldn't use user input so blindly, there may be methods on $obj which you wouldn't want be called.

You could, for example, check the method name against an array of allowed methods, e.g.

$method=$_GET["func"];
$ok=in_array($method, array('foo', 'bar', 'frobozz'));

Alternatively, you could only allow method names which follow a particular pattern, e.g. prefixed with 'ajax':

$method=$_GET["func"];
$ok=preg_match('/^ajax[A-Za-z]/', $method);

Or a variation on that idea, where the prefix is added to the passed method name so that only methods with that prefix can be called

$method='ajax'.preg_replace('/[^A-Za-z]/', '', $_GET["func"]);

There are other ways, but hopefully that illustrates a basic tenet: assume your worst enemy constructed the $_GET array!

Paul Dixon
I get it. So if my func paramter is "GetID" and param is 2, what I get it: $obj->GetID(2);
Vordreller
This is, of course, dangerous; in practice you'd never want to accept a function name from untrusted user input. But you're dealing with that, right?
bobince
Good point, have expanded answer.
Paul Dixon
+1  A: 

It's basically calling a funcion depending on parameters.

So, if you make a request like:

mypage.php?func=prop&param=value

What you'll end up getting this function call:

$obj->prop('value')

Braces serve to keep the array notation together and apply that ["func"] to the $_GET variable instead of $obj->$_GET (which could be a valid array). If you didn't use braces, what you'll be doing would be similar to:

($obj->$_GET)["func"](...)

In this case, note that you would be asking for the key "func" of array $obj->$_GET, instead of just $_GET.

Seb