2016-05-03 4 views
6

Ich habe eine Entität Product. Mein Produkt kann mehrere Namen in verschiedenen Sprachen haben. Ein Name auf Französisch, ein Name auf Englisch usw. Ich möchte keine automatische Übersetzung verwenden.Symfony3: Choice-Typ-Feld mit Array von Objekten gefüllt

Der Benutzer muss die Namen in das Produktformular schreiben und die entsprechende Sprache auswählen. Er kann so viele Namen hinzufügen, wie er möchte, dank einer Schaltfläche "Hinzufügen".

Alle Sprachen werden vom Benutzer admin (in einer anderen Form) erstellt. Also, Language ist auch eine Entität, die einen Namen (zB: Englisch) und einen Code (zB: EN) hat.

Ich erstellte die Entität ProductName, die einen Namen und eine Sprache haben (die dem entsprechen, was der Benutzer in der Produktform schreibt). In diesem Fall muss die Entität ProductName nicht mit der Entität Language verknüpft werden. Ich möchte nur den Sprachcode. Also, meine ProductName Einheit, ich habe diese Eigenschaft:

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

Meine Produktform (Product) eine Collection Feld, um mehrere Namen hinzuzufügen.

// Form/ProductType.php 

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

Und ProductInfosType Form hat zwei Felder:

// 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'); 
      } 
     )) 

Also, wenn ich auf meiner Form Seite gehen, ich habe einen Block, der ein Eingabetextfeld (Name) und ein Auswahlfeld enthält (Sprache). Das Auswahlfeld ist wie folgt:

<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> 

An diesem Punkt alles funktioniert gut. Ich habe ein Add-Taste, so dass der Benutzer andere Namen hinzufügen können, etc ...

Aber, wenn ich das Formular aus, wenn ich Formulardaten in meinem Product überprüfen, bemerkte ich, dass es nicht dem entspricht, was ich möchte in der Datenbank speichern.

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 
     ) 
) 

Was würde Ich mag ist:

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

Ich möchte die Sprache nicht Objekt, sondern direkt den Sprachcode!

Deshalb denke ich, dass ich nicht EntityField im ProductNameType Formular aber ChoiceType Feld verwenden sollte.

Wie kann ich alle in db gespeicherten Sprachen in das Auswahlfeld laden? Ich hoffe, dass diese Erklärung verständlicher ist ;-)

+0

Wenn ich es gut verstehe: Haben Sie versucht, eine '__toString()' Methode zu erstellen, die Ihre 'code' Eigenschaft von' Language' entity zurückgibt? – Delphine

+0

Nein. Ich glaube nicht, dass es mir hilft. Der Code meiner Sprache ist bereits eine Zeichenfolge. Beispiel: Name = Englisch und Code = EN. Anstatt eine Objektsprache zu erhalten, wenn ich mein Formular absende, möchte ich nur den Code, den ich in meiner Liste ausgewählt habe. – Felurian

+0

Ich verstehe nicht wirklich, was Sie mit "erhalten" nach dem Einreichen – Delphine

Antwort

6

fand ich die Lösung dank diesem Beitrag: Passing data to buildForm() in Symfony 2.8/3.0

ProductController.php: kundenspezifische Daten als Option in der createForm()-Methode übergeben.

// ... 

// 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 
)); 

Product Form: benutzerdefinierte Daten übergeben in die Optionen Dann

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

Resolver, in der buildForm() Funktion, fügen Sie eine entry_options Option im Collection Feld:

$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 
)); 

ProductInfosType-Formular: übergeben Sie benutzerdefinierte Daten in der o ptionen Resolver (genau das gleiche wie in der Product)

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

Jetzt haben Sie zwei Alternativen: Entweder Sie möchten, dass Ihre Form Entitäten oder einfache Zeichenfolgen zurückgibt.

In meinem Beispiel möchte ich nur den Sprachcode (wie FR, EN, etc.).

Fall 1: Rückkehr der Sprachcode nur, wenn das Formular geschrieben wird:

// 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  
     ) 
) 

Fall 2: Sprache Entity zurückkehren, wenn das Formular geschrieben wird: Mit diesem

// 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 
       )  
     ) 
) 

Lösung, müssen wir unsere Form nicht als Service erstellen, um den Entity Manager als Argument zu übergeben. Alles wird in den Controller- und Formularoptionen verwaltet.

1

Sie sollten choice_value von EntityType verwenden.

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

EDIT: nach dem Bearbeiten zu lesen, sind Sie in der Tat richtig, nicht EntityType nicht aber ChoiceType verwenden. Zum Füllen choices, ich denke, Sie sollten injizieren LanguageRepository in Ihrem Formular mit DependencyInjection, und erstellen Sie dann eine Abfrage in Ihrem Repository, um alle Sprachencodes abzurufen.

+0

Nein, ich habe bereits Codes als Werte meiner Auswahloptionen. Es ändert nicht die Daten meines Formulars. – Felurian

+0

Ich habe meinen Beitrag geändert, um mein Problem besser zu erklären ;-) – Felurian

+0

Alles klar, dann habe ich auch meine Antwort bearbeitet. – Terenoth