Symfony how to return all logged in Active Users
doctrine, php, symfony, symfony-2.3
Solution
There is a great post here: List online users.
You can create a Listener that listens on the `kernel.controller` event and updates a user field lastActivity every time a user is active. You can check `lastActivity < now()- 2 minutes` and update lastActivity timestamp.
Also: Implementing user activity in symfony 2
Here is how to do it
Note: If you're not using FOSUserBundle, see Edit below.
1 Add this to your User Entity
/**
* Date/Time of the last activity
*
* @var \Datetime
* @ORM\Column(name="last_activity_at", type="datetime")
*/
protected $lastActivityAt;
/**
* @param \Datetime $lastActivityAt
*/
public function setLastActivityAt($lastActivityAt)
{
$this->lastActivityAt = $lastActivityAt;
}
/**
* @return \Datetime
*/
public function getLastActivityAt()
{
return $this->lastActivityAt;
}
/**
* @return Bool Whether the user is active or not
*/
public function isActiveNow()
{
// Delay during wich the user will be considered as still active
$delay = new \DateTime('2 minutes ago');
return ( $this->getLastActivityAt() > $delay );
}
2 Create Event Listener
<?php
namespace Acme\UserBundle\EventListener;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\HttpKernel;
use FOS\UserBundle\Model\UserManagerInterface;
use FOS\UserBundle\Model\UserInterface;
/**
* Listener that updates the last activity of the authenticated user
*/
class ActivityListener
{
protected $securityContext;
protected $userManager;
public function __construct(SecurityContext $securityContext, UserManagerInterface $userManager)
{
$this->securityContext = $securityContext;
$this->userManager = $userManager;
}
/**
* Update the user "lastActivity" on each request
* @param FilterControllerEvent $event
*/
public function onCoreController(FilterControllerEvent $event)
{
// Check that the current request is a "MASTER_REQUEST"
// Ignore any sub-request
if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) {
return;
}
// Check token authentication availability
if ($this->securityContext->getToken()) {
$user = $this->securityContext->getToken()->getUser();
if ( ($user instanceof UserInterface) && !($user->isActiveNow()) ) {
$user->setLastActivityAt(new \DateTime());
$this->userManager->updateUser($user);
}
}
}
}
3 Declare event Listener as a service
parameters:
acme_user.activity_listener.class: Acme\UserBundle\EventListener\ActivityListener
services:
acme_user.activity_listener:
class: %acme_user.activity_listener.class%
arguments: [@security.context, @fos_user.user_manager]
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onCoreController }
And you're good to go!
Edit (without FOSUserBundle)
1 Add this to your User Entity
Same as Step 1 Above
2 Create Event Listener
<?php
namespace Acme\UserBundle\EventListener;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\HttpKernel;
use Doctrine\ORM\EntityManager;
use Acme\UserBundle\Entity\User;
/**
* Listener that updates the last activity of the authenticated user
*/
class ActivityListener
{
protected $securityContext;
protected $entityManager;
public function __construct(SecurityContext $securityContext, EntityManager $entityManager)
{
$this->securityContext = $securityContext;
$this->entityManager = $entityManager;
}
/**
* Update the user "lastActivity" on each request
* @param FilterControllerEvent $event
*/
public function onCoreController(FilterControllerEvent $event)
{
// Check that the current request is a "MASTER_REQUEST"
// Ignore any sub-request
if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) {
return;
}
// Check token authentication availability
if ($this->securityContext->getToken()) {
$user = $this->securityContext->getToken()->getUser();
if ( ($user instanceof User) && !($user->isActiveNow()) ) {
$user->setLastActivityAt(new \DateTime());
$this->entityManager->flush($user);
}
}
}
}
3 Declare event Listener as a service
parameters:
acme_user.activity_listener.class: Acme\UserBundle\EventListener\ActivityListener
services:
acme_user.activity_listener:
class: %acme_user.activity_listener.class%
arguments: [@security.context, @doctrine.orm.entity_manager]
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onCoreController }
And you're good to go!
Problem
I want to return all Logged in users of my application and render it in my Dashboard. The `user_id` and `user_name` should be retrieved from the session (I am using an external LDAP Library for authentication) I have created a field in the database called `lastActivity` which will contain the last login time and then I can query the database for `lastActivity` display users logged in in the last 2 minutes. ActivityListener.php ``` <?php namespace Bnpp\SecurityBundle\EventListener; use Doctrine\ORM\EntityManager; //use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\SecurityContext; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; use Symfony\Component\HttpKernel\HttpKernel; use Acme\SecurityBundle\Entity\User; use Doctrine\Bundle\DoctrineBundle\Registry; /** * Listener that updates the last activity of the authenticated user */ class ActivityListener { protected $securityContext; protected $entityManager; public function __construct(SecurityContext $securityContext, EntityManager $entityManager) { $this->securityContext = $securityContext; $this->entityManager = $entityManager; } /** * Update the user "lastActivity" on each request * @param FilterControllerEvent $event */ public function onCoreController(FilterControllerEvent $event) { // Check that the current request is a "MASTER_REQUEST" // Ignore any sub-request if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) { return; } // Check token authentication availability if ($this->securityContext->getToken()) { $user = $this->securityContext->getToken()->getUser(); if ( ($user instanceof User) && !($user->isActiveNow()) ) { $user->setLastActivity(new \DateTime('now')); $this->entityManager->flush($user); } } } } ``` Services.yml ``` services: activity_listener: class: Bnpp\SecurityBundle\EventListener\ActivityListener arguments: [@security.context, @doctrine.orm.entity_manager] tags: - { name: kernel.event_listener, event: kernel.controller, method: onCoreController } ``` User Entity ``` <?php namespace Acme\SecurityBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Security\Core\User\UserInterface; /** * User * * @ORM\Table(name="users") * @ORM\Entity(repositoryClass="Acme\SecurityBundle\Entity\UserRepository") */ class User implements UserInterface { /** * @var \DateTime * @ORM\Column(name="LASTACTIVITY", type="datetime") */ private $lastActivity; /** * @return bool whether the user is active or not */ public function isActiveNow() { $delay = new\DateTime('2 minutes ago'); return($this->getlastActivity()>$delay); } /** * Set lastActivity * * @param\Datetime $lastActivity * @return User */ public function setlastActivity($lastActivity) { $this->lastActivity = $lastActivity; return $this; } /** * Get lastActivity * * @return \DateTime */ public function getlastActivity() { return $this->lastActivity; } } ```