【问题标题】:Doctrine - using ManyToMany with additional fields and want to save more than one row in association tableDoctrine - 使用带有附加字段的 ManyToMany 并希望在关联表中保存多行
【发布时间】:2021-12-05 15:55:32
【问题描述】:

我开始通过使用多对多关系和教义来建立数据库。 我切换到另一种方法,因为我需要关联表中的其他字段。 我正在使用 symfony 5

我拥有 3 个实体:

namespace App\Entity;

use App\Repository\TemplateRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=TemplateRepository::class)
 * @ORM\Table(options={"collate"="utf8mb4_general_ci"})
 */
class Template
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity=TemplateSection::class, mappedBy="section", cascade={"persist"})
     */
    private $sections;

    ....
}


namespace App\Entity;

use App\Repository\SectionRepository;
use App\DBAL\Types\SectionElementType;
use Doctrine\ORM\Mapping as ORM;
use Fresh\DoctrineEnumBundle\Validator\Constraints as DoctrineAssert;

/**
 * @ORM\Entity(repositoryClass=SectionRepository::class)
 * @ORM\Table(options={"collate"="utf8mb4_general_ci"})
 */
class Section
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity=TemplateSection::class, mappedBy="template")
     */
    private $template;

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

    ....

}


namespace App\Entity;

use App\Repository\TemplateSectionRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=TemplateSectionRepository::class)
 * @ORM\Table(options={"collate"="utf8mb4_general_ci"})
 */
class TemplateSection
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity=Template::class, inversedBy="id", cascade={"persist"})
     * @ORM\JoinColumn(nullable=false)
     */
    private $template;

    /**
     * @ORM\ManyToOne(targetEntity=Section::class, inversedBy="id", cascade={"persist"})
     * @ORM\JoinColumn(nullable=false)
     */
    private $section;

    /**
     * @ORM\Column(type="smallint", options={"default": "0"})
     */
    private $sortOrder;

    ....

}

我有一个可以为模板定义新条目的表单。有一个字段secInput,我可以在其中定义多个要在此模板中使用的部分。 在 secInput 中是一个逗号分隔的值(Ids)列表,用于所选部分。

当我尝试保存表单时,只有最后一条记录保存在Template.sections

要将所有给定数据保存到数据库中,我需要进行哪些更改?

我在 TemplateController 中的代码:



    /**
     * @Route("/new", name="adminTemplateNew", methods={"GET","POST"})
     */
    public function new(Request $request): Response
    {
        $template = new Template();
        $form = $this->createForm(TemplateType::class, $template);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $entityManager = $this->getDoctrine()->getManager();
            $data = $form->getData();
            $repo = $entityManager->getRepository(Section::class);
            $templateSection = new TemplateSection();
            $template->setCreatedAt(new DateTime('NOW'));

            $sections = explode(',', $form->get('secInput')->getData());
            $count = 1;
            foreach ($sections as $secId) {
                if ( null !== $section = $repo->find($secId) ) {
                    $templateSection->setSortOrder($count);
                    $templateSection->setTemplate($template);
                    $templateSection->setSection($section);
                    $template->addSection($templateSection);
                    $entityManager->persist($templateSection);
                    $count++;
                }
            }

            $entityManager->persist($templateSection);
            $entityManager->persist($template);
            $entityManager->flush();

            return $this->redirectToRoute('template_index', ['data' => $data], Response::HTTP_SEE_OTHER);
        }

【问题讨论】:

    标签: php symfony doctrine-orm doctrine many-to-many


    【解决方案1】:

    您正在遍历选定的部分并在不保存的情况下覆盖它们。当您调用$entityManager->persist($templateSection) 时,您告诉EntityManager 跟踪它,但最终,当您调用$entityManager->flush() 时,只有一个对象被持久化。而且恰好是最新的数据。

    尝试构造一个新对象并将其持久化,如下所示:

        public function new(Request $request): Response
        {
            $form = $this->createForm(TemplateType::class, $template);
            $form->handleRequest($request);
    
            if ($form->isSubmitted() && $form->isValid()) {
                $entityManager = $this->getDoctrine()->getManager();
                $data = $form->getData();
                $repo = $entityManager->getRepository(Section::class);
    
                $template = new Template();
                $template->setCreatedAt(new DateTime('NOW'));
    
                $sections = explode(',', $form->get('secInput')->getData());
                $count = 1;
                foreach ($sections as $secId) {
                    if ( null !== $section = $repo->find($secId) ) {
                        $templateSection = new TemplateSection(); // This is new
                        $templateSection->setSortOrder($count);
                        $templateSection->setTemplate($template);
                        $templateSection->setSection($section);
                        $template->addSection($templateSection);
                        $entityManager->persist($templateSection);
                        $count++;
                    }
                }
    
                $entityManager->persist($template);
                $entityManager->flush();
    
                return $this->redirectToRoute('template_index', ['data' => $data], Response::HTTP_SEE_OTHER);
            }
    
    

    【讨论】:

    • 如此真实和明显被我自己的代码蒙蔽了双眼。效果很好,非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多