2013-08-31 3 views
0

Чтобы упростить, у меня есть два объекта. Один из них: Продукт, а второй - Атрибут. Продукт имеет отношение OneToMany к атрибуту и ​​атрибуту, получило ManyToOne для продуктов (так что это однонаправленное двунаправленное отношение). Я создал форму с CRUD и добавил коллекцию в ProductType, поэтому на одной странице я могу, например. отредактируйте для него атрибут assign. Проблема в том, что когда я нажимаю «Обновить», он вставляет строку в таблицу атрибутов, а столбец значений - в порядке, но столбцы product_id - null. Может ли кто-нибудь помочь мне в этом?Symfony: коллекция вставляет новую строку без идентификатора

Entity продукта:

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

} 

Атрибут Entity:

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

ProductType:

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__' 
           ))  
     ; 
    } 
      ... 
      ... 
} 

AttributeType:

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



    ... 
    ... 
} 

EDIT (временное решение):

Я обнаружил, что, когда я сохранении продукта с атрибутом, то он не работает функция 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

Привет изменить функцию 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; 
} 
+0

Привет, я уже пробовал это, но это не помогло. Я проверяю, выполняется ли эта функция при сохранении, и я обнаружил, что это не так (я добавил выход при начале этой функции). Я нашел временное решение, которое я добавил к моему вопросу. Поэтому, если бы вы знали лучшее решение, чем мое, то, пожалуйста, дайте мне знать. – Marek

3

Используйте stwe в связке с «by_reference» => ложный вариант формы на поле сбора. Взгляните на «Доктрина: Каскадные отношения» и сохраните раздел «Обратная сторона» по этой ссылке: How to Embed a Collection of Forms

Смежные вопросы