Silex — Symfony2: формы, автоматически заполненные для текстовых форм, а не для выбора

Во-первых, наилучшие пожелания всем на этот новый 2016 год!

Я столкнулся с проблемой, которую не смог решить самостоятельно.

Я работаю над Silex (~1.3) приложение. Я кодировал простые CRUD на своих классах домена. Я также создал несколько форм Type, чтобы иметь возможность изменять мои базовые классы домена. В этом случае я должен управлять понятием State в пределах Country, Каждый является определенным классом, и State имеет один Country приписывать.

В моей форме я объявил несколько текстовых полей и Choice поле для возможности выбора страны (класс формы скопирован ниже).

Моя проблема в том, что когда я пытаюсь изменить существующий State со следующим контроллером, текстовые поля name, code, unloc заполнены данными из базы данных, но не выбор country ни hub (класс контроллера копируется ниже).

Обратите внимание, что я не использую Doctrine, а самодельный (и довольно простой) DAO.

Вот мой код и некоторая информация:

  1. Представление выполняется с помощью ветки, со «стандартным» примером начальной загрузки, который можно найти здесь: Настройка формы, с помощью Макет начальной загрузки а также Макет формы :

    {% extends 'layout.html.twig' %} {% block title %}{{ title }}{% endblock %}
    {% block content %}
    {% if form and is_granted('IS_AUTHENTICATED_FULLY') and is_granted('ROLE_ADMIN')%}
    {% form_theme form 'bootstrap_3_layout.html.twig' %} {{ form_start(form) }}
    <div class="form-group">
    {{ form_errors(form) }}
    {{ form_widget(form) }}
    <input type="submit" class="btn btn-primary" value={% if button is not defined %} "Save"{% else %}"{{ button }}"{% endif %} />
    </div>
    {{ form_end(form) }}
    {% else %}
    <div>
    <p>Ask an admin to add/modify information.</p>
    </div>
    {% endif %}
    {% endblock %}
    
  2. Содержание composer.json:

    {
    "require": {
    "silex/silex": "~1.3",
    "doctrine/dbal": "2.5.*",
    "symfony/security": "2.7.*",
    "twig/twig": "1.21.*",
    "symfony/twig-bridge": "2.7.*",
    "symfony/form": "2.7.*",
    "symfony/translation": "2.7.*",
    "symfony/config": "2.7.*",
    "jasongrimes/silex-simpleuser": "*",
    "twig/extensions": "1.3.*",
    "symfony/validator": "2.*",
    "phpoffice/phpexcel": "1.*"},
    "require-dev": {
    "phpunit/phpunit": "*",
    "symfony/browser-kit": "*",
    "symfony/css-selector": "*",
    "silex/web-profiler": "*",
    "symfony/monolog-bridge": "*"},
    "autoload":{
    "psr-4":{"Easytrip2\\": "src"}
    }
    }
    
  3. Код формы:

    <?php
    
    namespace Easytrip2\Form\Type;
    
    use Easytrip2\DAO\CountryDAO;
    use Easytrip2\DAO\GeopointDAO;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    
    class StateType extends AbstractType {
    /**
    * @CountryDAO
    * \Easytrip2\DAO\CountryDAO
    * allow to find the Country for the form.
    */
    private $countryDAO;
    /**
    * @GeopointDAO
    * \Easytrip2\DAO\GeopointDAO
    * allow to find the Country for the form.
    */
    private $geopointDAO;
    /**
    *
    * {@inheritDoc}
    *
    * @see \Symfony\Component\Form\AbstractType::buildForm()
    */
    public function buildForm(FormBuilderInterface $builder, array     $options) {
    $builder->add ( 'name', 'text', array (
    'label' => 'State name'
    ) );
    $builder->add ( 'code', 'text', array (
    'label' => 'State code'
    ) );
    $builder->add ( 'unloc', 'text', array (
    'label' => 'State code'
    ) );
    $countries = $this->countryDAO->findAll ();
    $choices = array ();
    $labels = array ();
    foreach ( $countries as $value ) {
    $choices [] = $value;
    $labels [] = $value->getName ();
    }
    $builder->add ( 'country', 'choice', array (
    'choice_list' => new ChoiceList ( $choices, $labels )
    ) );
    
    $hubs = $this->geopointDAO->findAllHubs ();
    $choices = array ();
    $labels = array ();
    foreach ( $hubs as $value ) {
    $choices [] = $value;
    $labels [] = $value->getName ();
    }
    $builder->add ( 'hub', 'choice', array (
    'choice_list' => new ChoiceList ( $choices, $labels ),
    'required' => false
    ) );
    }
    
    /**
    *
    * {@inheritDoc}
    *
    * @see \Symfony\Component\Form\AbstractType::configureOptions()
    */
    public function configureOptions(OptionsResolver $resolver) {
    $resolver->setDefaults ( array (
    'data_class' => 'Easytrip2\Domain\State'
    ) );
    }
    
    /**
    *
    * {@inheritDoc}
    *
    * @see \Symfony\Component\Form\FormTypeInterface::getName()
    */
    public function getName() {
    return 'state';
    }
    /**
    * allow use of a CountryDAO
    */
    public function __construct(CountryDAO $countryDAO, GeopointDAO     $geopointDAO) {
    $this->geopointDAO = $geopointDAO;
    $this->countryDAO = $countryDAO;
    }
    }
    
  4. Контроллер контента:

    public function stateUpdateByIdAction($id, Request $request, Application $app) {
    if ($app ['security.authorization_checker']->isGranted ( 'IS_AUTHENTICATED_FULLY' ) and $app ['security.authorization_checker']->isGranted ( 'ROLE_ADMIN' )) {
    $obj = $app ['dao.state']->findById ( $id );
    $form = $app ['form.factory']->create ( new StateType ( $app ['dao.country'], $app ['dao.geopoint'] ), $obj );
    $form->handleRequest ( $request );
    if ($form->isSubmitted () && $form->isValid ()) {
    if ($app ['dao.state']->save ( $obj )) {
    $app ['session']->getFlashBag ()->add ( 'success', 'The state was succesfully updated.' );
    return $app->redirect ( $app ['url_generator']->generate ( 'state' ) );
    } else {
    $app ['session']->getFlashBag ()->add ( 'error', 'Something went wrong...' );
    }
    }
    return $app ['twig']->render ( 'form.html.twig', array (
    'form' => $form->createView (),
    'title' => 'Edit states'
    ) );
    } else {
    $app ['session']->getFlashBag ()->add ( 'error', 'Don\'t have the rights...' );
    return $app->redirect ( $app ['url_generator']->generate ( 'home' ) );
    }
    }
    

0

Решение

Предположим, что выбор не заполнен данными из БД, потому что страна и идентификатор концентратора не передаются в ChoiceList

$choices = array();
foreach ($countries as $value) {
$choices[$value->getId()] = $value->getName();
}
$builder->add('country', 'choice', array(
'choices' => $choices
));
0

Другие решения

Добавьте эту строку в ваш выбор вариантов:

'choices_as_values' => true,

Необходимо активировать новый API выбора типа
http://symfony.com/doc/current/reference/forms/types/choice.html#example-usage

0

Мне удалось найти решение (возможно, не лучшее, но оно работает).

Я понимаю это как: мы даем объект как choices, используйте его как значение, а затем используйте закрытие, чтобы получить ids а также labelsвместо того, чтобы делать работу самостоятельно и предоставлять готовые данные в форму.

Есть ли более чистый способ сделать это?

$obj = $this->countryDAO->findAll ();
$list = array ();
foreach ( $obj as $value ) {
$list [$value->getId ()] = $value;
}
$builder->add ( 'country', 'choice', array (
'choices' => $list,
'choices_as_values' => true,
'choice_label' => function ($value) {
return $value->getName ();
},
'choice_value' => function ($value) {
// you mightwant to check for null here, is your form concern
// a attribute that can be null, as the closure appear to be called
// on the attribute, and not only on the $obj contents;
return $value->getId ();
},
'placeholder' => 'Select a country'
) );
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector