JMSDiExtraBundle
JMSDiExtraBundle copied to clipboard
[doc] Can't use @Observe in controllers?
I feel like we can't use @Observe in controllers.
Here is my controller:
class DefaultController extends Controller {
/** @DI\Inject */
private $event_dispatcher;
/**
* @Route("/toy/{name}")
* @Template()
*/
public function indexAction($name) {
$this->event_dispatcher->dispatch("my_event");
return array('name' => $name);
}
/** @DI\Observe("my_event") */
public function onMyEvent(Event $event) {
echo "The @Observe in the controller class. <br>";
}
}
And I have a non-controller class with the exact same @Observe listener:
/** @DI\Service("my_service") */
class MyService {
/** @DI\Observe("my_event") */
public function onMyEvent(Event $event) {
echo "The @Observe in a non-controller class. <br>";
}
}
When visiting /toy/john, it displays
The @Observe in a non-controller class.
Hello john!
It looks like indeed we can't use @Observe in controllers:
- the config is correct because the annotation
@Injectis resolved in the controller - the event dispatcher setup works because the listener in
MyServiceis called - the syntax and setup for
@DI\Observeis correct because it's called inMyServicebut the listener in the controller is not called.
Listeners have to be services. your controller is not a service.
Btw, if your controller method is considered as a listener, you have a big issue about the responsibility of your controller class.
@stof, thanks for your answer. JMSDiExtraBundle's documentation says we can use all DI annotations on controllers, even if they are not services:
Yes, no services, but don’t worry you can still use all of the DIC’s features, and even some more.
Is the documentation misleading on that point or am I missing something?
As for the responsibility, I'm researching implementing with Symfony2 a design pattern that is experimented in the Rails community (here and here) where basically everything that is not parsing HTTP arguments or building HTTP response is outside the controller, but in some core classes. So there has to be some kind of callback mechanism for the core classes to return to the controller. In Rails, they would call some small methods of the controller that returns the HTTP response:
def card_updated(card)
redirect_to card_path(card), notice: 'Card saved'
end
def card_update_failed(card)
render action: 'new', alert: 'Ooops!', locals: { card: card }
end
But I feel it is not really possible in Symfony2 as a controller must return a Response object. So it looks like the render or redirect cannot be done by another method than the controller itself.
@qpleple a kernel.request listener can set a RedirectResponse in the event if you want (returning it has no effect though).
For the doc, I guess this sentence has been written before implementing Observe