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; } } ```

Original source

Related problems