2012-12-10 61 views
1

我正在做一個類的事件處理程序,但我想知道是否會更好地使用閉包而不是評估代碼?使用閉包進行事件處理而不是使用eval()會更好嗎?

我使用eval()的唯一原因僅僅是因爲它能夠訪問類中的所有內容(它真的非常不安全:D),但我不知道閉包是否可以。

,如果我做了這樣的事情:

<?php 
    class SomethingCool { 
     protected $handlers; 

     public function addHandler($cmd, closure $func) { 
      $this->handlers[$cmd][] = $func; 
     } 

     public function handle($cmd) { 
      if(!isset($this->handlers[$cmd])) 
       return false; 
      foreach($this->handlers[$cmd] as $func) 
       $func(); 
     } 
    } 
?> 

<?php 
    $wut = new SomethingCool(); 
    $wut->addHandler('lol', function() use($wut) { 
           $wut->handle('lol'); 
          } 
        ); 
?> 

它會執行沒有錯誤? 我會自己測試,但目前我無法進行測試。

+0

除了引用'unset'引起的明顯錯誤... –

+0

'$ this'應該引用什麼? –

+0

請參閱:http://php.net/manual/en/functions.anonymous.php#107949 –

回答

2

如果你寫使用eval處理程序,你最終會這樣寫代碼:

$wut->addHandler('lol', '$this->handle(\'lol\');'); 
從明顯可怕的問題,逃避的報價和破碎的語法在編輯器中突出

除此之外,這引入了問題不明確的依賴關係。 $this在您的代碼中引用了什麼?它不像字面上的代碼那樣工作,它取決於在特定的上下文中進行評估。這使代碼變得非常混亂。

另一種方法是依賴注入:

$wut->addHandler('lol', function (SomethingCool $sc) { 
    $sc->handle('lol'); 
}); 

當調用該處理程序,將SomethingCool本身注入作爲函數參數。這是更強大。這意味着您可以將此回調傳遞給其他上下文,並在後臺執行任何您想要的操作,回調並不依賴於在特定上下文中進行評估。

另外,使用閉包:

$wut->addHandler('lol', function() use ($wut) { 
    $wut->handle('lol'); 
}); 

這樣做,你是知道在你的依賴來自和了解,你可以依賴於它的同樣的好處。

所以是的,什麼eval好。

+0

哦,這似乎是最好的賭注imo。 感謝您輸入dewd,我會在家裏測試這個。 和大聲笑是啊,你爲什麼覺得我想離開eval()?它是邪惡的。 –

+0

工程太棒了!多謝,夥計。 –

+0

由於OP無法調出... +1 :) –

0

爲什麼不把您的SomethingCool的實例傳遞給每個處理程序?

public function handle($cmd) 
{ 
    if (!isset($this->handlers[$cmd])) { 
     return; 
    } 
    foreach ($this->handlers[$cmd] as $func) 
     $func($this); // pass ourself to each handler 
    } 
} 

$wut->addHandler('lol', function(SomethingCool $obj) { 
    // $obj refers to the SomethingCool instance 
}); 

$wut->handle('lol'); 

順便說一句,如果你也想能夠移除處理程序,你也可以使用SplObjectStorage每個命令的類別。

相關問題