在Symfony 3中登录后更新用户数据

时间:2017-02-22 20:07:13

标签: php login 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错误。为了解决这个问题,我只是在监听器构造函数中注入了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");

1 个答案:

答案 0 :(得分:4)

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

在控制器中,您可以执行以下操作: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();

但您不在控制器中,因此您可以在构造函数中注入doctrine服务并将您的实体保留在事件中。

<?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]