2012-06-18 15 views
4

我想要一個函數字典。有了這個字典,我可以有一個接受函數名和參數數組的處理程序,並執行該函數,返回它返回的值,如果它返回任何東西。如果名稱與現有函數不對應,則處理程序將拋出錯誤。如何在PHP中創建函數字典?

這將是很容易實現的Javascript:

var actions = { 
    doSomething: function(){ /* ... */ }, 
    doAnotherThing: function() { /* ... */ } 
}; 

function runAction (name, args) { 
    if(typeof actions[name] !== "function") throw "Unrecognized function."; 
    return actions[name].apply(null, args); 
} 

但由於功能是不是真的在PHP第一類對象,我無法弄清楚如何輕鬆地做到這一點。有沒有一個相當簡單的方法來在PHP中做到這一點?

+0

只關心爲什麼你需要這個,爲什麼不使用靜態類呢? – Eugene

+0

「但是由於函數不是PHP中的第一類對象」不是。匿名函數(這是你的代碼顯示的)是常規的PHP對象,類Closure(http://php.net/manual/en/class.closure.php) – newacct

回答

3
$actions = array(
    'doSomething'  => 'foobar', 
    'doAnotherThing' => array($obj, 'method'), 
    'doSomethingElse' => function ($arg) { ... }, 
    ... 
); 

if (!is_callable($actions[$name])) { 
    throw new Tantrum; 
} 

echo call_user_func_array($actions[$name], array($param1, $param2)); 

你的字典可以由任何允許的callable類型。

3

我不明白你的意思。
如果你需要的功能的陣列只是做:

$actions = array(
'doSomething'=>function(){}, 
'doSomething2'=>function(){} 
); 

可以比運行函數$actions['doSomething']();

當然你也可以有ARGS:

$actions = array(
'doSomething'=>function($arg1){} 
); 


$actions['doSomething']('value1'); 
+0

我沒有意識到你可以在PHP中做到這一點 –

+0

在PHP中,你沒有任何限制(恕我直言) – dynamic

+0

@yes「沒有限制」 - 大聲笑! :-D – deceze

2

你可以使用PHP的__call()爲:

class Dictionary { 
    static protected $actions = NULL; 

    function __call($action, $args) 
    { 
     if (!isset(self::$actions)) 
      self::$actions = array(
      'foo'=>function(){ /* ... */ }, 
      'bar'=>function(){ /* ... */ } 
      ); 

     if (array_key_exists($action, self::$actions)) 
      return call_user_func_array(self::$actions[$action], $args); 
     // throw Exception 
    } 
} 

// Allows for: 
$dict = new Dictionary(); 
$dict->foo(1,2,3); 

對於靜態調用,__callStatic()都可以使用(如PHP5.3的)。

+0

你也可以使用「真實」的方法,並檢查它們是否存在['method_exists'](http://de.php.net/method_exists)。然後避免類中的醜陋的數組結構。 – Michael

+0

這不會完全省略__call()嗎?手動指出它*在調用對象上下文中不可訪問的方法時被觸發。「* –

+0

我沒有嘗試,但如果是這樣,可以爲方法使用下劃線之類的前綴。然後從外部調用沒有下劃線,讓'__call'然後調用帶有下劃線前綴的內部方法。 – Michael

1
// >= PHP 5.3.0 
$arrActions=array(
    "doSomething"=>function(){ /* ... */ }, 
    "doAnotherThing"=>function(){ /* ... */ } 
); 
$arrActions["doSomething"](); 
// http://www.php.net/manual/en/functions.anonymous.php 


// < PHP 5.3.0 
class Actions{ 
    private function __construct(){ 
    } 

    public static function doSomething(){ 
    } 

    public static function doAnotherThing(){ 
    } 
} 
Actions::doSomething(); 
1

如果您計劃在對象上下文中使用它您不必創建任何函數/方法字典。

你可以簡單地提高對unexisting方法有些誤差與魔術方法__call()

class MyObject { 

    function __call($name, $params) { 
     throw new Exception('Calling object method '.__CLASS__.'::'.$name.' that is not implemented'); 
    } 

    function __callStatic($name, $params) { // as of PHP 5.3. < 
     throw new Exception('Calling object static method '.__CLASS__.'::'.$name.' that is not implemented'); 
    } 
} 

其他每一個類應該擴展你的MyObject類...

http://php.net/__call