php - Symfony 3 登录后更新用户数据

标签 php authentication symfony

我正在联系 Symfony,这是我的第一个应用程序,我正在尝试了解所有环境。这是一个非常简单的问题,但在网上冲浪了很长时间后我不知道如何做。

我有一个登录表单,可以很好地使用监听器来处理成功或错误,一切都很好,但当我尝试更新用户的上次访问日期时,问题就出现了。

我有一个用户实体(取自文档):

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;

/**
 * @ORM\Table(name="app_users")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */
class User implements AdvancedUserInterface, \Serializable
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=25, unique=true)
     */
    private $username;

    /**
     * @ORM\Column(type="string", length=64)
     */
    private $password;

    /**
     * @ORM\Column(type="string", length=60, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(name="is_active", type="boolean")
     */
    private $isActive;

    /**
     * @ORM\Column(name="salt", type="string", length=100)
     */
    private $salt;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $lastLogin = null;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $createdAt = null;

    public function __construct()
    {
        $this->isActive = true;
        // may not be needed, see section on salt below
        // $this->salt = md5(uniqid(null, true));
    }

    public function getUsername()
    {
        return $this->username;
    }

    public function setSalt($salt)
    {
        $this->salt = $salt;
    }

    public function getSalt()
    {
        // you *may* need a real salt depending on your encoder
        // see section on salt below
        return null;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function getRoles()
    {
        return array('ROLE_USER');
    }

    public function eraseCredentials()
    {
    }

    public function isAccountNonExpired()
     {
         return true;
     }

     public function isAccountNonLocked()
     {
         return true;
     }

     public function isCredentialsNonExpired()
     {
         return true;
     }

     public function isEnabled()
     {
         return $this->isActive;
     }

    /** @see \Serializable::serialize() */
    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->password,
            $this->isActive,
            $this->createdAt,
            $this->lastLogin,
            // see section on salt below
            // $this->salt,
        ));
    }

    /** @see \Serializable::unserialize() */
    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->username,
            $this->password,
            $this->isActive,
            $this->createdAt,
            $this->lastLogin,
            // see section on salt below
            // $this->salt
        ) = unserialize($serialized);
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set username
     *
     * @param string $username
     *
     * @return User
     */
    public function setUsername($username)
    {
        $this->username = $username;

        return $this;
    }

    /**
     * Set password
     *
     * @param string $password
     *
     * @return User
     */
    public function setPassword($password)
    {
        $this->password = $password;

        return $this;
    }

    /**
     * Set email
     *
     * @param string $email
     *
     * @return User
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Get email
     *
     * @return string
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Set isActive
     *
     * @param boolean $isActive
     *
     * @return User
     */
    public function setIsActive($isActive)
    {
        $this->isActive = $isActive;

        return $this;
    }

    /**
     * Get isActive
     *
     * @return boolean
     */
    public function getIsActive()
    {
        return $this->isActive;
    }

    /**
     * Updates last user login date
     *
     */
    public function updateLastLogin()
    {
        $this->lastAccess = new \DateTime("now");
    }

    public function getLastLogin()
    {
        return $this->lastLogin->format('Y-m-d H:i:s');
    }

    public function getCreatedAt()
    {
        return $this->createdAt->format('Y-m-d H:i:s');
    }
}

当用户登录时,我调用 updateLastLogin 方法:

<?php
namespace AppBundle\EventListener;

use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;

class LoginListener {

    public function __construct(){
    }

    public function onSuccessfulLogin(AuthenticationEvent $event)
    {
        $user = $event->getAuthenticationToken()->getUser();
        if($user instanceof AdvancedUserInterface){
            $user->updateLastLogin();
        }
    }

    public function onLoginError(AuthenticationEvent $event)
    {
        // Login error
    }
}

已到达 updateLastLogin 代码,但未在数据库中更新。谁能告诉我我做错了什么?

提前谢谢


@mdma 的答案引导我找到了正确的解决方案,通过他的解决方案,我得到了 Call to a member function getManager() on string 错误。为了解决这个问题,我只是在监听器构造函数中注入(inject)了 EntityManager 并添加了缺少的调用以将数据保留在数据库中:

<?php
namespace AppBundle\EventListener;

use Doctrine\ORM\EntityManager;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;

class LoginListener {

    protected $entityManager;

    public function __construct(EntityManager $entityManager){
        $this->entityManager = $entityManager;
    }

    public function onSuccessfulLogin(AuthenticationEvent $event)
    {
        $user = $event->getAuthenticationToken()->getUser();
        if($user instanceof AdvancedUserInterface){
            $user->updateLastLogin();
            $this->entityManager->persist($user);
            $this->entityManager->flush();
        }
    }

    public function onLoginError(AuthenticationEvent $event)
    {
        // Login error
    }
}

services.yml 文件中,我将其添加为参数:

app.login_service:
    class:        AppBundle\EventListener\LoginListener
    arguments:    ["@doctrine.orm.entity_manager"]
    tags:
        - { name: kernel.event_listener, event: security.authentication.success, method: onSuccessfulLogin }

现在它按预期工作了。

请注意,更新登录日期时用户类中存在拼写错误,我使用的变量不存在。而不是 $this->lastAccess = new\DateTime("now"); 它必须是:

$this->lastLogin = new \DateTime("now");

最佳答案

您正在更新实体类(对象)。要将其保存在数据库中,您应该使用学说管理器服务。

在 Controller 中,您可以执行以下操作:doc

$em = $this->getDoctrine()->getManager();

// tells Doctrine you want to (eventually) save the Product (no queries yet)
$em->persist($product);

// actually executes the queries (i.e. the INSERT query)
$em->flush();

但您不在 Controller 中,因此您可以在构造函数中注入(inject)学说服务并将您的实体保留在事件上。

<?php
namespace AppBundle\EventListener;

use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;

class LoginListener {
    protected $doctrine;

    public function __construct($doctrine){
        $this->doctrine = $doctrine;
    }

    public function onSuccessfulLogin(AuthenticationEvent $event)
    {
        $user = $event->getAuthenticationToken()->getUser();
        if($user instanceof AdvancedUserInterface){
            $user->updateLastLogin();
            $this->doctrine->getManager()->persist($user);
            $this->doctrine->getManager()->flush();
        }
    }

    public function onLoginError(AuthenticationEvent $event)
    {
        // Login error
    }
}

并在您的服务定义中:

services:
    app.login_service:
        class:        AppBundle\EventListener\LoginListener
        arguments:    [doctrine]

关于php - Symfony 3 登录后更新用户数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42401250/

相关文章:

svn - SVN客户端在哪里存储用户认证数据?

Symfony ChoiceType 启用或禁用 TextType

unit-testing - 如何使用 Symfony 在 serviceTest 中模拟 EntityManager?

php - 如何在查询中选择小时和分钟

javascript - Angular:页面标题服务在导航上仍会发生变化

php - <br> 存储在 mysql 字段中,但回显时没有换行符

PHP Uploadprogress 扩展函数总是返回 null,没有上传数据

php - 验证更新表格

php - 为什么即使类和构造函数的大小写不同,我的构造函数仍然被调用?

authentication - 有人可以解释 OIDC 中的 ACR 返回值吗?