Доктрина — использует множество различных дополнительных полей и хочет сохранить более одной строки в ассоциативной таблице

#php #symfony #doctrine-orm #doctrine #many-to-many

Вопрос:

Я начал создавать базу данных, используя множество связей с доктриной. Я переключился на другой подход, потому что мне нужны были дополнительные поля в таблице ассоциаций. Я использую symfony 5

Я имею в виду 3 Сущности:

 namespace AppEntity;  use AppRepositoryTemplateRepository; use DoctrineCommonCollectionsArrayCollection; use DoctrineCommonCollectionsCollection; use DoctrineORMMapping as ORM;  /**  * @ORMEntity(repositoryClass=TemplateRepository::class)  * @ORMTable(options={"collate"="utf8mb4_general_ci"})  */ class Template {  /**  * @ORMId  * @ORMGeneratedValue  * @ORMColumn(type="integer")  */  private $id;   /**  * @ORMOneToMany(targetEntity=TemplateSection::class, mappedBy="section", cascade={"persist"})  */  private $sections;   .... }   namespace AppEntity;  use AppRepositorySectionRepository; use AppDBALTypesSectionElementType; use DoctrineORMMapping as ORM; use FreshDoctrineEnumBundleValidatorConstraints as DoctrineAssert;  /**  * @ORMEntity(repositoryClass=SectionRepository::class)  * @ORMTable(options={"collate"="utf8mb4_general_ci"})  */ class Section {  /**  * @ORMId  * @ORMGeneratedValue  * @ORMColumn(type="integer")  */  private $id;   /**  * @ORMOneToMany(targetEntity=TemplateSection::class, mappedBy="template")  */  private $template;   /**  * @ORMColumn(type="string", length=255)  */  private $title;   ....  }   namespace AppEntity;  use AppRepositoryTemplateSectionRepository; use DoctrineCommonCollectionsArrayCollection; use DoctrineCommonCollectionsCollection; use DoctrineORMMapping as ORM;  /**  * @ORMEntity(repositoryClass=TemplateSectionRepository::class)  * @ORMTable(options={"collate"="utf8mb4_general_ci"})  */ class TemplateSection {   /**  * @ORMId  * @ORMGeneratedValue  * @ORMColumn(type="integer")  */  private $id;   /**  * @ORMManyToOne(targetEntity=Template::class, inversedBy="id", cascade={"persist"})  * @ORMJoinColumn(nullable=false)  */  private $template;   /**  * @ORMManyToOne(targetEntity=Section::class, inversedBy="id", cascade={"persist"})  * @ORMJoinColumn(nullable=false)  */  private $section;   /**  * @ORMColumn(type="smallint", options={"default": "0"})  */  private $sortOrder;   ....  }   

У меня есть форма, в которой я могу определить новые записи для шаблона. Есть поле secInput , в котором я могу определить более 1 раздела, который будет использоваться в этом шаблоне. В secInput-это разделенный запятыми список значений(идентификаторов), которые будут использоваться для выбранных разделов.

Когда я пытаюсь сохранить форму, только последняя запись сохраняется в Template.sections

Что мне нужно изменить, чтобы сохранить все данные в базе данных?

Мой код в TemplateController:

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

Ответ №1:

Вы повторяете выбранные разделы и перезаписываете их без сохранения. Когда вы звоните $entityManager-gt;persist($templateSection) , вы указываете EntityManager отслеживать его, но в конце концов, когда вы звоните $entityManager-gt;flush() , сохраняется только один объект. И это происходит с самыми последними данными.

Попробуйте создать новый объект и сохранить его, вот так:

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

Комментарии:

1. Так верно и очевидно, Что я был слеп по своему собственному кодексу. Отлично работает, большое спасибо!