简体   繁体   English

Symfony2 ManyToMany嵌入形成了意想不到的结果

[英]Symfony2 ManyToMany embedded forms unexpected result

I have the following code which is working, the only problem I've found is when I create/edit a cliente and append/remove a servicio from it, instead of linking me the id of the existing servicio it creates another one, I explain here. 我有以下的代码这是工作,我已经找到了唯一的问题是,当我创建/编辑cliente并追加/删除servicio从它,而不是链接我现有的ID servicio它创造一个又一个,我解释这里。

cliente: foo. id: 1

service: bar. id: 1

I go to the form, select foo and bar , when I submit, I want to have on the table clientes_servicios which handles the relationships this data: 我转到表单,选择foobar ,当我提交时,我想在表clientes_servicios上处理这些数据的关系:

cliente_id      servicio_id
    1               1

Instead, what I'm getting is this: 相反,我得到的是这样的:

cliente_id      servicio_id
    1               2

If I go to table servicios i see that Symfony2 has created another servicio with name bar but id 2 instead of using the existing servicio bar with id 1 如果我去表servicios我发现Symfony2创建了另一个名称bar但是id为2的servicio而不是使用id为1的现有servicio bar

So what I want is to use the existing servicio and never create a new servicio from cliente form (because I have another form JUST for Servicio) 所以我想要的是使用现有的servicio并且永远不会cliente形式创建一个新的servicio (因为我有另一个形式JUST for Servicio)

Cliente form 客户形式

<?php
namespace Pge\IncidenciasBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ClientesType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('nombre')
            ->add('servicio', 'collection', array(
                    'type' => new ServiciosType(),
                    'allow_add' => true,
                    'allow_delete' => true,
                    'prototype' => true,
                    // Post Update
                    'by_reference' => false
        ))
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Pge\IncidenciasBundle\Entity\Clientes',
            'csrf_protection' => false,
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'pge_incidenciasbundle_clientestype';
    }
}

Servicio form Servicio表格

<?php

namespace Pge\IncidenciasBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

use Doctrine\ORM\EntityRepository;
class ServiciosType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('nombre', 'entity', array(
                    'class' => 'PgeIncidenciasBundle:Servicios'
        ));
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Pge\IncidenciasBundle\Entity\Servicios'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'pge_incidenciasbundle_serviciostype';
    }
}

Cliente Controller 客户控制器

public function createAction(Request $request)
    {
        $entity  = new Clientes();
        $form = $this->createForm(new ClientesType(), $entity);
        $form->submit($request);

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

            return $this->redirect($this->generateUrl('clientes_show', array('id' => $entity->getId())));
        }

        return $this->render('PgeIncidenciasBundle:Clientes:new.html.twig', array(
            'entity' => $entity,
            'form'   => $form->createView(),
        ));
    }

    /**
     * Displays a form to create a new Clientes entity.
     *
     */
    public function newAction()
    {
        $entity = new Clientes();

        $form   = $this->createForm(new ClientesType(), $entity);

        return $this->render('PgeIncidenciasBundle:Clientes:new.html.twig', array(
            'entity' => $entity,
            'form'   => $form->createView(),
        ));
    }

Cliente yml Cliente yml

Pge\IncidenciasBundle\Entity\Clientes:
    type: entity
    table: clientes
    id:
      id:
        type: integer
        generator:
          strategy: IDENTITY
    fields:
        nombre:
            type: string
            length: 250
            fixed: false
            nullable: true   
    manyToMany:
        servicio:
            targetEntity: Servicios
            cascade: [persist]
    lifecycleCallbacks: {  }

Servicio YML Servicio YML

Pge\IncidenciasBundle\Entity\Servicios:
    type: entity
    table: servicios
    id:
      id:
        type: integer
        generator:
          strategy: IDENTITY
    fields:
        nombre:
            type: string
            length: 250
            fixed: false
            nullable: true
    lifecycleCallbacks: {  }

Cliente Entity Cliente实体

<?php

namespace Pge\IncidenciasBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Clientes
 */
class Clientes
{
    /**
     * @var integer
     */
    private $id;

    /**
     * @var string
     */
    private $nombre;

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    private $servicio;

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

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

    /**
     * Set nombre
     *
     * @param string $nombre
     * @return Clientes
     */
    public function setNombre($nombre)
    {
        $this->nombre = $nombre;

        return $this;
    }

    /**
     * Get nombre
     *
     * @return string 
     */
    public function getNombre()
    {
        return $this->nombre;
    }

    /**
     * Add servicio
     *
     * @param \Pge\IncidenciasBundle\Entity\Servicios $servicio
     * @return Clientes
     */
    public function addServicio(\Pge\IncidenciasBundle\Entity\Servicios $servicio)
    {
        $this->servicio[] = $servicio;

        return $this;
    }

    /**
     * Remove servicio
     *
     * @param \Pge\IncidenciasBundle\Entity\Servicios $servicio
     */
    public function removeServicio(\Pge\IncidenciasBundle\Entity\Servicios $servicio)
    {
        $this->servicio->removeElement($servicio);
    }

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

    public function __toString()
    {
        return $this->nombre;
    }
}

Servicio entity Servicio实体

<?php

namespace Pge\IncidenciasBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Servicios
 */
class Servicios
{
    /**
     * @var integer
     */
    private $id;

    /**
     * @var string
     */
    private $nombre;


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

    /**
     * Set nombre
     *
     * @param string $nombre
     * @return Servicios
     */
    public function setNombre($nombre)
    {
        $this->nombre = $nombre;

        return $this;
    }

    /**
     * Get nombre
     *
     * @return string 
     */
    public function getNombre()
    {
        return $this->nombre;
    }

    public function __toString()
    {
        return (string) $this->nombre;
    }
}

The point is that you are building the form in a bad way. 关键是你正在以糟糕的方式构建表单。 Your clientes type should be: 您的客户类型应为:

$builder
    ->add('nombre')
    ->add('servicio', 'entity', array(
        'class' => '/service/entity/namespace',
        'multiple' => true,
    ));

You will get a multiselect of servicios given an existent Cliente or a new one. 给定现有的Cliente或新的客户,您将获得多选服务。

Some tips 一些技巧

  • Symfony2 entity is always Singular ( Cliente, Servicio ) Symfony2实体总是奇异的(Cliente,Servicio)
  • *ToMany relation variable should be plural ( $servicios, $clientes ) * ToMany关系变量应该是复数($ servicios,$ clientes)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM