0

为了简化,我有两个实体。一是产品,二是属性。Product 实体与 Attribute 具有 OneToMany 关系,而 Attribute 与 Products 具有 ManyToOne 关系(所以这是 OneToMany 双向关系)。我已经使用 CRUD 创建了表单并在 ProductType 中添加了集合,因此在一个页面上我可以例如为它编辑产品的分配属性。问题是,当我单击“更新”时,它正在向属性表插入行,值列没问题,但 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')
        ;
    }
    ...
    ...
}

产品控制器:

/**
 * 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做一些改变:

产品控制器:

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

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

4

2 回答 2

3

将 stwe 的解决方案与集合字段上的 'by_reference' => false 表单选项结合使用。看看这个链接中的“学说:级联关系和保存“反向”端”部分:如何嵌入表单集合

于 2014-01-08T08:45:18.623 回答
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;
}
于 2013-08-31T17:48:57.390 回答