2012-12-10 105 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每个命令的类别。

相关问题