2012-08-26 20 views
12

の第三層に取り組んでいない私は3つの層を持つフォームを持っている: 第一層は、ゲームのためのコンテナである:私はしませんので、カスケード検証フォーム

class GameListType extends AbstractType { 

    public function buildForm(FormBuilderInterface $builder, array $options) { 
     $builder->add('games', 'collection', array(
      'required' => false, 
      'allow_add' => true, 
      'prototype' => true, 
      'by_reference' => false, 
      'type' => new GameBetType(), 
     )) 
     ; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) { 
     parent::setDefaultOptions($resolver); 
     $resolver->setDefaults(array(
      'cascade_validation' => true, 
     )); 
    } 
} 

第二の層は、ゲームそのものですゲームを変更しようとするが、それに賭け、それが唯一の賭けのためのフォームが含まれています

class GameBetType extends AbstractType { 

    public function buildForm(FormBuilderInterface $builder, array $options) { 
     $builder->add('bet', new BetType()); 
    } 

    public function setDefaultOptions(\Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver) { 
     parent::setDefaultOptions($resolver); 
     $resolver->setDefaults(array(
      'data_class' => 'Strego\TippBundle\Entity\Game', 
      'cascade_validation' => true, 
     )); 
    } 
} 

と第3層は、賭けのための形式です:

class BetType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 

     $builder->add('scoreT1' , 'text') 
       ->add('scoreT2' , 'text'); 
     ; 
    } 


     public function setDefaultOptions(\Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver) { 
     parent::setDefaultOptions($resolver); 
     $resolver->setDefaults(array(
      'data_class' => 'Strego\TippBundle\Entity\Bet', 
     )); 
    } 

} 

私は特にベットエンティティを検証する場合、第3レベルの検証制約がある場合、ルートフォームが常に有効であること、しかし、私は私のコントローラで正しい違反のリストを取得されている問題:

// Form processing 
$form = $this->createForm(new GameListType(), $entity); 
$request = $this->getRequest(); 

if ($request->getMethod() == 'POST') { 
    $form->bind($request); 
    $entity = $form->getData(); 

    if ($form->isValid()) { 
     foreach ($entity->getGames() as $game) {     
      if($game->hasBet()){ 
       $bet = $game->getBet(); 
       $bet->setUser($user); 
       $validator = $this->container->get('validator'); 
       $errors = $validator->validate($bet); 
       var_dump($errors) //<-- i see there are errors 
       if(count($errors) == 0){ 
        print($bet. ' gets persisted<br>'); 
        $em->persist($bet); 
       } 
      }    
     } 
    $em->flush(); 
    } 
} 

別の問題は、私が$em->persist($bet)と呼んでもエンティティが永続化されるということです。

print($bet.'gets persisted<br>'); 

出力は表示されますが、フォーム入力は依然としてデータベースに保持されています。

だから私の二つの質問:

  1. 検証が賭けに失敗した場合、私はエラーを取得するにはどうすればよいが、フォームに失敗しただけであっ可能性があるので、(私は、フォーム全体が無効になりたくありません3賭けのうち1賭けは無効です)。

  2. 私が$em-persist($bet)に電話をかけなくても、なぜベットが持続するのですか?これはバインディングで起こるいくつかの魔法ですか?

+0

親切にもクラスAbstractTypeを提供 – Vineet1982

+0

そのSymfony2のデフォルトAbstractTypeをcascade_validationを追加することを忘れ/Symfony/Component/Form/AbstractType.php – m0c

答えて

3

2番目の質問に答えるために、あなたはUserBetエンティティ間の双方向OneToMany関係を宣言し、関係のUser側にcascade={"persist"}を設定している場合があります。したがって、エンティティマネージャは、次のflush操作で自動的にBetエンティティオブジェクトに挿入/更新をマークします。また、ループから$em->flush();行を移動します。 flushメソッドはdbクエリを発行するので、コードがループに入るたびにdbに接続します。 $em->flush();がループ外にある場合、エンティティは1回のトランザクションでラップされたすべての変更されたsqlを使用して1回クエリを実行します。

+0

私は秘密の関係を持っていますが、どちらの側にもカスケード= {persist}はありません。フラッシュはループの外側にあります。おそらく、私はそれを間違ってコピーしました。 – m0c

0

gameエンティティではなく、betエンティティを保持する必要があります。

検証グループの設定があるかどうかを検証するために、検証が正しく行われていない可能性があります。 https://github.com/symfony/symfony/blob/master/src:

+0

このフォームでは、賭けのみが提出され、ゲームは前に存在し、変更されていません。検証グループはありません。 – m0c

1

あなただけcollectionタイプにゲームに

$builder->add('games', 'collection', array(
    'required' => false, 
    'allow_add' => true, 
    'prototype' => true, 
    'by_reference' => false, 
    'type' => new GameBetType(), 
    'cascade_validation' => true 
));