2017-01-19 14 views
0

プロジェクトに多対多リレーションがありますが、リレーションテーブルを変更したいので、別のエンティティのジョインテーブルと多対1リレーションシップに変換しました。Symfony2チェックボックスリスト

問題は、2つの初期エンティティのチェックボックスグループをレンダリングしようとすると、私はそれを使用できないということです。ここで

は私のコードです:

class Professional extends User 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

... 

/** 
    * @ORM\OneToMany(targetEntity="TurnsProfessional", mappedBy="professional") 
    */ 
    private $turns; 

... 

私の第二のエンティティ

class Turn 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 
... 

    /** 
    * @ORM\OneToMany(targetEntity="TurnsProfessional", mappedBy="turn") 
    */ 
    private $professionals; 

... 

とエンティティに参加

class TurnsProfessional 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    public function __construct() 
    { 
    } 

    /** 
    * @ORM\ManyToOne(targetEntity="Turn", inversedBy="professionals") 
    * @ORM\JoinColumn(name="turn_id", referencedColumnName="id") 
    */ 
    private $turn; 

    /** 
    * @ORM\ManyToOne(targetEntity="Professional", inversedBy="turns") 
    * @ORM\JoinColumn(name="professional_id", referencedColumnName="id") 
    */ 
    private $professional; 

    /** 
    * @ORM\Column(type="boolean") 
    */ 
    private $status = 0; 
... 

私の目標はとプロフェッショナルフォームのチェックボックスリストを作成することですターン。ここ

... 
->add('turns', 'entity', 
      array('class' => 'AppBundle:TurnsProfessional', 
       'property' => 'label', 
       'multiple' => true, 
       'expanded' => true, 
       )); 
... 

問題は、フォームがチェックボックスをレンダリングしていないということです。

まず、私は電源を入れてProfessionalTypeに::クラスをフィールドを追加しようとしました:私は二つのことを試してみました。

... 
->add('turns', 'entity', 
      array('class' => 'AppBundle:Turn', 
       'property' => 'label', 
       'multiple' => true, 
       'expanded' => true, 
       )); 
... 

フォームは、すべてのチェックボックスをレンダリングしないが、私はそれを送信する上でエラーを取得する:私は、クラスを変更それ以外の場合

関連 AppBundle \上のタイプAppBundle \エンティティ\ターンの

見つかり実体エンティティ\プロフェッショナル#はなりますが、(コメントに)オリバーが言ったように

I'veがフォームを編集し AppBundle \エンティティ\ TurnsProfessionalを期待:

TurnsProfessionalType

class TurnsProfessionalType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
     ->add('status') 
     ->add('turn', EntityType::class, 
      array('class' => 'AppBundle:Turn', 
       'property' => 'label', 
       'multiple' => true, 
       'expanded' => true, 
      )); 

    } 

    public function getBlockPrefix() 
    { 
     return 'turns_professional_registration_form'; 
    } 

    public function getName() 
    { 
     return $this->getBlockPrefix(); 
    } 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => TurnsProfessional::class, 
     )); 
    } 
} 

->add($builder->create('turns', CollectionType::class, array(
      'entry_type' => TurnsProfessionalType::class, 
      'by_reference' => false, 
     ))); 

は今、私はとしてそれをレンダリングしました:

{% for turn in form.turns %} 
     <td><div class="checkbox">{{ form_widget(turn.status)}}<label></label></div></td> 
    {% endfor %} 

しかし、私はラベルとして、それぞれのデータベースのラベルを配置する必要があり

を回す誰もい助けられる? ありがとうございました!

+0

あなたは代わりに[CollectionTypeは](http://symfony.com/doc/2.7/reference/forms/types/collection.html)を使用する必要があります(フォームのコレクションを埋め込む方法)に関するsymfonyのドキュメントをご覧ください(https://symfony.com/doc/2.7/form/form_collections.html) – OlivierC

+0

@OlivierC Turn of Collectionを使用する必要がありますか?またはTurnsProfessional? –

+0

ターンエンティティを持つEntityTypeフィールドを持つTurnsProfessionalTypeのCollectionType – OlivierC

答えて

0

プロフェッショナルエンティティ

/** 
* @var ArrayCollection 
* 
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TurnsProfessional", mappedBy="professional", cascade={"persist"}) 
*/ 
private $turns; 

public function __construct() 
{ 
    $this->turns = new ArrayCollection(); 
} 

/** 
* Add turn 
* 
* @param TurnsProfessional $turns 
* @return Professional 
*/ 
public function addTurn(TurnsProfessional $turn) 
{ 
    /* 
     Doctrine only checks the owning side(ManyToOne). So you 
     need to manually call the join entity setter to keep 
     your data in sync. 
    */ 
    $turn->setProfessional($this); 
    $this->turns->add($turn); 

    return $this; 
} 

/** 
* Remove turn 
* 
* @param TurnsProfessional $turn 
* @return Professional 
*/ 
public function removeTurn(TurnsProfessional $turn) 
{ 
    /* 
     Doctrine only checks the owning side(ManyToOne). So you 
     need to manually call the join entity setter to keep 
     your data in sync. 
    */ 
    $turn->setProfessional(); 
    $this->turns->removeElement($turn); 

    return $this; 
} 

/** 
* Get turns 
* 
* @return ArrayCollection 
*/ 
public function getTurns() 
{ 
    return $this->turns; 
} 

ターンエンティティ

/** 
* @var ArrayCollection 
* 
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TurnsProfessional", mappedBy="turn", cascade={"persist"}) 
*/ 
private $professionals; 

public function __construct() 
{ 
    $this->professionals = new ArrayCollection(); 
} 

/** 
* Add professional 
* 
* @param TurnsProfessional $professional 
* @return Turn 
*/ 
public function addProfessional(TurnsProfessional $professional) 
{ 
    /* 
     Doctrine only checks the owning side(ManyToOne). So you 
     need to manually call the join entity setter to keep 
     your data in sync. 
    */ 
    $professional->setTurn($this); 
    $this->professionals->add($professional); 

    return $this; 
} 

/** 
* Remove professional 
* 
* @param TurnsProfessional $professional 
* @return Turn 
*/ 
public function removeProfessional(TurnsProfessional $professional) 
{ 
    /* 
     Doctrine only checks the owning side(ManyToOne). So you 
     need to manually call the join entity setter to keep 
     your data in sync. 
    */ 
    $professional->setTurn(); 
    $this->professional->removeElement($professional); 

    return $this; 
} 

/** 
* Get professionals 
* 
* @return ArrayCollection 
*/ 
public function getProfessionals() 
{ 
    return $this->professionals; 
} 

TurnsProfessionalエンティティ

/** 
* @var Professional 
* 
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Professional", inversedBy="turns", cascade={"persist"}) 
*/ 
private $professional; 

/** 
* @var Turn 
* 
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Turn", inversedBy="professionals", cascade={"persist"}) 
*/ 
private $turn; 

/** 
* @var bool 
* 
* @ORM\Column(name="status", type="boolean") 
*/ 
private $status = true; //You should set a default value to true, since it is non sense to create some value if it not active 

/** 
* Set professional 
* 
* @param Professional $professional 
* @return TurnsProfessional 
*/ 
public function setProfessional(Professional $professional = null) 
{ 
    /* 
     Using a default null value allows you to unset of the value of 
     the joined entity when removing in inverse side 
     (see removeTurn in Professional entity) 
    */ 
    $this->professional = $professional; 

    return $this; 
} 

/** 
* Set turn 
* 
* @param Turn $turn 
* @return TurnsProfessional 
*/ 
public function setTurn(Turn $turn = null) 
{ 
    /* 
     Using a default null value allows you to unset of the value of 
     the joined entity when removing in inverse side 
     (see removeProfessional in Turn entity) 
    */ 
    $this->turn = $turn; 

    return $this; 
} 

ProfessionalType

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolver; 
use Symfony\Component\Form\Extension\Core\Type\CollectionType; 
use AppBundle\Form\TurnsProfessionalType; 

class ProfessionalType extends AbstractType 
{ 
    /** 
    * {@inheritdoc} 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('turns', CollectionType::class, array(
      'entry_type' => TurnsProfessionalType::class, 
      'allow_add' => true, 
      'by_reference' => false, //with by_reference at false you force the call of the setter 
     )) 
      //other fields 
     ; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\Professional', 
      'cascade_validation => true //will also validate joined entities 
     )); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getBlockPrefix() 
    { 
     return 'turns_professional_registration_form'; 
    } 
} 

TurnsProfessionalType

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolver; 
use Symfony\Bridge\Doctrine\Form\Type\EntityType; 
use AppBundle\Entity\Turn; 

class TurnsProfessionalType extends AbstractType 
{ 
    /** 
    * {@inheritdoc} 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('turn', EntityType::class, array(
      'class' => Turn::class, 
      'choice_label' => 'label' 
     )); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\TypesProfessional' 
     )); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getBlockPrefix() 
    { 
     return 'turns_professional_registration_form'; 
    } 
} 

小枝テンプレート

/* 
    By default you will have an empty turns collection which 
    which means you will get no field displayed 
    that's why you need a addTurn button to fill your collection 
    and add fields to your form 
*/ 
{{ form_start(form) }} 
    <ul class="turns" data-prototype="{{ form_widget(form.turns.vars.prototype)|e('html_attr') }}"> 
     {% for turn in form.turns %} 
      <li>{{ form_row(turn.turn) }}</li> 
     {% endfor %} 
    </ul> 
{{ form_end(form) }} 

<script> 
    var $collectionHolder; 

    // setup an "add a turn" link 
    var $addTurnLink = $('<a href="#" class="add_turn_link">Add a turn</a>'); 
    var $newLinkLi = $('<li></li>').append($addTurnLink); 

    jQuery(document).ready(function() { 
     // Get the ul that holds the collection of turns 
     $collectionHolder = $('ul.turns'); 

     // add the "add a turn" anchor and li to the turns ul 
     $collectionHolder.append($newLinkLi); 

     // count the current form inputs we have (e.g. 2), use that as the new 
     // index when inserting a new item (e.g. 2) 
     $collectionHolder.data('index', $collectionHolder.find(':input').length); 

     $addTurnLink.on('click', function(e) { 
      // prevent the link from creating a "#" on the URL 
      e.preventDefault(); 

      // add a new turn form (see next code block) 
      addTurnForm($collectionHolder, $newLinkLi); 
     }); 
    }); 

    function addTurnForm($collectionHolder, $newLinkLi) { 
     // Get the data-prototype explained earlier 
     var prototype = $collectionHolder.data('prototype'); 

     // get the new index 
     var index = $collectionHolder.data('index'); 

     // Replace '__name__' in the prototype's HTML to 
     // instead be a number based on how many items we have 
     var newForm = prototype.replace(/__name__/g, index); 

     // increase the index with one for the next item 
     $collectionHolder.data('index', index + 1); 

     // Display the form in the page in an li, before the "Add a turn" link li 
     var $newFormLi = $('<li></li>').append(newForm); 
     $newLinkLi.before($newFormLi); 
    } 
</script> 
+0

あなたはいくつかの説明を追加する必要があります。 – Veve

+0

@Veveあなたは正しいです、私はちょうどいくつか持っていました – OlivierC

関連する問題