2017-12-20 14 views
2

CollectionTypeを使用してsymfony 3で巨大なフォームを作成しようとしています。私は複数のサブフォームを定義しなければならず、複数のサブフォームを定義する必要があります。入れ子フォームフィールドへのアクセス(フォームコレクションの埋め込み)

これはそのための私にformTypeです:

public function buildRegistrationForm(FormBuilderInterface $builder, array $options) { 
    $builder->add('userRegistration', CollectionType::class, [ 
     'entry_type' => UserRegistrationType::class, 
     'entry_options' => ['label' => true], 
    ]); 
    $builder->add('meters', CollectionType::class, [ 
     'entry_type' => MeterType::class, 
     'entry_options' => ['label' => true], 
     'allow_add' => true, 
    ]); 
    ... 
} 

は今、私はビューのCollectionTypeはフィールドにアクセスしてみてください。

{{ form_label(registrationForm.email, null, {'label_attr': {'class': 'form-label'}}) }} 
{{ form_widget(registrationForm.email, {'attr': {'class': 'form-control'}}) }} 

が、私はエラーを取得する:このためのコードがある

Neither the property "email" nor one of the methods "email()", "getemail()"/"isemail()"/"hasemail()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView". 

私は「symfonyはメインフォーム(registrationForm)から直接電子メールのフィールドを取得しようとしますが、私はドンことを知っていますサブフォームにアクセスする方法を知っています。ドキュメント(http://symfony.com/doc/current/form/form_collections.html)には、registrationForm.userRegistration.emailを使用してサブフォームに簡単にアクセスできると記載されています。しかし、これは私にエラーを与える:

Neither the property "userRegistration" nor one of the methods ... 

私はどのようにビュー内のサブフィールドにアクセスできますか?

答えて

0
  1. 最初のステップは、collectionTypeを使用する理由を理解することです。 多対多または多対多の関係がある場合は、CollectionTypeを使用する必要があります。 例:私たちはチームと呼ばれるいくつかのエンティティを持っている。この例では

    /** 
    * Class Team 
    * 
    * @ORM\Entity 
    * @ORM\Table(name="example_project_team") 
    */ 
    class Team 
    { 
    
        // ... 
    
        /** 
        * Unidirectional Many-To-Many 
        * 
        * Many Teams has many users accounts. 
        * 
        * @var ArrayCollection $users 
        * 
        * @ORM\ManyToMany(
        *  targetEntity="AppBundle\Entity\User", 
        *  cascade={"persist", "remove"}, 
        *  orphanRemoval=true 
        * ) 
        * 
        * @ORM\JoinTable(name="teams_to_users", 
        *  joinColumns={@ORM\JoinColumn(name="team_id", referencedColumnName="id", onDelete="CASCADE")}, 
        *  inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")} 
        *  ) 
        */ 
        protected $users; 
    
        // ... 
    
    } 
    

。各チームには多くのユーザーがいます(これはあなたに関連する単なる例です)。あなたはすでにUserエンティティを作成していると思います。

  1. ユーザーエンティティのUserRegistrationTypeがあるとします。

    /** 
    * Class UserRegistrationType 
    */ 
    class UserRegistrationType extends AbstractType 
    { 
        /** 
        * @param FormBuilderInterface $builder 
        * @param array     $options 
        */ 
        public function buildForm(FormBuilderInterface $builder, array $options) 
        { 
         $builder 
          ->add('username', 'Symfony\Component\Form\Extension\Core\Type\TextType', [ 
           'label'     => false, 
           'translation_domain' => 'messages' 
          ]) 
          ->add('email', 'Symfony\Component\Form\Extension\Core\Type\TextType', [ 
           'label'     => false, 
           'translation_domain' => 'messages' 
          ]) 
    
          // ... the other fields 
    
         ; 
        } 
    
        /** 
        * @return string 
        */ 
        public function getName() 
        { 
         return 'app_user_registration_type'; 
        } 
    
        /** 
        * @return null|string 
        */ 
        public function getBlockPrefix() 
        { 
         return 'app_user_registration'; 
        } 
    
        /** 
        * @param OptionsResolver $resolver 
        */ 
        public function configureOptions(OptionsResolver $resolver) 
        { 
         $resolver->setDefaults(array(
          'data_class'   => User::class, 
          'csrf_protection'  => true, 
          'validation'   => true, 
         )); 
        } 
    } 
    

    注意を払ってください! ここに使用'data_class' => User::class, ご覧のとおり、userRegistrationTypeにUserオブジェクトを使用しています。これは、タイプがUserまたはFieldタイプのCollectionType(あなたの場合!)ではなく、ユーザーのコレクションを持つすべてのオブジェクトにこのフォームを使用できることを意味します。 チームエンティティにはフィールドユーザーがいます。

  2. ここで、userRegistrationTypeをすでに作成しているので、これをTeamFormTypeに追加できます。

    public function teamRegistrationFormType(FormBuilderInterface $builder, array $options) { 
        $builder->add('users', CollectionType::class, [ 
         'entry_type' => UserRegistrationType::class, 
          'entry_options' => [ 
           'label' => false, 
          ], 
          'label'   => false, 
          'allow_add'  => true, 
          'allow_delete' => true, 
          'by_reference' => false, 
        ]); 
    
        // ... 
    
    } 
    
  3. 最後に、小枝でフォーム:

    {# you can add this form in your twig file #} 
    <div class="box"> 
        {% block team_form %} 
        {{ form_start(team_form, { 'attr': {'class': 'form-horizontal', 'role' : 'form'}}) }} 
        <div class="box-body"> 
           <div class="form-group"> 
            {% block users_collection %} 
             <label for="" class="col-sm-2 control-label"> 
              {{ 'admin.label.phones'|trans }} 
             </label> 
             <div class="col-sm-10 users" data-prototype="{{ form_widget(team_form.users.vars.prototype)|e('html_attr') }}"> 
              {% for user in users %} 
               <div> 
                {{ form_widget(user) }} 
               </div> 
              {% endfor %} 
             </div> 
             <span class="help-block"> 
              {{ form_errors(users) }} 
             </span> 
            {% endblock users_collection %} 
           </div> 
         <div class="form-group"> 
           <div class="col-sm-offset-2 col-sm-10"> 
            <button type="submit" class="btn btn-danger"> 
             {{ 'admin.button.submit'|trans }} 
            </button> 
           </div> 
          </div> 
          {{ form_end(team_form) }} 
        </div> 
        {% endblock team_form %} 
    </div> 
    
  4. ここでは、奇妙なウィジェット{{ form_widget(user) }}を持っています。私は、あなたはこのウィジェットのスタイルを編集したいと思います。 Symfonyに組み込まれたフォームスタイルを使用してこれを行うことができます。ファイルをまだ作成していない場合は、ファイルを作成してuserRegistrationTypeのスタイルを追加します。通知は、このウィジェットの名前は、あなたの名前から作成されたアドインを設定し、ボタンを削除する必要がありますブロックのプレフィックスと文字列「_widget」(​​)

    {% file fields.html.twig %} 
    {% trans_default_domain 'messages' %} 
    
    {% block app_user_registration_widget %} 
        {% spaceless %} 
         <div class="form-group" {{ block('widget_container_attributes') }}> 
          <div class="col-sm-2"> 
           {{ form_widget(form.username, {'attr' : {'class' : 'form-control' }}) }} 
          </div> 
          <div class="col-sm-4"> 
           {{ form_widget(form.email, {'attr' : {'class' : 'form-control' }}) }} 
          </div> 
         </div> 
        {% endspaceless %} 
    {% endblock %} 
    
  5. そしてもちろんを形成します。この目的のために、公式のドキュメントを使用することをお勧めします:How to Embed a Collection of Formsまたはバンドル(ただし公式ではありません):ninsuo/symfony-collection

関連する問題