douzuo5504 2016-09-22 11:54
浏览 48
已采纳

handleRequest()交换后的表单集合数据

I have embed a collection of forms by symfony tutorial. Everything works, except existing entity removal.

Initial data:

+----+-------+
| id | value |
+----+-------+
| 1  | a     |
+----+-------+
| 2  | b     |
+----+-------+
| 3  | c     |
+----+-------+

Then in collection form i remove a value form. After submitting and handleRequest(), the data became:

+----+-------+
| id | value |
+----+-------+
| 1  | b     |
+----+-------+
| 2  | c     |
+----+-------+

Looks like handleRequest() is just overriding array collection values and removing all the diffs. The expected result should be:

+----+-------+
| id | value |
+----+-------+
| 2  | b     |
+----+-------+
| 3  | c     |
+----+-------+

So why is this happening?

Controller:

public function indexAction(Request $request, Agreement $agreement)
{
    $form = $this
        ->createForm(CostGroupsCollectionType::class, $agreement)
        ->add('submit', SubmitType::class, ['label' => 'button.save']);
    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->flush();

        return $this->redirectToRoute('team_agreements_cost_groups', ['id' => $agreement->getId()]);
    }

    return array(
        'form' => $form->createView(),
        'agreement' => $agreement
    );
}

CostGroupsCollectionType:

class CostGroupsCollectionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('costGroups', CollectionType::class, [
            'label' => false,
            'entry_type' => CostGroupType::class,
            'cascade_validation' => true,
            'allow_add'    => true,
            'allow_delete' => true,
            'prototype'    => true,
            'by_reference' => false,
            'attr'         => array(
                'class' => 'form-collection',
            ),
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'Nfq\TeamBundle\Entity\Agreement',
            'cascade_validation' => true
        ]);
    }

    public function getName()
    {
        return 'nfq_team_bundle_cost_groups_collection_type';
    }
}

CostGroupType:

class CostGroupType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        /** @var EmployeeRepository $employeeRepo */
        $employeeRepo = $options['employeesRepo'];

        $builder
            ->add('costGroupPosition', EntityType::class, [
                'label' => 'teams.cost_group.title',
                'class' => 'Nfq\TeamBundle\Entity\CostGroupPosition',
                'attr' => ['class' => 'autocomplete'],
                'choice_label' => 'title',
                'multiple' => false,
                'required' => true
            ])
            ->add('price', NumberType::class, [
                'label' => 'teams.cost_group.price',
                'required' => true
            ])
            ->add('employees', EntityType::class, [
                'label' => 'teams.cost_group.employees',
                'class'=> 'Nfq\ResourcesBundle\Entity\Employee',
                'attr' => ['class' => 'autocomplete-unique'],
                'choice_label' => function ($employee) {
                    /** @var Employee $employee */
                    return $employee->getFullName();
                },
                'multiple'  => true,
                'required' => false
            ])
            ->add('currency', EntityType::class, [
                'label' => 'currency.single_title',
                'class' => Currency::class,
                'choice_label' => function (Currency $c) {
                    return $c->getName();
                },
                'multiple' => false,
                'expanded' => false,
                'empty_data' => 'null',
                'placeholder' => 'misc.selectAValue',
                'required' => true
            ])
            ->add('exchangeRate', NumberType::class, [
                'label' => 'teams.dedicated.invoices.details.exchange_rate',
                'required' => true,
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'Nfq\TeamBundle\Entity\CostGroup'
        ]);
    }

    public function getName()
    {
        return 'nfq_team_bundle_cost_group_type';
    }
}

Agreement

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

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

    /**
     * @ORM\ManyToOne(targetEntity="Nfq\ClientsBundle\Entity\Company", inversedBy="agreements")
     * @ORM\JoinColumn(name="Company_id", referencedColumnName="id")
     */
    private $client;

    /**
     * @ORM\ManyToOne(targetEntity="Nfq\ResourcesBundle\Entity\Team", inversedBy="agreements")
     * @ORM\JoinColumn(name="Team_id", referencedColumnName="id")
     */
    private $team;

    /**
     * @ORM\ManyToOne(targetEntity="Nfq\UserBundle\Entity\User", inversedBy="agreements")
     * @ORM\JoinColumn(name="User_id", referencedColumnName="id")
     */
    private $assignee;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="start_date", type="date")
     */
    private $startDate;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="end_date", type="date", nullable=true)
     */
    private $endDate;

    /**
     * @var bool
     *
     * @ORM\Column(name="ended", type="boolean")
     */
    private $ended;

    /**
     * @ORM\OneToOne(targetEntity="Nfq\TeamBundle\Entity\Requisites", mappedBy="agreement")
     */
    private $requisites;

    /**
     * @ORM\OneToMany(targetEntity="Nfq\TeamBundle\Entity\CostGroup", mappedBy="agreement",
     *     cascade={"all"}, orphanRemoval=true)
     */
    private $costGroups;

    /**
     * @ORM\OneToMany(targetEntity="Nfq\TeamBundle\Entity\DedicatedInvoice", mappedBy="agreement")
     */
    private $dedicatedInvoices;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->ended = false;
        $this->costGroups = new \Doctrine\Common\Collections\ArrayCollection();
        $this->dedicatedInvoices = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get id.
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title.
     *
     * @param string $title
     *
     * @return Agreement
     */
    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

    /**
     * Get title.
     *
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set startDate.
     *
     * @param \DateTime $startDate
     *
     * @return Agreement
     */
    public function setStartDate($startDate)
    {
        $this->startDate = $startDate;

        return $this;
    }

    /**
     * Get startDate.
     *
     * @return \DateTime
     */
    public function getStartDate()
    {
        return $this->startDate;
    }

    /**
     * Set endDate.
     *
     * @param \DateTime $endDate
     *
     * @return Agreement
     */
    public function setEndDate($endDate)
    {
        $this->endDate = $endDate;

        return $this;
    }

    /**
     * Get endDate.
     *
     * @return \DateTime
     */
    public function getEndDate()
    {
        return $this->endDate;
    }

    /**
     * Set ended.
     *
     * @param boolean $ended
     *
     * @return Agreement
     */
    public function setEnded($ended)
    {
        $this->ended = $ended;

        return $this;
    }

    /**
     * Get ended.
     *
     * @return boolean
     */
    public function getEnded()
    {
        return $this->ended;
    }

    /**
     * Set client.
     *
     * @param \Nfq\ClientsBundle\Entity\Company $client
     *
     * @return Agreement
     */
    public function setClient(\Nfq\ClientsBundle\Entity\Company $client = null)
    {
        $this->client = $client;

        return $this;
    }

    /**
     * Get client.
     *
     * @return \Nfq\ClientsBundle\Entity\Company
     */
    public function getClient()
    {
        return $this->client;
    }

    /**
     * Set team.
     *
     * @param \Nfq\ResourcesBundle\Entity\Team $team
     *
     * @return Agreement
     */
    public function setTeam(\Nfq\ResourcesBundle\Entity\Team $team = null)
    {
        $this->team = $team;

        return $this;
    }

    /**
     * Get team.
     *
     * @return \Nfq\ResourcesBundle\Entity\Team
     */
    public function getTeam()
    {
        return $this->team;
    }

    /**
     * Set assignee.
     *
     * @param User $assignee
     *
     * @return Agreement
     */
    public function setAssignee(User $assignee = null)
    {
        $this->assignee = $assignee;

        return $this;
    }

    /**
     * Get assignee.
     *
     * @return User
     */
    public function getAssignee()
    {
        return $this->assignee;
    }

    /**
     * Set requisites.
     *
     * @param \Nfq\TeamBundle\Entity\Requisites $requisites
     *
     * @return Agreement
     */
    public function setRequisites(\Nfq\TeamBundle\Entity\Requisites $requisites = null)
    {
        $this->requisites = $requisites;

        return $this;
    }

    /**
     * Get requisites.
     *
     * @return \Nfq\TeamBundle\Entity\Requisites
     */
    public function getRequisites()
    {
        return $this->requisites;
    }

    /**
     * Add costGroup.
     *
     * @param \Nfq\TeamBundle\Entity\CostGroup $costGroup
     *
     * @return Agreement
     */
    public function addCostGroup(\Nfq\TeamBundle\Entity\CostGroup $costGroup)
    {
        if (!$this->costGroups->contains($costGroup)) {
            $this->costGroups->add($costGroup);
        }
        $costGroup->setAgreement($this);

        return $this;
    }

    /**
     * Remove costGroup.
     *
     * @param \Nfq\TeamBundle\Entity\CostGroup $costGroup
     */
    public function removeCostGroup(\Nfq\TeamBundle\Entity\CostGroup $costGroup)
    {
        if ($this->costGroups->contains($costGroup)) {
            $this->costGroups->removeElement($costGroup);
        }
        $costGroup->setAgreement(null);
    }

    /**
     * Get costGroups.
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getCostGroups()
    {
        return $this->costGroups;
    }

    /**
     * Add dedicatedInvoice.
     *
     * @param \Nfq\TeamBundle\Entity\DedicatedInvoice $dedicatedInvoice
     *
     * @return Agreement
     */
    public function addDedicatedInvoice(\Nfq\TeamBundle\Entity\DedicatedInvoice $dedicatedInvoice)
    {
        $this->dedicatedInvoices[] = $dedicatedInvoice;

        return $this;
    }

    /**
     * Remove dedicatedInvoice.
     *
     * @param \Nfq\TeamBundle\Entity\DedicatedInvoice $dedicatedInvoice
     */
    public function removeDedicatedInvoice(\Nfq\TeamBundle\Entity\DedicatedInvoice $dedicatedInvoice)
    {
        $this->dedicatedInvoices->removeElement($dedicatedInvoice);
    }

    /**
     * Get dedicatedInvoices.
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getDedicatedInvoices()
    {
        return $this->dedicatedInvoices;
    }
}

CostGroup

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

    /**
     * @var float
     *
     * @ORM\Column(name="price", type="decimal", precision=10, scale=2)
     */
    private $price;

    /**
     * @ORM\ManyToOne(targetEntity="Nfq\TeamBundle\Entity\Agreement", inversedBy="costGroups")
     * @ORM\JoinColumn(name="Agreement_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private $agreement;

    /**
     * @ORM\ManyToOne(targetEntity="Nfq\TeamBundle\Entity\CostGroupPosition", inversedBy="costGroups")
     * @ORM\JoinColumn(name="cost_group_position_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private $costGroupPosition;

    /**
     * @ORM\ManyToMany(targetEntity="Nfq\ResourcesBundle\Entity\Employee", inversedBy="costGroups")
     * @ORM\JoinTable(name="cost_group_employee")
     */
    private $employees;

    /**
     * @ORM\OneToMany(targetEntity="Nfq\TeamBundle\Entity\DedicatedEmployees", mappedBy="costGroup")
     */
    private $dedicatedEmployees;

    /**
     * @var float
     * @ORM\Column(name="exchange_rate", type="float", nullable=true)
     */
    private $exchangeRate;

    /**
     * @var Currency
     * @ORM\ManyToOne(targetEntity="Nfq\SettingsBundle\Entity\Currency", inversedBy="costGroups")
     * @ORM\JoinColumn(name="Currency_id", referencedColumnName="id")
     */
    private $currency;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->employees = new \Doctrine\Common\Collections\ArrayCollection();
        $this->dedicatedEmployees = new \Doctrine\Common\Collections\ArrayCollection();
        $this->exchangeRate = 1;
    }

    /**
     * Get id.
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set price.
     *
     * @param string $price
     *
     * @return CostGroup
     */
    public function setPrice($price)
    {
        $this->price = $price;

        return $this;
    }

    /**
     * Get price.
     *
     * @return string
     */
    public function getPrice()
    {
        return $this->price;
    }

    /**
     * Set agreement.
     *
     * @param \Nfq\TeamBundle\Entity\Agreement $agreement
     *
     * @return CostGroup
     */
    public function setAgreement(\Nfq\TeamBundle\Entity\Agreement $agreement = null)
    {
        $this->agreement = $agreement;

        return $this;
    }

    /**
     * Get agreement.
     *
     * @return \Nfq\TeamBundle\Entity\Agreement
     */
    public function getAgreement()
    {
        return $this->agreement;
    }

    /**
     * Set costGroupPosition.
     *
     * @param \Nfq\TeamBundle\Entity\CostGroupPosition $costGroupPosition
     *
     * @return CostGroup
     */
    public function setCostGroupPosition(\Nfq\TeamBundle\Entity\CostGroupPosition $costGroupPosition = null)
    {
        $this->costGroupPosition = $costGroupPosition;

        return $this;
    }

    /**
     * Get costGroupPosition.
     *
     * @return \Nfq\TeamBundle\Entity\CostGroupPosition
     */
    public function getCostGroupPosition()
    {
        return $this->costGroupPosition;
    }

    /**
     * Add employee.
     *
     * @param \Nfq\ResourcesBundle\Entity\Employee $employee
     *
     * @return CostGroup
     */
    public function addEmployee(\Nfq\ResourcesBundle\Entity\Employee $employee)
    {
        $this->employees[] = $employee;

        return $this;
    }

    /**
     * Remove employee.
     *
     * @param \Nfq\ResourcesBundle\Entity\Employee $employee
     */
    public function removeEmployee(\Nfq\ResourcesBundle\Entity\Employee $employee)
    {
        $this->employees->removeElement($employee);
    }

    /**
     * Get employees.
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getEmployees()
    {
        return $this->employees;
    }

    /**
     * Add dedicatedEmployee.
     *
     * @param \Nfq\TeamBundle\Entity\DedicatedEmployees $dedicatedEmployee
     *
     * @return CostGroup
     */
    public function addDedicatedEmployee(\Nfq\TeamBundle\Entity\DedicatedEmployees $dedicatedEmployee)
    {
        $this->dedicatedEmployees[] = $dedicatedEmployee;

        return $this;
    }

    /**
     * Remove dedicatedEmployee.
     *
     * @param \Nfq\TeamBundle\Entity\DedicatedEmployees $dedicatedEmployee
     */
    public function removeDedicatedEmployee(\Nfq\TeamBundle\Entity\DedicatedEmployees $dedicatedEmployee)
    {
        $this->dedicatedEmployees->removeElement($dedicatedEmployee);
    }

    /**
     * Get dedicatedEmployees.
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getDedicatedEmployees()
    {
        return $this->dedicatedEmployees;
    }

    /**
     * Set exchangeRate.
     *
     * @param float $exchangeRate
     *
     * @return CostGroup
     */
    public function setExchangeRate($exchangeRate)
    {
        $this->exchangeRate = $exchangeRate;

        return $this;
    }

    /**
     * Get exchangeRate.
     *
     * @return float
     */
    public function getExchangeRate()
    {
        return $this->exchangeRate;
    }

    /**
     * Set currency.
     *
     * @param Currency $currency
     *
     * @return CostGroup
     */
    public function setCurrency(Currency $currency = null)
    {
        $this->currency = $currency;

        return $this;
    }

    /**
     * Get currency.
     *
     * @return Currency
     */
    public function getCurrency()
    {
        return $this->currency;
    }
}
  • 写回答

1条回答 默认 最新

  • duangu6588 2016-09-22 13:01
    关注

    See the documentation how to handle correctly persisting of ArrayCollection with Doctrine.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 个人网站被恶意大量访问,怎么办
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制