$$-> getUser()不起作用/ Doctrine尝试创建新记录而不是更新现有记录

问题描述 投票:-1回答:1

我用$user = $this->getUser();获得了当前用户。在接下来的几行中,我将更改实体的一个字段(字段= forename)。当我坚持使用此$user实体时,Doctrine会尝试使用insert

非工作代码(试图插入新用户):

$user = $this->getUser();
$user->setForename('test');
$entityManager->persist($user);
$entityManager->flush();

正在工作(原则正在更新当前实体$user2):

$user = $this->getUser();
$user2 = $entityManager->getRepository(User::class)->find($user->getId());
$user->setForename('test');
$entityManager->persist($user2);
$entityManager->flush();

Symfony 4.4,默认配置。

用户提供者

namespace App\Security;

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class UserProvider implements UserProviderInterface
{

    private $entityManager;

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

    public function loadUserByUsername($username)
    {
        return $this->entityManager->getRepository(User::class)
            ->findOneBy([
                'email' => $username,
            ]);
    }

    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(sprintf('Invalid user class "%s".', get_class($user)));
        }

        $fetchedUser = $this->loadUserByUsername($user->getEmail());

        if ($fetchedUser->getId() == $user->getId()) {
            return $user;
        }

        return $user;
    }

    public function supportsClass($class)
    {
        return User::class === $class;
    }
}
php symfony doctrine
1个回答
0
投票

您不是在更改来自Doctrine的用户实体对象,而是在会话中每个请求开始时读取的用户实体对象。

由于该特定实例尚未从您的存储层读取],因此,Doctrine根本不会对其进行跟踪。因此,不会保留对该实体的任何更改。

(并且正如其他用户所提到的,如果您使用正确的实例,则无论如何,调用persist()都是多余的。

问题来自您的UserProvider::refreshUser()方法。

public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(sprintf('Invalid user class "%s".', get_class($user)));
        }

        $fetchedUser = $this->loadUserByUsername($user->getEmail());

        if ($fetchedUser->getId() == $user->getId()) {
            return $user;
        }

        return $user;
    }

此方法接收UserInterface的实例,该实例已从session

存储反序列化。

docs

在每个请求结束时(除非您的防火墙是无状态的),您的User对象都被序列化到会话。在下一个请求的开始,它会反序列化,然后传递给您的用户提供程序以“刷新”它(例如,针对新用户的教义查询)。

然后,将两个“用户”对象(会话中的原始对象和刷新的用户对象)进行“比较”,以查看它们是否“相等”。

您正在做一个非常简单的比较(检查它们是否具有相同的ID,而不是检查对象是否具有任何其他更改)。

但是您的方法返回的用户是从会话中读取的原始用户,而不是来自Doctrine的用户。那就是您的脚本$fetchedUser

如果您只是返回那个那个

而不是$userreturn $fetchedUser;),您的代码可能会按预期工作(尽管再次,您可以在不调用persist()的情况下执行此操作,因为该对象已经被跟踪了)学说)。
© www.soinside.com 2019 - 2024. All rights reserved.