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

时间:2013-08-19 10:16:48

标签: php mysql symfony collections doctrine-orm

我有以下代码正常工作,我发现的唯一问题是当我创建/编辑cliente并从中追加/删除servicio时,而不是将我的ID链接起来现有的servicio它创建了另一个,我在这里解释。

cliente: foo. id: 1

service: bar. id: 1

我转到表单,选择foobar,当我提交时,我想要在表clientes_servicios上处理此数据的关系:

cliente_id      servicio_id
    1               1

相反,我得到的是:

cliente_id      servicio_id
    1               2

如果我去表servicios,我发现Symfony2创建了另一个名为bar但标识为2的服务,而不是使用标识为{{bar的现有服务1 1}}

所以我想要的是使用现有的servicio从不servicio表单创建一个新的cliente(因为我有另一个表单JUST for Servicio )

Cliente表格

<?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表格

<?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

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

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

<?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实体

<?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;
    }
}

1 个答案:

答案 0 :(得分:2)

关键是你正在以糟糕的方式构建表单。 您的客户类型应为:

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

如果有现有的Cliente或新的客户,您将获得多选服务。

一些提示

  • Symfony2实体始终是Singular(Cliente,Servicio)
  • * ToMany关系变量应为复数($ servicios,$ clientes)