首页 > 解决方案 > 在持久化数据之后和刷新数据之前触发 UniqueEntity

问题描述

我正在通过学​​说实体管理器导入一种 csv 数据,但是,我有一个执行批处理的循环,正如在文档级别提到的那样。 https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/batch-processing.html#bulk-inserts

$validationErrors = [];
foreach($data as $itrationNumber => $item) {
    /** @var User|null $user **/
    $user = $this->em->getRepository(User::class)->findOnBy(['email' => $item['email']]);
    $user = ($user) ? $user : new User();
    $user->setName('test');
    $errors = $this->validator->validate($user);
    if ($errors->count() === 0) {
        $this->persist($user);
    } else {
       $validationErrors[] = $errors;
    }
    
    if ($itratioNumber% 100 === 0) {
         $this->em->flush();
    }
}

return $validationErrors;

这是我的用户类,它对电子邮件字段有一个独特的约束:

/**
 * @ORM\Entity
 * @UniqueEntity("email")
 */
class User
{
    /**
     * @ORM\Column(name="email", type="string", length=255, unique=true)
     * @Assert\Email
     */
    protected $email;
}

不幸的是,如果我的数据中有不止一行具有相同的电子邮件地址,UniqueEntity则不会触发验证,原因很简单,因为用户被持久化但没有被刷新到数据库中。

如果用户已经存在于数据库中,并且我们调用 的问题,我在和 中em-> persist()都找不到任何持久对象。$entityManager->getUnitOfWork()->getScheduledEntityInsertions()$entityManager->getUnitOfWork()->getScheduledEntityUpdates()

仅在新插入期间,我洞对象在函数的响应中持续存在->getScheduledEntityInsertions()

如果有人知道如何恢复$entityManager->persist()步骤后仍然存在的实体,我将不胜感激。或者只是第三种解决方案,即使在批处理上下文中,它也允许我触发对电子邮件唯一性的验证。

标签: symfonydoctrine

解决方案


您应该保留第二点信息,以查看电子邮件地址是否已被处理:

$emails = [];
foreach($data as $itrationNumber => $item) {
    if (isset($emails[$item['email']])) {
        continue;
    }

    /** @var User|null $user **/
    $user = $this->em->getRepository(User::class)->findOnBy(['email' => $item['email']]);
    $user = ($user) ? $user : new User();
    $user->setName('test');
    if ($this->validator->validate($user)->count() === 0) {
        $this->persist($user);
        $emails[$item['email']] = true;
    }
    
    if ($itratioNumber% 100 === 0) {
         $this->em->flush();
    }
}

此代码片段不会规范化电子邮件地址,这应该首先完成(例如 strtolower 并且可能删除 +foo gmail 本地部分)。


推荐阅读