2013-04-14 13 views
5

Tôi đang làm việc với Symfony2 Biểu mẫu và FOSRestBundle.Cách hoạt động chính xác với Biểu mẫu, Gói FOS Rest và nhiều mối quan hệ trong Symfony2

Tôi đang cố lưu vào cơ sở dữ liệu, một thực thể có mối quan hệ nhiều đến nhiều.

tôi tạo một Form với một lĩnh vực thu gom (http://symfony.com/doc/master/cookbook/form/form_collections.html) như thế này:

class MainType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('name'); 
     $builder->add('description'); 

     $builder->add('others', 'collection', array(
      'type' => new OtherType() 
     )); 
    } 

    public function getName() 
    { 
     return ''; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Acme\SearchBundle\Entity\Main', 
      'csrf_protection' => false 
     )); 
    } 
} 

class OtherType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('id'); 
    } 

    public function getName() 
    { 
     return ''; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Acme\SearchBundle\Entity\Other', 
      'csrf_protection' => false 
     )); 
    } 
} 

Bộ sưu tập của các đối tượng của loại "Khác" được lưu trữ trong cơ sở dữ liệu. Và tôi không muốn lưu trữ nhiều đối tượng thuộc loại đó, chỉ đọc và liên kết chúng với đối tượng chính.

Khi tôi xử lý các hình thức tôi sử dụng chức năng này:

private function processForm(Main $main, $new = false) 
{ 

    $new = true; 

    $statusCode = $new ? 201 : 204; 

    $form = $this->createForm(new MainType(), $main); 
    $form->bind($this->getRequest()); 


    if ($form->isValid()) { 

     $mainValidated = $form->getData(); 

     // I should store the collection of objects of type other 
     // in the database 

     $em = $this->getDoctrine()->getEntityManager(); 
     $em->persist($mainValidated); 
     $em->flush(); 

     return $this->view($new ? $mainValidated : null, $statusCode); 
    } 

    return $this->view($form, 400); 
} 

Mã json tôi gửi từ một khách hàng Backbone.js là:

{"others":[{"id":1}, {"id":2}]} 

Đối tượng:

  • chính

Xml:

<entity name="Acme\SearchBundle\Entity\Main" table="main"> 
    <id name="id type="integer" column="id"> 
     <generator strategy="IDENTITY"/> 
    </id> 
    <field name="name" type="integer" column="name" nullable="true"/> 
    <field name="description" type="integer" column="description" nullable="true"/> 

    <many-to-many field="others" target-entity="Other" inversed-by="mains"> 
     <cascade> 
     <cascade-persist/> 
     </cascade> 
     <join-table name="main_has_other"> 
     <join-columns> 
      <join-column name="main" referenced-column-name="id"/> 
     </join-columns> 
     <inverse-join-columns> 
      <join-column name="other" referenced-column-name="id"/> 
     </inverse-join-columns> 
     </join-table> 
    </many-to-many> 

    </entity> 

Entity:

<?php 

namespace Acme\SearchBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

use JMS\Serializer\Annotation\Type; 

use JMS\Serializer\Annotation\Groups; 
use JMS\Serializer\Annotation\Expose; 

class Main 
{ 
    /** 
    * @Type("integer") 
    * @Groups({"admin"}) 
    * 
    * @var integer 
    * 
    */ 
    private $id; 

    /** 
    * 
    * @Type("string") 
    * @Groups({"manage"}) 
    * 
    * @var string 
    */ 
    private $name; 


    /** 
    * @Type("string") 
    * @Groups({"manage"}) 
    * 
    * @var string 
    */ 
    private $description; 


    /** 
    * @Type("ArrayCollection<Acme\SearchBundle\Entity\Other>") 
    * @Groups({"manage"}) 
    * 
    * @var \Doctrine\Common\Collections\Collection 
    */ 
    private $others; 


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



    /** 
    * Set name 
    * 
    * @param string $name 
    * @return Main 
    */ 
    public function setName($name) 
    { 
     $this->name = $name; 

     return $this; 
    } 

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

    /** 
    * Set description 
    * 
    * @param string $description 
    * @return Main 
    */ 
    public function setDescription($description) 
    { 
     $this->description = $description; 

     return $this; 
    } 

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

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

    /** 
    * Add others 
    * 
    * @param \Acme\SearchBundle\Entity\Other $other 
    * @return Main 
    */ 
    public function addOthers(\Acme\SearchBundle\Entity\Other $other) 
    { 
     $this->others[] = $other; 

     return $this; 
    } 

    /** 
    * Remove others 
    * 
    * @param \Acme\SearchBundle\Entity\Other $other 
    */ 
    public function removeOthers(\Acme\SearchBundle\Entity\Other $other) 
    { 
     $this->others->removeElement($other); 
    } 

    /** 
    * Get others 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getOthers() 
    { 
     return $this->others; 
    } 
} 
  • khác

Xml:

<entity name="Acme\SearchBundle\Entity\Other" table="other"> 
    <id name="id" type="integer" column="id"> 
    <generator strategy="IDENTITY"/> 
    </id> 
    <field name="name" type="string" column="name" length="255" nullable="true"/> 
    <field name="description" type="string" column="name" length="255" nullable="true"/> 
    <many-to-many field="mains" target-entity="Main" mapped-by="others"> 
    <cascade> 
     <cascade-persist/> 
    </cascade> 
    </many-to-many> 
</entity> 

Entity:

<?php 

namespace Acme\SearchBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

use JMS\Serializer\Annotation\Type; 
use JMS\Serializer\Annotation\Groups; 

class Other 
{ 

    /** 
    * @Type("integer") 
    * @Groups({"manage"}) 
    * 
    * @var integer 
    */ 
    private $id; 

    /** 
    * @Type("string") 
    * @Groups({"manage"}) 
    * 
    * @var string 
    */ 
    private $name; 

    /** 
    * @Type("string") 
    * @Groups({"manage"}) 
    * 
    * @var string 
    */ 
    private $description; 

    /** 
    * @Type("Acme\SearchBundle\Entity\Main") 
    * @Groups({"admin"}) 
    * 
    * @var \Doctrine\Common\Collections\Collection 
    */ 
    private $mains; 

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

    /** 
    * Set name 
    * 
    * @param string $name 
    * @return Other 
    */ 
    public function setName($name) 
    { 
     $this->name = $name 
    } 

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

    /** 
    * Set description 
    * 
    * @param string $description 
    * @return Other 
    */ 
    public function setDescription($description) 
    { 
     $this->description = $description; 

     return $this; 
    } 

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

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

    /** 
    * Set id 
    * 
    * @param integer $id 
    * @return Other 
    */ 
    public function setId($id) 
    { 
     $this->id = $id; 

     return $this; 
    } 

    /** 
    * Add main 
    * 
    * @param \Acme\SearchBundle\Entity\Main $main 
    * @return Other 
    */ 
    public function addMains(\Acme\SearchBundle\Entity\Main $main) 
    { 
     $this->mains[] = $main; 

     return $this; 
    } 

    /** 
    * Remove main 
    * 
    * @param \Acme\SearchBundle\Entity\Main $main 
    */ 
    public function removeMains(\AcmeSearchBundle\Entity\Main $main) 
    { 
     $this->mains->removeElement($main); 
    } 

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

Khi tôi duy trì đối tượng thuộc loại "chính" trong cơ sở dữ liệu, bộ sưu tập không được đặt trong bảng có nhiều mối quan hệ. Tôi phải lưu bộ sưu tập thủ công khi vẫn tồn tại đối tượng "chính".

Tôi đang tìm cách lưu bộ sưu tập đối tượng tự động dễ dàng nhất có thể.

+0

Bạn cần sử dụng 'cascade = {" persist "}'. – cheesemacfly

+1

Tôi gặp phải lỗi này: "biểu mẫu này không được chứa các trường thừa" – escrichov

+0

Bạn có thể đăng mã twig của mình cho biểu mẫu không? – cheesemacfly

Trả lời

4

Tôi gặp sự cố tương tự, tôi nghĩ bạn chỉ cần định cấu hình biểu mẫu để mong đợi các mục bổ sung trong bộ sưu tập của mình.

'allow_add' => true 

Lỗi "biểu mẫu này không chứa trường bổ sung" sẽ không tăng, vì biểu mẫu sẽ mong đợi các trường bổ sung này. Vì vậy, mã phải là

$builder->add('others', 'collection', array(
     'type' => new OtherType(), 
     'allow_add' => true 
    )); 
Các vấn đề liên quan