Documentação do Symfony - versão 3.1
Renderizada do repositório symfony-docs-pt-BR no Github
Para permitir que várias classes adicionem métodos para uma outra, você pode definir o
método mágico __call()
na classe que você deseja que seja estendida da seguinte forma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Foo
{
// ...
public function __call($method, $arguments)
{
// cria um evento chamado 'foo.method_is_not_found'
$event = new HandleUndefinedMethodEvent($this, $method, $arguments);
$this->dispatcher->dispatch($this, 'foo.method_is_not_found', $event);
// nenhum listener foi capaz de processar o evento? O método não existe
if (!$event->isProcessed()) {
throw new \Exception(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
}
// retorna o valor retornado pelo listener
return $event->getReturnValue();
}
}
|
Ela utiliza um HandleUndefinedMethodEvent
especial que também deve ser
criado. Esta é uma classe genérica que poderia ser reutilizada cada vez que você precisa
utilizar esse padrão de extensão de classe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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;
}
/**
* Define o valor de retorno e pára a notificação para outros listeners
*/
public function setReturnValue($val)
{
$this->returnValue = $val;
$this->isProcessed = true;
$this->stopPropagation();
}
public function getReturnValue($val)
{
return $this->returnValue;
}
public function isProcessed()
{
return $this->isProcessed;
}
}
|
Em seguida, crie uma classe que vai ouvir o evento foo.method_is_not_found
e adicionar o método bar()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class Bar
{
public function onFooMethodIsNotFound(HandleUndefinedMethodEvent $event)
{
// queremos somente responder as chamadas do método 'bar'
if ('bar' != $event->getMethod()) {
// permite que outro listener cuide deste método desconhecido
return;
}
// o objeto (a instância foo)
$foo = $event->getSubject();
// os argumentos do método bar
$arguments = $event->getArguments();
// faz algo
// ...
// define o valor de retorno
$event->setReturnValue($someValue);
}
}
|
Por fim, adicione o novo método bar
na classe Foo
para registrar uma
instância de Bar
com o evento foo.method_is_not_found
:
1 2 | $bar = new Bar();
$dispatcher->addListener('foo.method_is_not_found', $bar);
|