2016-05-03 5 views
6

У меня есть объект Product. Мой продукт может иметь несколько имен на разных языках. Имя на французском, имя на английском и т. Д. Я не хочу использовать автоматический перевод.Symfony3: поле выбора типа, заполненное массивом объектов

Пользователь должен будет записать имена в форме продукта и выбрать соответствующий язык. Он может добавить столько имен, сколько захочет, благодаря кнопке «Добавить».

Все языки создаются пользователем admin (в другой форме). Таким образом, Language также является сущностью, которая имеет имя (например: английский) и код (например: EN).

Я создал объект ProductName, который имеет имя и язык (который соответствует тому, что пользователь пишет в форме продукта).

В этом случае мне не нужно связывать Entity ProductName с Entity Language. Мне просто нужен код языка. Таким образом, в моем ProductName сущности, у меня есть это свойство:

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

Мой вид продукта (ProductType) имеет поле CollectionType, чтобы добавить несколько имен.

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

Так что, когда я иду на моей странице формы, у меня есть блок, который содержит текстовое поле ввода (Name) и выберите поле (язык). Поле выбора, как это:

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

Я не хочу объект языка, но непосредственно код языка!

Вот почему я думаю, что я не должен использовать EntityField в форме ProductNameType, но ChoiceType.

Как загрузить все языки, хранящиеся в db в поле выбора? Я надеюсь, что это объяснение более понятно ;-)

+0

Если я хорошо понимаю: вы пытались создать метод '__toString()', который возвращает свойство 'code' объекта' Language'? – Delphine

+0

Нет. Я не думаю, что это помогает мне. Код моего языка уже является строкой. Ex: Name = English и Code = EN. Вместо того, чтобы получить объект Язык, когда я отправляю свою форму, мне просто нужен код, который я выбрал в своем списке. – Felurian

+0

Я действительно не понимаю, что вы подразумеваете под «get» после отправки – Delphine

ответ

6

Я нашел решение благодаря этому сообщению: Passing data to buildForm() in Symfony 2.8/3.0

ProductController.php: передать пользовательские данные в качестве опции в методе 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 форма: передать пользовательские данные в опции решающие

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

Затем в функции buildForm(), добавьте entry_options опцию в поле CollectionType:

$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: передавать пользовательские данные в o ptions распознаватель (точно так же, как и в ProductForm)

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

Теперь у вас есть два варианта: либо вы хотите, чтобы ваша форма возвращает объекты или простые строки.

В моем примере мне просто нужен код языка (например, 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: возвращение языка Entity когда форма размещена:

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

Вы должны использовать choice_value из EntityType.

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

EDIT: После прочтения вашего редактирования, вы действительно правы, не используйте EntityType но ChoiceType. Чтобы заполнить choices, я думаю, вы должны ввести LanguageRepository внутри вашей формы, используя DependencyInjection, а затем создать запрос в вашем репозитории для извлечения всех кодов языков.

+0

Нет, у меня уже есть коды в качестве значений моих опций. Он не меняет данные моей формы. – Felurian

+0

Я изменил свой пост, чтобы лучше объяснить мою проблему ;-) – Felurian

+0

Хорошо, тогда я также отредактировал свой ответ. – Terenoth

 Смежные вопросы

  • Нет связанных вопросов^_^