Symfony:集合插入没有id的新行

时间:2013-08-31 14:21:59

标签: symfony collections doctrine-orm one-to-many crud

为了简化,我有两个实体。一个是产品,第二个是属性。产品实体与属性有一个OneToMany关系,而属性已经有了ManyToOne到产品(所以这是OneToMany双向关系)。我已经使用CRUD创建了表单并在ProductType中添加了集合,因此在一个页面上我可以例如为产品编辑一个assign属性。问题是,当我单击“更新”时,它会将行插入属性表,值列正常,但product_id列为空。有人可以帮帮我吗?

产品实体:

/**
 * Product
 *
 * @ORM\Table(name="product")
 * @ORM\Entity
 */
class Product
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    ...
    ...
    ...

    /**
     * @ORM\OneToMany(targetEntity="Attribute", mappedBy="product", cascade={"persist", "remove"})
     */
    private $attribute;

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

    /**
     * Add attribute
     *
     * @param \ePOS\ProductsBundle\Entity\Attribute $attribute
     * @return Product
     */
    public function addAttribute(\ePOS\ProductsBundle\Entity\Attribute $attribute)
    {
        $this->attribute[] = $attribute;

        return $this;
    }

    /**
     * Remove attribute
     *
     * @param \ePOS\ProductsBundle\Entity\Attribute $attribute
     */
    public function removeAttribute(\ePOS\ProductsBundle\Entity\Attribute $attribute)
    {
        $this->attribute->removeElement($attribute);
    }

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

}

属性实体:

/**
 * Attribute
 *
 * @ORM\Table(name="product_attribute")
 * @ORM\Entity
 */
class Attribute
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="attribute")
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id")
     **/
    private $product;

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

    /**
     * Set value
     *
     * @param string $value
     * @return Attribute
     */
    public function setValue($value)
    {
        $this->value = $value;

        return $this;
    }

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

    /**
     * Set product
     *
     * @param \ePOS\ProductsBundle\Entity\Product $product
     * @return Attribute
     */
    public function setProduct(\ePOS\ProductsBundle\Entity\Product $product = null)
    {
        $this->product = $product;

        return $this;
    }

    /**
     * Get product
     *
     * @return \ePOS\ProductsBundle\Entity\Product 
     */
    public function getProduct()
    {
        return $this->product;
    }
}

产品型号:

class ProductType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {        
        $builder
            ->add('name')
            ->add('attribute', 'collection', array(
                                'type' => new AttributeType(),
                                'allow_add' => true,
                                'prototype' => true,
                                'prototype_name' => 'attribute__name__'
                                ))    
        ;
    }
            ...
            ...
}

属性类型:

class AttributeType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('value')
        ;
    }
    ...
    ...
}

ProductController的:

/**
 * Product controller.
 *
 * @Route("/product")
 */
class ProductController extends Controller
{
    ...
    ...

    /**
     * Displays a form to edit an existing Product entity.
     *
     * @Route("/{id}/edit", name="products_product_edit")
     * @Method("GET")
     * @Template()
     */
    public function editAction($id)
    {
        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('ePOSProductsBundle:Product')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find Product entity.');
        }

        $editForm = $this->createEditForm($entity);
        $deleteForm = $this->createDeleteForm($id);

        return array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        );
    }

    /**
    * Creates a form to edit a Product entity.
    *
    * @param Product $entity The entity
    *
    * @return \Symfony\Component\Form\Form The form
    */
    private function createEditForm(Product $entity)
    {
        $form = $this->createForm(new ProductType(), $entity, array(
            'action' => $this->generateUrl('products_product_update', array('id' => $entity->getId())),
            'method' => 'PUT',
        ));

        $form->add('submit', 'submit', array('label' => 'Update'));

        return $form;
    }

    /**
     * Edits an existing Product entity.
     *
     * @Route("/{id}", name="products_product_update")
     * @Method("PUT")
     * @Template("ePOSProductsBundle:Product:edit.html.twig")
     */
    public function updateAction(Request $request, $id)
    {
        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('ePOSProductsBundle:Product')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find Product entity.');
        }

        $deleteForm = $this->createDeleteForm($id);
        $editForm = $this->createEditForm($entity);
        $editForm->handleRequest($request);

        if ($editForm->isValid()) {
            $em->flush();

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

        return array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        );
    }



    ...
    ...
}

编辑(临时解决方案):

我发现当我使用属性保存产品时,它没有运行setAttribute函数。所以我所做的是在函数createEditForm中进行一些更改:

ProductController的:

private function createEditForm(Product $entity)
{

    $data = $this->get('request')->request->get('epos_productsbundle_product');
    $count = count($data['attribute']);

    for($i=1; $i<=$count; $i++){
        $attribute = new \ePOS\ProductsBundle\Entity\Attribute();
        $attribute->setProduct($entity);
        $entity->addAttribute($attribute);
    }

    $form = $this->createForm(new ProductType($this->get('security.context')->getToken()->getUser()->getId()), $entity, array(
        'action' => $this->generateUrl('products_product_update', array('id' => $entity->getId())),
        'method' => 'PUT',
    ));

    $form->add('submit', 'submit', array('label' => 'Update'));

    return $form;
}

但如果有人能够知道更好的解决方案,请告诉我。

2 个答案:

答案 0 :(得分:3)

使用stwe的溶液与'by_reference'=&gt;结合使用集合字段上的false表单选项。 看一下'Doctrine:Cascading Relations并保存此链接中的“Inverse”side'部分:How to Embed a Collection of Forms

答案 1 :(得分:2)

您可以更改addAttribute函数,

/**
 * Add attribute
 *
 * @param \ePOS\ProductsBundle\Entity\Attribute $attribute
 * @return Product
 */
public function addAttribute(\ePOS\ProductsBundle\Entity\Attribute $attribute)
{
    $attribute->setProduct($this);
    $this->attribute[] = $attribute;

    return $this;
}