2009-11-22 80 views
14

我想根據變量觸發函數。PHP:函數名稱中的變量

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

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

*行是不正確的行。

我以前做過這個,但是我找不到它。我意識到潛在的安全問題等。

有人嗎?非常感謝。

回答

19

你能做到這一點,但也不是沒有第一插值字符串:

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

或者跳過臨時可變與call_user_func()

call_user_func('sound_' . $animal); 
+0

謝謝一堆。你救了我很多煩惱! – LibraryThingTim 2009-11-22 04:40:51

+0

這是一個有趣的方法。給REQUEST變量直接訪問它會帶來安全風險嗎?如果是這樣,可以採取什麼措施來預防呢?也許是你只想訪問的函數列表,並且在遇到這個名字的REQUEST var時檢查這個列表? – 2012-12-18 01:33:03

+0

您不應直接訪問REQUEST(請閱讀:始終清理用戶輸入)。根據Greg Hewgill的回答,派送表可能是最好的解決方案。您可以通過array_key_exists()檢查REQUEST輸入的有效性,只要確保引用值(sound_dog - >'sound_dog')或它會發出通知。 – scribble 2012-12-20 20:39:39

1

你應該問自己,爲什麼你需要做這個,也許你需要重構你的代碼類似如下:

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

$animal = "cow"; 
print animal_sound($animal); 
+1

我發現你的方法不夠乾淨。這是C的心態。 – 2009-11-22 04:41:36

+0

1個功能和2個功能一樣嗎? – Sam152 2009-11-22 04:42:27

+4

C心態?使用散列表?更像可維護的代碼思維。 – recursive 2009-11-22 04:43:38

15

你可以這樣說:

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

然而,一個更好的方法是使用一個數組:

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

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

之一陣列方法的優點是,當你回到你的代碼6幾個月後,不知道「哎呀,這個sound_cow函數用在哪裏?」你可以通過簡單的文本搜索來回答這個問題,而不必遵循所有創建可變函數名稱的邏輯。

0

對於課程功能,您可以使用$this->self::。下面的示例提供了一個函數輸入參數。

$var = 'some_class_function'; 
call_user_func(array($this, $var), $inputValue); 
// equivalent to: $this->some_class_function($inputValue); 
0

您可以使用大括號來構建您的函數名稱。不確定向後兼容性,但至少PHP 7+可以做到這一點。

這裏是我的代碼中使用碳時,基於(的「添加」或「子」)用戶選擇的類型加上或減去時間:

$type = $this->date->calculation_type; // 'add' or 'sub' 

$result = $this->contactFields[$this->date->{'base_date_field'}] 
        ->{$type.'Years'}($this->date->{'calculation_years'}) 
        ->{$type.'Months'}($this->date->{'calculation_months'}) 
        ->{$type.'Weeks'}($this->date->{'calculation_weeks'}) 
        ->{$type.'Days'}($this->date->{'calculation_days'}); 

這裏最重要的部分是{$type.'someString'}部分。這將在執行之前生成函數名稱。因此,在第一種情況下,如果用戶選擇了「添加」,則{$type.'Years'}將變爲addYears