【问题标题】:Symfony2 ManyToMany embedded forms unexpected resultSymfony2 ManyToMany 嵌入式表单意外结果
【发布时间】:2013-08-21 02:30:52
【问题描述】:

我有以下正在运行的代码,我发现的唯一问题是当我创建/编辑 cliente 并从中追加/删除 servicio,而不是链接我现有 @ 的 id 987654323@它创建另一个,我在这里解释。

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 但 id 2 的服务,而不是使用现有的服务 bar 和 id 1

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

客户表格

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

服务表格

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

客户控制器

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(),
        ));
    }

客户 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: {  }

服务 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: {  }

客户实体

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

服务实体

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

【问题讨论】:

    标签: php mysql symfony collections doctrine-orm


    【解决方案1】:

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

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

    在给定现有客户或新客户的情况下,您将获得多项服务。

    一些提示

    • Symfony2 实体总是单数的(Cliente, Servicio)
    • *ToMany 关系变量应该是复数( $servicios, $clientes )

    【讨论】:

    • 谢谢您,它现在运行良好。关于提示,我已经知道了,但是数据库来自其他旧项目,我只是没有更新名称和资料...但是谢谢! :)
    • 还有一件事(如果你愿意,我可以提出另一个问题,但与这个问题有关)。为了以另一种形式(与客户和服务的 OneToOne 关系的另一个表)显示客户拥有哪些服务,我必须在我的otherTableType.php 中做什么? -&gt;add('servicio'); 显示每个服务,而不是依赖于客户
    • 您必须在 Cliente 上创建新方法为 __toString(),例如 getCompleteClient(),并序列化所有数据(客户端名称和所有服务以逗号分隔),并在定义新的 formType 时,您可以定义要在选择中显示的属性(symfony.com/doc/current/reference/forms/types/…
    • 是的,我绝对不知道如何处理它以将带有方法的 X 客户端服务返回到实体中,我唯一能想到的就是带有一些连接查询的 repo,但仍然不知道如何发送到表单...
    猜你喜欢
    • 1970-01-01
    • 2014-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多