Short story : I have some diffulties to use a listener properly on my custom "vendor" bundle.
I'm coding a reusable bundle for Symfony 4.1 framework (for managing Users). I put the whole bundle in this location of a new symfony project : myproject/lib/AcmeUserBundle/src/
Just like this Demo
Because my bundle is at a non usual place, I changed my config/services.yaml like this (in case this is relevent) :
services: # default configuration for services in *this* file _defaults: autowire: true autoconfigure: true public: false App\: resource: '../src/*' exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}' App\Controller\: resource: '../src/Controller' tags: ['controller.service_arguments'] Acme\UserBundle\: resource: '../lib/AcmeUserBundle/src/*' exclude: '../lib/AcmeUserBundle/src/{DependencyInjection,Entity,Migrations,Tests}' Acme\UserBundle\Controller\: resource: '../lib/AcmeUserBundle/src/Controller' tags: ['controller.service_arguments']
Then, I coded a login form (that you don't care much), and when a user logged in, I want to update his last datetime connexion info in database. So I have built a listener following this tutorial on the security.interactive_login
event :
<?phpnamespace Acme\UserBundle\EventListener;use DateTime;use Doctrine\ORM\EntityManagerInterface;use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;class LoginListener{ /** * @var EntityManagerInterface */ private $entityManager; /** * LoginListener constructor. * * @param EntityManagerInterface $entityManager */ public function __construct(EntityManagerInterface $entityManager) { $this->entityManager = $entityManager; } /** * @param InteractiveLoginEvent $event */ public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) { // Get the User entity. $user = $event->getAuthenticationToken()->getUser(); /** @var \Acme\UserBundle\Entity\User $user */ $user->setLastLoggedAt(new DateTime()); $this->entityManager->persist($user); $this->entityManager->flush(); }}
lib/AcmeUserBundle/src/Resources/config/services.yaml looks like :
services: Acme\UserBundle\EventListener\LoginListener: tags: - { name: kernel.event_listener, event: security.interactive_login }
lib/AcmeUserBundle/src/DependencyInjection/AcmeUserExtension.php looks like :
class AcmeUserExtension extends Extension{ /** * @param array $configs * @param ContainerBuilder $container */ public function load(array $configs, ContainerBuilder $container) { $loader = new YamlFileLoader( $container, new FileLocator(__DIR__.'/../Resources/config') ); $loader->load('services.yaml'); }}
I can see my service using these symfony commands :php bin/console debug:autowiring
php bin/console debug:container
But I can't see anything with :php bin/console debug:event-dispatcher
When I log-in with my user, no error occurs, and of course, no date is inserted in database. That's why I think my listener is not properly registered.
Any idea why ?
EDIT after Cerad's comment :
Output of php bin/console debug:container LoginListener
---------------- ------------------------------------------------ Option Value ---------------- ------------------------------------------------ Service ID Acme\UserBundle\EventListener\LoginListener Class Acme\UserBundle\EventListener\LoginListener Tags - Public no Synthetic no Lazy no Shared yes Abstract no Autowired yes Autoconfigured yes ---------------- ------------------------------------------------
We can see that the Tags part is empty. That's the reason why my listener is ignored.And... it works if I comment that part of my config/service.yaml :
... #Acme\UserBundle\: # resource: '../lib/AcmeUserBundle/src/*' # exclude: '../lib/AcmeUserBundle/src/{DependencyInjection,Entity,Migrations,Tests}'...
New output of php bin/console debug:container LoginListener
---------------- ----------------------------------------------------------- Option Value ---------------- ----------------------------------------------------------- Service ID Acme\UserBundle\EventListener\LoginListener Class Acme\UserBundle\EventListener\LoginListener Tags kernel.event_listener (event: security.interactive_login) Public no Synthetic no Lazy no Shared yes Abstract no Autowired no Autoconfigured no ---------------- -----------------------------------------------------------
Tags is now correct and my listener works properly