tags:

views:

200

answers:

4

I want to trigger a function based on a variable.

function sound_dog() { return 'woof'; }
function sound_cow() { return 'moo'; }

$animal = 'cow';
print sound_{$animal}(); *

The * line is the line that's not correct.

I've done this before, but I can't find it. I'm aware of the potential security problems, etc.

Anyone? Many thanks.

+1  A: 

http://php.net/manual/en/functions.variable-functions.php

To do your example, you'd do

$animal_function = "sound_$animal";
$animal_function();
Brendan Long
+4  A: 

You can do that, but not without interpolating the string first:

$animfunc = 'sound_' . $animal;
print $animfunc();

Or, skip the temporary variable with call_user_func():

call_user_func('sound_' . $animal);
scribble
Thanks a bunch. You saved me a lot of irritation!
LibraryThingTim
+1  A: 

You should ask yourself why you need to be doing this, perhaps you need to refactor your code to something like the following:

function animal_sound($type){ 
    $animals=array(); 
    $animals['dog'] = "woof"; 
    $animals['cow'] = "moo"; 
    return $animals[$type];
}

$animal = "cow";
print animal_sound($animal);
Sam152
I find your method much less clean. This is the C mindset.
San Jacinto
1 function that does the same thing as 2 functions?
Sam152
C mindset? Using a hash table? More like the maintainable code mindset.
recursive
99% of the time, you'd be right. This is in a virtual <i>sea</i> of code, and I can only remember doing it once before. Where it comes in handy, however, is when you have a whole bunch of very similar functions, like:search_book_amazon();search_book_bn();search_book_z3950();... 20 moreIn cases like that...<pre>if($type == 'amazon') { search_book_amazon(); }if(type == 'bn') { search_book_bn(): }</pre>just adds another point of failure, and is annoying to type to boot.
LibraryThingTim
I wish my PREs worked in comments. What, when we comment we can't use code?!
LibraryThingTim
Maybe you need a search class.
Sam152
And comments use _a different_ form of *markup*.
Sam152
Couldn't you just do search_book('amazon') and search_book('bn')..?Also I'd use a switch statement rather than the array listed above.
Brendan Long
@recursive it's not the has table I have a problem with. I'd like to see it more functional, with each animal value being a function that is maintained outside animal_sound by attaching it to an animal object. When animal_sound is called (if you need it at all), you pass it the animal object and the animal sounds himself. In OOP, it works nice. In normal PHP, you may need to emulate closures in LISP to do the same thing. The C mindset is making 1 common function that you call, and everytime you want to extend the functionality, you need to edit that function until...
San Jacinto
...it is so huge, you end up refactoring it into several functions anyway, that aren't really all that well decoupled or reusable. It isn't the hash table that causes the problem, it's the design.
San Jacinto
+5  A: 

You can do it like this:

$animal = 'cow';
$sounder = "sound_$animal";
print ${sounder}();

However, a much better way would be to use an array:

$sounds = array('dog' => sound_dog, 'cow' => sound_cow);

$animal = 'cow';
print $sounds[$animal]();

One of the advantages of the array method is that when you come back to your code six months later and wonder "gee, where is this sound_cow function used?" you can answer that question with a simple text search instead of having to follow all the logic that creates variable function names on the fly.

Greg Hewgill