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 :
<?php
namespace 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 ?
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