2016-09-14 39 views
0

私はフォームHotelを持っています。これにはCollectionTypeが含まれています。これにはCollectionTypeも含まれています。ネストされたコレクションのタイプ

class Room { 
/** 
* @ORM\ManyToOne(targetEntity = "Hotel", inversedBy = "rooms") 
* @ORM\JoinColumn(name = "id_hotel", referencedColumnName = "id") 
*/ 
private $hotel; 

/** 
* @ORM\OneToMany(targetEntity="PictureRoom", mappedBy="room", cascade={"remove", "persist"}) 
*/ 
private $pictures; 
/** 
* @ORM\OneToMany(targetEntity="PriceRoom", mappedBy="room", cascade={"remove", "persist"}) 
*/ 
private $prices; 

class Hotel { 
/** 
* @ORM\OneToMany(targetEntity="Room", mappedBy="hotel", cascade={"remove", "persist"}) 
*/ 
private $rooms; 

HotelController:

エンティティの関係ここで

class HotelType extends AbstractType{ 
/** 
* @param FormBuilderInterface $builder 
* @param array $options 
*/ 
public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('rooms', CollectionType::class, array(
      'entry_type' => RoomType::class, 
      "label" => "Add rooms", 
      'allow_add' => true, 
      'allow_delete' => true, 
      'prototype' => true, 
     )) 

class RoomType extends AbstractType{ 
/** 
* @param FormBuilderInterface $builder 
* @param array $options 
*/ 
public function buildForm(FormBuilderInterface $builder, array $options){ 
    $builder 

     ->add('pictures', CollectionType::class, array(
      'entry_type' => PictureRoomType::class, 
      "label" => "Add pictures", 
      'allow_add' => true, 
      'allow_delete' => true, 
      'prototype' => true, 
     )) 
     ->add('prices', CollectionType::class, array(
      'entry_type' => PriceRoomType::class, 
      "label" => "Add prices", 
      'allow_add' => true, 
      'allow_delete' => true, 
      'prototype' => true, 
     )) 
    ; 

:この形式では、私は再びいくつかのエンティティを含むことができ、複数の子を含めることができる親エンティティを、追加したいです

class HotelController extends Controller{ 
/** 
* Creates a new Hotel entity. 
* 
* @Route("/new", name="hotel_new") 
* @Method({"GET", "POST"}) 
*/ 
public function newAction(Request $request) 
{ 
    $hotel = new Hotel(); 
    $form = $this->createForm('AppBundle\Form\HotelType', $hotel); 
    $form->handleRequest($request); 

    if ($form->isSubmitted() && $form->isValid()) { 
     if ($hotel->getRooms() != null) { 
      foreach ($hotel->getRooms() as $room) { 
       if (!empty($room)) { 
        $room->setHotel($hotel); 
        if ($room->getPictures() != null) { 
         foreach ($room->getPictures() as $picture) { 
          if (!empty($picture)) { 
           $picture->setRoom($room); 
           $picture->upload(); 
          } 
         } 
        } 
        if ($room->getPrices() != null) { 
         foreach ($room->getPrices() as $price) { 
          if (!empty($price)) { 
           $price->setRoom($room); 
           $price->setIdTva($price->getIdTva()->getId()); 
          } 
         } 
        } 
        $room->setIdTva($room->getIdTva()->getTva()); 
       } 
      } 
     } 

フィールドを処理するJSファイルがあります。追加:

$(document).ready(function() { 

var fields = $('div[data-prototype]'); 
var childElementCount = 1; 

fields.each(function (index) { 
    var field = $(this); 
    var elementCount = 1; 

    field.parent().append('<a href="#" class="btn btn-primary" id="add-another-' + index + '"><i class="glyphicon glyphicon-plus"></i> Add an element</a>'); 

    var trigger = $("#add-another-" + index); 
    var childCollections; 

    trigger.click(function (e) { 
     var newWidget = field.attr('data-prototype'); 
     newWidget = newWidget.replace(/label__/g, ""); 
     newWidget = newWidget.replace(/col-md-6/g, "col-md-12"); 
     newWidget = newWidget.replace(/__name__/g, elementCount); 
     e.preventDefault(); 
     elementCount++; 
     field.parent().append(newWidget); 

     childCollections = field.parent().find('.collection'); 

     if(childCollections.length == 1){ 

      childCollections.parent().append('<a href="#" class="btn btn-primary" id="add-another-' + index + '-'+ elementCount + '"><i class="glyphicon glyphicon-plus"></i> Add an element</a>'); 
      var childTrigger = $('#add-another-' + index + '-' + elementCount); 

      childTrigger.click(function (e) { 
       var newChildWidget = childCollections.find('div[data-prototype]').attr('data-prototype'); 
       //newChildWidget = newChildWidget.replace(/__child__/g, "_" + childElementCount); 
       console.log(newChildWidget); 
       e.preventDefault(); 
       childElementCount += 1; 
       console.log(childElementCount); 
       childCollections.parent().append(newChildWidget); 
      }); 

     } else if (childCollections.length > 1) { 
      childCollections.each(function(childIndex){ 
       var childField = $(this); 
       childField.parent().append('<a href="#" class="btn btn-primary" id="add-another-' + index + '-'+ elementCount + childIndex + '"><i class="glyphicon glyphicon-plus"></i> Add an element</a>'); 
       var childTrigger = $('#add-another-' + index + '-' + elementCount + childIndex); 


       childTrigger.click(function (e) { 
        var newChildWidget = childField.find('div[data-prototype]').attr('data-prototype'); 
        //newChildWidget = newChildWidget.replace(/__child__/g, "_" + childElementCount); 
        console.log(newChildWidget); 

        e.preventDefault(); 
        childElementCount+= 1; 
        console.log(childElementCount); 
        childField.parent().append(newChildWidget); 
       }); 
      }) 
     } 
    }); 
}); 

"Add an element"をクリックすると、正しいFormTypeが正しいdivに追加されます。しかし、私がデータを提出すると、PictureRoomやPricesRoomのような孫のフィールドはデータベースに保存されません。そのようなネストされたCollectionTypeフォームを使用する方法を誰かが知っていますか?

ありがとうございました。

答えて

2

CollectionTypeはSymfony Form Componentの機能であり、実際にはdoctrineをする必要はありません。

CollectionTypeを使用すると、一部のオブジェクトのフォームデータArrayCollectionに含まれますが、それらを処理して永続させる方法はあなたの責任です。

個人的には、プロパティを使用して、CollectionTypeを通じて作成された新しいエンティティを永続化することをお勧めします。

何かがRoomPictureのための同じ

->add('prices', CollectionType::class, array(
     'entry_type' => PriceRoomType::class, 
     "label" => "Add prices", 
     'allow_add' => true, 
     'allow_delete' => true, 
     'prototype' => true, 
     'empty_data' => function (FormInterface $form) { 
      $price = PriceRoom(); 
      $price->setRoom($form->getParent()->getData()); 
      return $price; 
     }, 
    )) 

ようなものです。また、どのレベルにもcascade={"remove", "persist"}を持たなければなりません。この場合

わからない$form->getParent()->getData()Room実体を持つことになりますが、とにかくそれは何とか$formオブジェクトからアクセスすることができ、コードだけでビットを再生する場合。

関連する問題