¿Cómo persistir los datos de OneToMany Relationship en Symfony? [privada]

Estoy enfrentando un problema con la persistencia de datos de relación OneToMany en la base de datos. A continuación figura el Código:

Tipo de artículo

->add('title')
->add('image',FileType::class)
->add('size', CollectionType::class,[
    'entry_type'=> SizeType::class,
    'entry_options' => ['label' => false],
    'by_reference' => false,
    'allow_add' =>true,
    'allow_delete' => true
])
->add('content',CKEditorType::class)
->add('save', SubmitType::class);

Tema Entidad

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

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

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

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

    public function getId(): ?int
    {
        return $this->id;
    }

    /**
     * @return Collection|Size[]
     */
    public function getSize(): Collection
    {
        return $this->size;
    }

    public function addSize(Size $size): self
    {
        if (!$this->size->contains($size)) {
            $this->size[] = $size;
            $size->setSize($this);
        }

        return $this;
    }

    public function removeSize(Size $size): self
    {
        if ($this->size->removeElement($size)) {
            // set the owning side to null (unless already changed)
            if ($size->getSize() === $this) {
                $size->setSize(null);
            }
        }

        return $this;
    }
}

Entidad de tamaño

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

    /**
     * @ORM\ManyToOne(targetEntity=Item::class, inversedBy="size", fetch="EAGER")
     */
    private $size;

    public function getSize(): ?Item
    {
        return $this->size;
    }

    public function setSize(?Item $size): self
    {
        $this->size = $size;

        return $this;
    }
}

Controlador

/**
 * @Route("/admin/post-product", name="post_product")
 */
public function postProduct(Request $request, SluggerInterface $slugger): Response
{
    $item = new Item();   
    $size = new Size();
    $form = $this->createForm(ItemType::class, $item);
    $form->handleRequest($request);
    if($form->isSubmitted()){
        $file_image = $form->get('image')->getData();

        dump($item->getSize());
        //die;
        if($file_image){
           //image
        }

        $sizes = $item->getSize();
        $item->addSize($sizes);

        $em = $this->getDoctrine()->getManager();
        $em->persist($item);
        $em->flush();

        return $this->redirectToRoute('post_product');
    }
    return $this->render('admin/post-product.html.twig',[

        'form' => $form->createView(),
    ]);
} 

Mi problema aquí es que no puedo guardar los datos en la base de datos que he intentado con bucles, pero no pude. La clase El artículo es unatomany con el tamaño. Que es Artículo tiene tamaños relacionados(s,m,l,xl,xxl). Lo que quiero o lograr aquí es que cuando haga clic en el botón guardar el elemento y la tabla de tamaño debe ser poblada. Por favor, ayúdame ..

Pregunta hecha hace 3 años, 5 meses, 0 días - Por bytebard


3 Respuestas:

  • Usted está tratando de persistir la relación del lado inverso (el que tiene un mappedBy). La doctrina no revisará la relación cuando persista el lado inverso. En este caso en particular, creo que mezclaste los lados propios/inversos. Trataría de poner el inversedBy en tu Item clase y la mappedBy en el Size clase.

    Si quieres mantener la relación como es. Usted tendría que establecer la propiedad en el lado propio al establecer la propiedad en el lado inverso.

    Respondida el Dec 17, 2020 a las 19:25 - por compilerhero

    Votos positivos: 0 | Votos negativos: 0

  • El problema en tu código radica en la forma en que estás intentando persistir los datos de la relación OneToMany entre la entidad Item y Size. Aquí te dejo algunas correcciones que puedes realizar en tu controlador para solucionar el problema:

    • Elimina la creación de un nuevo objeto `Size` en tu controlador, ya que las instancias de `Size` se añadirán dinámicamente a través del formulario.
    • Elimina la línea donde intentas agregar los tamaños a `$item`. Esto no es necesario ya que estos datos serán manejados automáticamente por el formulario.
    • Dentro del condicional donde verificas si el formulario ha sido enviado y válido, realiza la persistencia de `$item` de la siguiente manera:
    php
    $item = new Item();
    $form = $this->createForm(ItemType::class, $item);
    $form->handleRequest($request);
    
    if ($form->isSubmitted() && $form->isValid()) {
        // Procesar la subida de la imagen si es necesario
        if ($file_image) {
            // Tratar la imagen
        }
    
        $em = $this->getDoctrine()->getManager();
        $em->persist($item);
    
        // No es necesario llamar a persist para los tamaños ya que serán manejados automáticamente
        // Persistir los datos
        $em->flush();
    
        return $this->redirectToRoute('post_product');
    }
    

    Con estas correcciones, Symfony se encargará de manejar la persistencia de los tamaños que se agregaron dinámicamente a través del formulario. Asegúrate de que los datos se envíen correctamente desde el formulario y las entidades se configuren de forma adecuada para la relación OneToMany. Si sigues teniendo problemas, te recomendaría revisar la configuración de tu formulario ItemType para asegurarte de que estás correctamente manejando la relación OneToMany con los tamaños.

    Respondida el Dec 18, 2020 a las 19:22 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Problema:

    Estás intentando persistir datos de una relación OneToMany dentro de la base de datos, pero la persistencia falla.

    Solución:

    Para persistir correctamente los datos de la relación OneToMany, debes seguir estos pasos:

    • Añade la anotación `cascade`: En la entidad principal (en este caso, `Item`), añade la anotación `cascade` a la relación `OneToMany` para especificar que las entidades relacionadas deben persistir en cascada.
    • Inicializa la colección: Antes de persistir la entidad principal, asegurate de inicializar la colección de entidades relacionadas (en este caso, `$item->size`) para que Doctrine sepa que se están creando nuevas entidades.

    Código actualizado:

    php
    // Entidad del artículo (Item)
    /*
      @ORM\OneToMany(targetEntity=Size::class, mappedBy="size", cascade={"persist"})
     /
    private $size;
    
    // Controlador (postProductAction)
    $item = new Item();
    $item->getSize()->add($sizes); // inicializa y añade entidades relacionadas a la colección
    $em->persist($item);
    $em->flush();
    

    Explicación:

    • La anotación `@ORM\OneToMany(cascade={"persist"})` especifica que cuando se persiste la entidad `Item`, también deben persistir las entidades `Size` relacionadas.
    • La inicialización de `$item->getSize()` antes de persistir el `Item` garantiza que Doctrine sepa que los objetos `Size` se están creando y que deben persistir en cascada.

    Nota:*

    Asegurate de que tus entidades estén correctamente mapadas y que el ORM (por ejemplo, Doctrine) esté configurado correctamente para admitir relaciones OneToMany.

    Respondida el Dec 18, 2020 a las 19:26 - por Gemini

    Votos positivos: 0 | Votos negativos: 0