在我的应用程序中,用户可以随着时间的推移在免费用户和高级用户之间切换,当他们的订阅到期时,他们不再拥有高级特权。
我想我可以偷工减料,不在数据库中存储高级用户角色,只存储他们付款的日期,这样就不需要添加cron作业,也不需要从我的用户中删除角色高级。
我想到的解决方案是在用户实体上这样做:
public function __construct()
{
if ( $this->hasPlus() )
{
$this->addRole('ROLE_PLUSUSER');
}
}
其中hasPlus是一个比较当前日期和截止日期的函数,如果用户仍在付款,则返回true。
现在,这不起作用,所以我想也许有人可以为我阐明这一点——我知道角色是在登录时添加的,如果我在登录后添加角色,我需要注销并重新登录才能生效,但在这里,我试图在构建我的用户对象时添加角色,但它仍然不起作用。。。
根据下面的优秀答案添加了eventListener,仍然无法向用户添加角色:
<?php
namespace Hemekonomi'UserBundle'EventListener;
use Symfony'Component'Security'Http'Event'InteractiveLoginEvent;
use Symfony'Component'Security'Core'SecurityContext;
use Symfony'Component'HttpFoundation'Session;
class SecurityListener
{
protected $security;
protected $session;
/**
* Constructs a new instance of SecurityListener.
*
* @param SecurityContext $security The security context
* @param Session $session The session
*/
public function __construct(SecurityContext $security, Session $session)
{
//You can bring whatever you need here, but for a start this should be useful to you
$this->security = $security;
$this->session = $session;
}
/**
* Invoked after a successful login.
*
* @param InteractiveLoginEvent $event The event
*/
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
//Your logic needs to go here
//You can addRole
//Even persist if you want but bring the right tools to your constructor
$security = $this->security;
if ($security->getToken()->getUser()->hasPlus()) {
$security->getToken()->getUser()->addRole('ROLE_PLUSUSER');
}
}
}
您的逻辑不会在user
实体上工作。。。
如果您想要在登录时实现,请使用Event Listeners
,这就是它们如此有用的原因:-)
您需要创建一个对事件InteractiveLoginEvent
做出反应的监听器,类似于以下内容:
1/创建一个监听器
<?php
namespace Acme'YourBundle'EventListener;
use Symfony'Component'Security'Http'Event'InteractiveLoginEvent;
use Symfony'Component'Security'Core'SecurityContext;
use Symfony'Component'HttpFoundation'Session'Session;
class SecurityListener
{
protected $security;
protected $session;
/**
* Constructs a new instance of SecurityListener.
*
* @param SecurityContext $security The security context
* @param Session $session The session
*/
public function __construct(SecurityContext $security, Session $session)
{
//You can bring whatever you need here, but for a start this should be useful to you
$this->security = $security;
$this->session = $session;
}
/**
* Invoked after a successful login.
*
* @param InteractiveLoginEvent $event The event
*/
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
//Your logic needs to go here
//You can addRole
//Even persist if you want but bring the right tools to your constructor
}
}
请记住,InteractiveLoginEvent默认情况下已经在Symfony中创建(如您在use
语句中所见),因此现在几乎没有什么可做的:
2/将此侦听器声明为服务:
services:
acme_your_bundle.listener.login:
class: Acme'YourBundle'EventListener'SecurityListener
arguments: [@security.context, @session]
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin }
3/如果需要,请查看文档
事件调度器组件
如何创建事件侦听器
Dustin Dobervich的登录重定向:这篇文章将给你一个很好的例子,告诉你听众是如何工作的,以及你如何在登录时简单地实现它们。