【问题标题】:Symfony - Update a unique OneToMany relation propertySymfony - 更新唯一的 OneToMany 关系属性
【发布时间】:2018-07-09 14:42:09
【问题描述】:

一家公司可以有多个电子邮件,并且所有电子邮件都必须是唯一的。
这是 Company 和 CompanyEmail 的我的实体

公司电子邮件实体:

/**
 * @ORM\Entity(repositoryClass="App\Repository\CompanyEmailRepository")
 * @UniqueEntity("name")
 */
class CompanyEmail
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=128, unique=true)
     * @Assert\Email()
     */
    private $name;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Company", inversedBy="emails")
     * @ORM\JoinColumn(nullable=false)
     */
    private $company;

    // ...
}

公司实体:

/**
 * @ORM\Entity(repositoryClass="App\Repository\CompanyRepository")
 */
class Company
{
    // ...

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\CompanyEmail", mappedBy="company", orphanRemoval=true, cascade={"persist"})
     * @Assert\Valid
     */
    private $emails;

    // ...
}

我正在使用一个自定义 EmailsInputType,它使用了这个 DataTransformer

class EmailArrayToStringTransformer implements DataTransformerInterface
{
    public function transform($emails): string
    {
        return implode(', ', $emails);
    }


    public function reverseTransform($string): array
    {
        if ($string === '' || $string === null) {
            return [];
        }

        $inputEmails = array_filter(array_unique(array_map('trim', explode(',', $string))));

        $cEmails = [];
        foreach($inputEmails as $email){
            $cEmail = new CompanyEmail();
            $cEmail->setName($email);
            $cEmails[] = $cEmail;
        }

        return $cEmails;
    }
}

并且在Controller中使用这个编辑方法

/**
     * @Route("/edit/{id}", name="admin_company_edit", requirements={"id": "\d+"}, methods={"GET", "POST"})
     */
    public function edit(Request $request, $id): Response
    {
        $entityManager = $this->getDoctrine()->getManager();
        $company = $entityManager->getRepository(Company::class)->find($id);

        $form = $this->createForm(CompanyType::class, $company);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $entityManager->flush();
        }
    }

这段代码有两个问题

1 - 在编辑表单中,当我尝试保留已保存的电子邮件时,Symfony 会生成一个验证错误,告知该电子邮件已退出。

2 - 当我从代码中删除验证限制时,Symfony 抛出数据库错误“*完整性约束违规:1062 Duplicate entry ... *”

我应该怎么做才能让我的代码按预期工作!

【问题讨论】:

  • 这个问题一点都不清楚:你需要什么,有什么问题?即:当您更新实体而不添加任何电子邮件时显示的错误(无论是什么)(只是试图猜测这里的问题是什么)。请提供用例的准确描述以及现有代码失败的场景的准确描述。谢谢。
  • 对不起,我尽力说明我的问题,但是我的英语太差了,我会再试一次
  • DonCallisto 假设我们有一个公司实体已经有两封电子邮件,当我尝试更新实体而不更改电子邮件(保持相同的旧电子邮件)时,@UnqiueEntity 约束的验证错误将是显示,这就是 Symfony 不知道我正在尝试更新而不是插入的问题!

标签: php symfony doctrine-orm


【解决方案1】:

问题就在这里

public function reverseTransform($string): array
{
  [...]

  foreach($inputEmails as $email){
    $cEmail = new CompanyEmail();
    [...]
  }

  [...]
}

您需要检索email 而不是创建新的。 所以基本上,注入一个CompanyEmailRepository,尝试查找电子邮件是否已经存在(findOneBy(['name'])),如果它不存在,则创建一个新的,但如果存在,使用你检索到的。

只有几个注释

  • 注意电子邮件所有者(所以我猜应该按用户进行检索,因为没有人可以共享相同的邮件,除非您可以指定一些别名或共享地址)
  • 也许您不需要像CompanyEmail 这样的额外实体,因为您可以使用json 字段以逗号分隔的方式存储它们(除非您需要一些额外的参数或除非您需要执行一些索引/查询邮件的操作)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-27
    • 1970-01-01
    • 2023-04-05
    • 2014-09-27
    • 1970-01-01
    • 2019-06-29
    • 2018-06-01
    • 2011-11-27
    相关资源
    最近更新 更多