Symfony唯一违规.....密钥xxxxx已经存在

时间:2017-08-07 12:19:21

标签: symfony doctrine

我被要求收回几个月前离开公司的人的代码。 他开发了一个应用程序,允许一些人要求更改防火墙规则 当tou询问更改时,您可以选择/填写: 防火墙名称(对应防火墙接口) 港口 来源地址 目的地址 服务类型(TCP / UDP / ICMP)

数据库中有两个表:

Rule                                         FW
----------                                   ---------
ID                                           ID
Fw_Id                                        Name
idrule                                       Description
Port                                         ----------
Source Address 
Destination Adress
Service Type
----------

只有1个防火墙/规则和1个规则/防火墙

当我尝试保存表单时出现问题,doctrine尝试保存所有防火墙信息,而不仅仅是id,并告诉他们有一个唯一的密钥违规。 我搜索但无法弄清楚错误

规则实体:

<?php

namespace FWBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
* Rule
*
* @ORM\Table(name="rule", uniqueConstraints={@ORM\UniqueConstraint(name="unique_fw_id", columns={"fw_id", "idrule"})})
* @ORM\Entity(repositoryClass="FwBundle\Repository\ruleRepository")
* @UniqueEntity(fields={"fw","idrule"}, message="Rule already exists")
*/

class Rule
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

     /**
     * @ORM\OneToOne(targetEntity="FwBundle\Entity\fw")
     * @ORM\JoinColumn(name="fw_id",referencedColumnName="id")
     * @Assert\Valid()
     */
    private $fw;

    /**
     * @var int
     *
     * @ORM\Column(name="idrule", type="integer")
     */
    private $idrule;

FW实体:

<?php

namespace FWBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;


/**
 * fw
 *
 * @ORM\Table(name="fw")
 * @ORM\Entity(repositoryClass="FWBundle\Repository\FwRepository")
 * @UniqueEntity(fields="name", message="Firewall already exists.")
 */
class Fw
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

RuleController:

public function AddAction($id,Request $request)
{
    $namespace = 'FwBundle';
    $em = thiss->getDoctrine()->getManager();
    $repositoryRule = $em->getRepository($namespace.':Rule');
    $repositoryFw = $em->getRepository($namespace.':Fw');

    $rule = new rule();

    $form = $this->createForm(RuleType::class, $rule,array('fw'=>$id));
    $form->handleRequest($request);
        if    ($form->isSubmitted() && $form->isValid()) {
            $rule = $form->getData();
            $em->persist($rule);
            $em->flush();
        }
}

1 个答案:

答案 0 :(得分:0)

Rule只能与一个Firewall相关联,而一个Firewall只能与一个Rule相关联。您要做的是将多个Rule链接到一个Firewall

您应该考虑将OneToOne关系更改为ManyToOne,因为防火墙可能有很多规则,错误应该消失(您必须先更新数据库架构)

如果您确定OneToOne是您想要的那个,则如果防火墙已有一个规则,则不应在表单中创建新规则。

您的代码应与此类似:

public function AddAction($id,Request $request)
{
    $namespace = 'FwBundle';
    $em = thiss->getDoctrine()->getManager();
    $repositoryRule = $em->getRepository($namespace.':Rule');
    $repositoryFw = $em->getRepository($namespace.':Fw');

    $rule = new rule(); // remove this line and change it with the two lines below
    $fw = $repositoryFw->find($id); // assuming that id is the id of firewall
    $rule = $fw->getRule() ? : new Rule(); // if Firewall has a rule entity then take it otherwise create a new one. 

    $form = $this->createForm(RuleType::class, $rule,array('fw'=>$id));
    $form->handleRequest($request);
        if    ($form->isSubmitted() && $form->isValid()) {
            $rule = $form->getData();
            $em->persist($rule);
            $em->flush();
        }
}