2016-05-03 11 views
6

私はエンティティProductを持っています。私の製品は、異なる言語で複数の名前を持つことができます。フランス語の名前、英語の名前など。私は自動翻訳を使いたくない。Symfony3:オブジェクトの配列で埋められた選択型フィールド

ユーザーは、製品フォームに名前を入力し、対応する言語を選択する必要があります。彼はAddボタンのおかげでたくさんの名前を追加できます。

すべての言語は管理者によって(別の形式で)作成されます。したがって、Languageは、名前(例:英語)とコード(例:EN)を持つエンティティです。

私はエンティティProductNameを作成しました。このエンティティは名前と言語(ユーザーが製品フォームに書き込んだ内容に準拠しています)を持っています。

この場合、エンティティProductNameをエンティティLanguageに関連付ける必要はありません。私は言語コードがほしいのです。

/** 
* @ORM\Column(name="Language_Code", type="string", length=2) 
*/ 
private $language; 

マイプロダクト形(でProductType)複数の名前を追加するためにCollectionTypeはフィールドを持つ:だから、私のProductNameエンティティに、私は、このプロパティを持っています。

// Form/ProductType.php 

    ->add('infos',  CollectionType::class, array(
     'entry_type' => ProductInfosType::class, 
     'allow_add'  => true, 
     'allow_delete' => true, 
     'prototype'  => true, 
     'label'   => false, 
     'mapped'  => false 
    )) 

そしてProductInfosTypeフォームは2つのフィールドがありますので、

// Form/ProductInfosType.php 

     ->add('name',   TextType::class, array(
      'attr'    => array('size' => 40) 
     )) 
     ->add('language',  EntityType::class, array(
      'placeholder'  => '', 
      'class'    => 'AppBundle:Language', 
      'choice_label'  => 'code', 
      'attr'    => array('class' => 'lang'), 
      'query_builder'  => function (EntityRepository $er) { 
       return $er->createQueryBuilder('l')->orderBy('l.code', 'ASC'); 
      } 
     )) 

を、私は私のフォームページに行くとき、私は入力テキストフィールド(名前)と選択フィールドが含まれているブロックを持っている(言語)。選択フィールドは、このようなものです:この時点で

<select id="product_infos_0_language" required="required" name="product[infos][0][language]"> 
    <option value=""></option> 
    <option value="DE">DE</option> 
    <option value="EN">EN</option> 
    <option value="ES">ES</option> 
    <option selected="selected" value="FR">FR</option> 
</select> 

、すべてがうまく動作します。ユーザーが他の名前などを追加できるように追加ボタンを作成しました。

しかし、フォームを送信すると、ProductControllerでフォームデータをチェックすると、私はそれに対応していませんデータベースに保存したい私が望む何

print_r($form->get('infos')->getData()); 

// returns : 
Array 
(
    [0] => AppBundle\Entity\ProductName Object 
     ( 
      [language:AppBundle\Entity\ProductName:private] => AppBundle\Entity\Language Object 
       (
        [code:AppBundle\Entity\Language:private] => FR 
        [name:AppBundle\Entity\Language:private] => Français 
       ) 

      [name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin 
     ) 
) 

は次のとおりです。

Array 
(
    [0] => AppBundle\Entity\ProductName Object 
     ( 
      [language:AppBundle\Entity\ProductName:private] => FR  
      [name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin 
     ) 
) 

私は言語オブジェクトをしたいが、直接言語コードはありません!

だから、ProductNameTypeフォームにはEntityFieldを使用しないでくださいが、ChoiceTypeフィールドとしてください。

dbに格納されているすべての言語を選択フィールドにロードするにはどうすればよいですか? この説明を理解していただければ幸いです。

+0

私がよく理解していれば、 'Language'エンティティの' code'プロパティを返す '__toString()'メソッドを作成しようとしましたか? – Delphine

+0

いいえ、私はそれが私を助けるとは思わない。私の言語のコードはすでに文字列です。 例:名前=英語とコード= EN。 フォームを送信するときにオブジェクトを取得する代わりに、自分のリストで選択したコードが必要です。 – Felurian

+0

提出後に「取得」することが本当にわかりません – Delphine

答えて

6

私はこの投稿への解決策のおかげで見つかった:ProductController.phpPassing data to buildForm() in Symfony 2.8/3.0

を:createForm()方法のオプションとしてカスタムデータを渡します。

// ... 

// build the form 
$em = $this->getDoctrine()->getManager(); 
$product = new Product(); 
$languages = $em->getRepository('AppBundle:Language')->findAllOrderedByCode(); 

$form = $this->createForm(ProductType::class, $product, array(
    'languages' => $languages 
)); 

でProductTypeフォーム

$builder->add('infos', CollectionType::class, array(
    'entry_type' => ProductInfosType::class, 
    'entry_options' => array('languages' => $options['languages']), 
    'allow_add'  => true, 
    'allow_delete' => true, 
    'prototype'  => true, 
    'label'   => false, 
    'by_reference' => false 
)); 

:CollectionTypeはフィールドにentry_optionsオプションを追加し、buildForm()機能では、次に

public function configureOptions(OptionsResolver $resolver) { 
    $resolver->setDefaults(array(
     'data_class' => 'AppBundle\Entity\Product', 
     'languages' => null 
    )); 
} 

レゾルバオプションでカスタムデータを渡しますProductInfosType form:oでカスタムデータを渡すptionsリゾルバ(ProductFormと全く同じ)

public function configureOptions(OptionsResolver $resolver) { 
    $resolver->setDefaults(array(
     'data_class' => 'AppBundle\Entity\ProductName', 
     'languages' => null 
    )); 
} 

今、あなたは2つの方法があります。どちらかのあなたのフォームがエンティティまたは単純な文字列を返すことにしたいです。

私の例では、言語コード(FR、ENなど)がほしいだけです。

ケース1:フォームがポストされたときのみ、言語コードを返す:

// Form/ProductInfosType.php 

// ... 

// Convert array of objects in an array of strings 
$choices = array(); 
foreach ($options['languages'] as $lang) { 
    $code = $lang->getCode(); 
    $choices[$code] = $code; 
} 

$builder->add('language', ChoiceType::class, array(
    'placeholder'  => '', 
    'choices'   => $choices 
)); 

// returns : 
Array 
(
    [0] => AppBundle\Entity\ProductName Object 
     ( 
      [name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin 
      [language:AppBundle\Entity\ProductName:private] => FR  
     ) 
) 

ケース2:フォームがポストされたときの言語のエンティティを返します。これにより

// Form/ProductInfosType.php 

// ... 

$builder->add('language', ChoiceType::class, array(
    'placeholder'  => '', 
    'choices'   => $options['languages'], 
    'choice_label'  => 'code', 
    'choice_value'  => 'code' 
)); 

// returns : 
Array 
(
    [0] => AppBundle\Entity\ProductName Object 
     ( 
      [name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin 
      [language:AppBundle\Entity\ProductName:private] => AppBundle\Entity\Language Object 
       (
        [code:AppBundle\Entity\Language:private] => FR 
        [name:AppBundle\Entity\Language:private] => Français 
       )  
     ) 
) 

ソリューションとして、エンティティマネージャを引数として渡すために、サービスとしてフォームを作成する必要はありません。すべてがコントローラとフォームオプションで管理されます。

1

EntityTypeの choice_valueを使用してください。EDIT

'choice_value' => function ($language) { return $language->getCode(); }, 

あなたの編集を読んだ後、あなたは EntityTypeが、 ChoiceTypeを使用していない、右確かです。 choicesを入力するには、DependencyInjectionを使用してフォーム内に LanguageRepositoryを注入し、すべての言語コードを取得するためにリポジトリにクエリを作成する必要があります。

+0

いいえ、私の選択オプションの値としてのコードはすでにあります。私のフォームのデータは変更されません。 – Felurian

+0

私の問題をよりよく説明するために自分の投稿を変更しました;-) – Felurian

+0

いいえ、私は私の答えも編集しました。 – Terenoth

関連する問題