【问题标题】:Symfony OneToMany updates instead of insertSymfony OneToMany 更新而不是插入
【发布时间】:2018-08-22 15:55:04
【问题描述】:

我是 Symfony 的初学者。

我的表单中有一个奇怪的问题。

我有 2 个实体:Proposal_Lsi 和 Lsi_Beams。一个提案可以有多个波束,但一个波束只能有一个提案。我想我应该使用 OneToMany/ManyToOne 关系,我拥有的一方是梁一方,反方是提案。

我按照https://symfony.com/doc/3.1/form/form_collections.html 上关于表单集合的官方指南进行操作。

一切都很好,我可以提交一个带有多个光束的新提案,并且所有内容都正确存储在数据库中。

每当我尝试向我的提案添加新梁时,就会出现问题:系统会覆盖(更新查询)现有梁(从数据库中的第一个梁开始)而不是添加新梁(插入查询)。

我错过了什么?

这是我的一些代码,如果有帮助的话。

提案类别:

class Proposal_lsi{
/**
* @ORM\OneToOne(targetEntity="Emir2Bundle\Entity\Proposal", inversedBy="proposal_lsi")
* @ORM\JoinColumn(name="proposal", referencedColumnName="id")
* @ORM\Id
*/  
private $proposal;

/**
* @ORM\OneToMany(targetEntity="Emir2Bundle\Entity\Lsi_beams", mappedBy="proposal_lsi")
*/  
private $lsi_beams;

...

/**
 * Add lsiBeam
 *
 * @param \Emir2Bundle\Entity\Lsi_beams $lsiBeam
 * @return Proposal_lsi
 */
public function addLsiBeam(\Emir2Bundle\Entity\Lsi_beams $lsiBeam)
{
    $lsiBeam->setProposalLsi($this);
    $this->lsi_beams[] = $lsiBeam;

    return $this;
}

}

梁类:

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

/**
* @ORM\ManyToOne(targetEntity="Emir2Bundle\Entity\Proposal_lsi", inversedBy="lsi_beams", cascade={"persist"})
* @ORM\JoinColumn(name="proposal_lsi", referencedColumnName="proposal", nullable=false)
*/
private $proposal_lsi;

...
}

以及控制器中的表单:

$form = $this->createFormBuilder($proposallsi)
        ->setAction($this->generateUrl('lsi_submission', array('id' => $id)))
        ->setMethod('POST')
        ->add('lsi_beams', CollectionType::class, array(
            'entry_type'    => LsiBeamsType::class,
            'allow_add'     => true,
            'allow_delete'      => true,
            'prototype'     => true,
            'by_reference'  => false
            )
        )
...

我做错了什么?如果您需要更多代码,请告诉我。

感谢您的回复!

【问题讨论】:

  • 您是否正在渲染已保存的选项?如果它们没有与表单一起提交,它们将被删除。
  • 晚上好,stackoverflow.com/a/49028183/4350745 这将有助于您的映射和实体,之后您的人口和持久性将是好的 :)
  • @l13 恐怕这无济于事,因为我使用注释。如果我与我所拥有的相比,它是相似的。谢谢。
  • @s-gregoire Okey,我不确定,但你能不能试试这个改变并说问题仍然存在@ORM\ManyToOne(targetEntity="Emir2Bundle\Entity\Proposal_lsi", inversedBy="lsi_beams", cascade={"persist"}, fetch="EAGER"}

标签: php symfony symfony-forms symfony-3.1


【解决方案1】:

注意事项:

  1. 使用 Doctrine ArrayCollection 更好地跟踪收藏
  2. cascade={"persist"} 放在关联的反面(您有mappedBy
  3. 保持实体名称单数(例如 Lsi_beam 而不是 Lsi_beams
  4. 保持您的命名策略清晰和严格。不要在你的类名和属性名中使用反分线(例如,使用 $lsiBeams 而不是 $lsi_beams)

提案

use Doctrine\Common\Collections\ArrayCollection;

class ProposalLsi
{
    /**
    * @ORM\OneToMany(targetEntity="LsiBeam", mappedBy="proposalLsi", cascade={"persist"})
    */  
    private $lsiBeams;

    public function __construct()
    {
        $this->lsiBeams = new ArrayCollection();
    }

    public function addLsiBeam(LsiBeams $lsiBeam)
    {
        if ($this->lsiBeams->contains($lsiBeam)) {

            return;
        } else {

            $lsiBeam->setProposalLsi($this);
            $this->lsiBeams->add($lsiBeam);
        }
    
        return $this;
    }

    public function removeLsiBeam(LsiBeams $lsiBeam)
    {
        if (!$this->lsiBeams->contains($lsiBeam)) {

            return;
        } else {

            $lsiBeam->setProposalLsi(null);
            $this->lsiBeams->removeElement($lsiBeam);
        }
    
        return $this;
    }
}

LsiBeam

class LsiBeam
{
    /**
    * @ORM\ManyToOne(targetEntity="ProposalLsi", inversedBy="lsiBeams")
    */
    private $proposalLsi;

    public function setProposalLsi(?ProposalLsi $proposalLsi)
    {
        $this->proposalLsi = $proposalLsi;
    }

}

【讨论】:

  • 感谢您的帮助。以后我会尽量坚持你的编码建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-15
  • 1970-01-01
  • 2013-06-28
  • 2019-07-20
  • 2021-07-19
  • 2014-05-18
相关资源
最近更新 更多