容许多个类将方法添加到另一个(至关于总控);咱们能够在扩展类中使用魔术方法 __call()
this
class Foo { public $dispatcher; public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function __call($method, $arguments) { // 建立一个名称为 'foo.method_is_not_found'的事件 $event = new HandleUndefinedMethodEvent($this, $method, $arguments); $this->dispatcher->dispatch('foo.method_is_not_found', $event); // 若是没有监听者处理该事件证实该方法不存在 if (!$event->isProcessed()) { throw new \Exception(sprintf('Call to undefined method %s::%s.', get_class($this), $method)); } // 返回监听者设置的返回值 return $event->getReturnValue(); } }
建立事件对象类spa
use Symfony\Component\EventDispatcher\Event; class HandleUndefinedMethodEvent extends Event { protected $subject; protected $method; protected $arguments; protected $returnValue; protected $isProcessed = false; public function __construct($subject, $method, $arguments) { $this->subject = $subject; $this->method = $method; $this->arguments = $arguments; } public function getSubject() { return $this->subject; } public function getMethod() { return $this->method; } public function getArguments() { return $this->arguments; } /** * 若是方法已经找到;设置返回值;且中止事件传播给其它监听者 */ public function setReturnValue($val) { $this->returnValue = $val; $this->isProcessed = true; //标识为已处理;证实方法存在; $this->stopPropagation(); //中止事件传播; } public function getReturnValue() { return $this->returnValue; } public function isProcessed() { return $this->isProcessed; } }
添加监听者类code
class Bar { public function onFooMethodIsNotFound(HandleUndefinedMethodEvent $event) { // 仅仅调用bar方法的时候该监听者才处理; if ('bar' != $event->getMethod()) { //让其余的监听者处理未知的方法 return; } //主题对像(foo 实例) $foo = $event->getSubject(); // 获取bar方法参数 $arguments = $event->getArguments(); // ... do something // 设置返回值 $event->setReturnValue("aaaaaa"); } }
public function testNotMethodEventAction() { $bar = new Bar(); $dispatcher = new EventDispatcher(); $dispatcher->addListener("foo.method_is_not_found", array($bar, 'onFooMethodIsNotFound')); $foo = new Foo($dispatcher); $foo->bar(); $foo->xxx(); return new Response("xxxxaazzz"); }
这个例子实际上是经过foo经过事件(不是使用继承)来调用bar和其余监听中的某些方法对象