我需要记录最后一个用户的活动时间,每个页面加载或ajax呼叫计数。
我想我需要订阅一些活动,但我不知道哪一个。
在this answer中提到的InteractiveLoginEvent,我的理解仅在交互式登录时触发。但是,如果一个会话可能持续一周或更长时间,它将使记录方式过于不准确。所以我需要另一个活动,但是哪一个?
或者,是否有开箱即用的功能?
答案 0 :(得分:1)
解决方案可以是KernelEvents::RESPONSE
事件的监听器,确保用户通过身份验证。
namespace AppBundle\Subscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class LastActivityListener implements EventSubscriberInterface
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function onResponse(FilterResponseEvent $event)
{
$token = $this->tokenStorage->getToken();
if ($token->isAuthenticated()) {
// save last activity for $token->getUser(); in some place.
}
}
public static function getSubscribedEvents()
{
return [
KernelEvents::RESPONSE => 'onResponse',
];
}
}
此外,您可能需要注入存储服务以保存此记录(例如,如果Doctrine可用,则为EntityManager
。)
答案 1 :(得分:1)
执行此操作的最简单方法是订阅kernel.controller
事件,该事件将在每个控制器操作之前运行,无论是正常还是通过AJAX。它看起来像这样:
namespace AppBundle\EventSubscriber;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class UserActivityLogSubscriber implements EventSubscriberInterface
{
/** @var TokenStorageInterface **/
private $tokenStorage;
/** @var LoggerInterface **/
private $logger;
/**
* @param TokenStorageInterface $tokenStorage
* @param LoggerInterface $logger
*/
public function __construct(
TokenStorageInterface $tokenStorage,
LoggerInterface $logger
) {
$this->tokenStorage = $tokenStorage;
$this->logger = $logger;
}
public function onKernelController(FilterControllerEvent $event)
{
$actionTime = new \DateTime();
$controller = $event->getController();
if (!is_array($controller) {
return;
}
$action = get_class($controller[0]).'::'.$controller[1];
$token = $this->tokenStorage->getToken();
$user = $token->getUser();
if ($user) {
$logger->info('User: '.$user->getId().' Action: '.$action.' at: '.$now->format('Y-m-d g:i:s');
}
}
public static function getSubscribedEvents()
{
return array(
KernelEvents::CONTROLLER => 'onKernelController',
);
}
}
这只是将控制器操作记录到标准记录器的简单示例。您可以注入 EntityManager ,而不是仅输出到日志,而是将事件时间记录到数据库中的last_activity
列。
您还可以执行类似于创建 UserLoggableController 控制器接口的操作,并且只有在您的控制器实现该接口时才执行此操作:
<强>接口强>
namespace AppBundle\Controller;
interface UserLoggableController
{
// ...
}
<强>控制器:强>
class MyController extends Controller implements UserLoggableController
修改后的UserActivityLogSubscriber:
if (!$controller[0] instanceof UserActivityLogSubscriber) {
return;
}
Symfony在setting up controller before/after filters上也提供了一些很好的文档。