Symfony 2用数据库中的数据预先填充表单


Symfony 2 prefilled form with data from the database

我正试图用数据库中的数据填充表单字段,以便编辑它们。我已经在谷歌上搜索过了。

这里是返回空字段的控制器

public function userViewAction($id,Request $request){
    $em = $this->getDoctrine()->getManager()->getRepository('BFVMailingBundle:MailingList');
    $user = $em->findById($id);
    $form = $this->get('form.factory')->createBuilder('form',$user)
        ->add('unsubscribed','checkbox')
        ->add('name','text')
        ->add('givenName','text')
        ->add('additionalName','text',array('required'=>false))
        ->add('familyName','text',array('required'=>false))
        ->add('emailValue','text')
        ->add('language','choice',array(
            'choices'  => array('en_GB' => 'en_GB', 'es_ES' => 'es_ES', 'fr_FR' => 'fr_FR'),
            'required' => true,
        ))
        ->add('commentary','textarea',array('required'=>false))
        ->add('save','submit')
        ->getForm();

    if ($request->getMethod() == 'POST') {
        $form->bindRequest($request);
        if ($form->isValid()) {
            // perform some action, such as save the object to the database
            $em->flush();
            return $this->redirect($this->generateUrl('user_view',array('id'=>$id)));
        }
    }

这是我的模板

<div class="cell">  
    {{ form_start(form, {'attr': {'class': 'form-horizontal'}}) }}
    {{ form_end(form) }}
</div>

我错过什么了吗?

编辑-读取此解决方案

正如John Noel所暗示的那样,我用命令

构建了一个外部化的表单
php app/console doctrine:generate:form BFVMailingBundle:MailingList

我的实体是MailingList而不是User

MailingListType是一个在BFV'MailingBundle' form中生成的表单模板。数据类型是我自己添加的。

<?php
namespace BFV'MailingBundle'Form;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
class MailingListType extends AbstractType
{
/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $str = date("U");
    $codeValue = sha1($str);
    $builder
        ->add('secretCode','hidden',array( 'data' => $codeValue ))
        ->add('name','text')
        ->add('givenName','text')
        ->add('additionalName','text',array('required'=>false))
        ->add('familyName','text',array('required'=>false))
        ->add('emailValue','text')
        ->add('language','choice',array(
            'choices'  => array('en_GB' => 'en_GB', 'es_ES' => 'es_ES', 'fr_FR' => 'fr_FR'),
            'required' => true,
        ))
        ->add('unsubscribed','checkbox')
        ->add('commentary','textarea',array('required'=>false))
        ->add('save','submit')
    ;
}
/**
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'BFV'MailingBundle'Entity'MailingList'
    ));
}
/**
 * @return string
 */
public function getName()
{
    return 'bfv_mailingbundle_mailinglist';
}
}

在重新格式化的控制器中,我添加了向表单生成器添加MailingList $user[0]的实例,而不是$user。我在很多网站上读到,通常你把$变量直接放在表单构建器中,但这会产生以下错误:

The form's view data is expected to be an instance of class 
BFV'MailingBundle'Entity'MailingList, but is a(n) array. You can avoid 
this error by setting the "data_class" option to null or by adding a
view transformer that transforms a(n) array to an instance of 
BFV'MailingBundle'Entity'MailingList

因此在控制器中:

    public function userViewAction($id,Request $request){
    if (!$id) {
        throw $this->createNotFoundException('No id !!');
    }
    $em = $this->getDoctrine()->getManager()->getRepository('BFVMailingBundle:MailingList');
    $user = $em->findById($id);
    if (!$user){
        throw $this->createNotFoundException('No user with the id selected');
    }
    $form = $this->createForm(new MailingListType(), $user[0]);
    if ($request->getMethod() == 'POST') {
        $form->bindRequest($request);
        if ($form->isValid()) {
            $em->flush();
            return $this->redirect($this->generateUrl('user_view',array('id'=>$id)));
        }
    }
    return $this->render('BFVMailingBundle:Default:user_view.html.twig',array(
        'user'=>$user,
        'form'=>$form->createView()
            ));
}

结论:我得到了从数据库中填充数据的视图表单渲染。

要做到这一点,您需要查看表单类,这些表单类将充当视图(也将填充)您提供的数据。所以在你的例子中,你要创建一个表单类UserType:

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('unsubscribed','checkbox')
            ->add('name','text')
            ->add('givenName','text')
            ->add('additionalName','text',array('required'=>false))
            ->add('familyName','text',array('required'=>false))
            ->add('emailValue','text')
            ->add('language','choice',array(
                'choices'  => array('en_GB' => 'en_GB', 'es_ES' => 'es_ES', 'fr_FR' => 'fr_FR'),
                'required' => true,
            ))
            ->add('commentary','textarea',array('required'=>false))
            ->add('save','submit')
        ;
    }
    public function getName()
    {
        return 'user';
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Your'Entity'Class',
        ));
    }
}

然后在你的控制器中,你会做一些类似这样的事情:

$form = $this->createForm(new UserType(), $user);

然后是控制器的其余部分。一定要仔细阅读表单类,因为这是Symfony表单许多高级功能的起点。

我不确定这是否是造成差异的原因,但是您是否尝试过:

$form = $this->createFormBuilder($user)
             ->add(...)
             ->getForm()

您还可以检查您从DB中读取的User是否正确。

例如:

if (!is_object($user)) {
   $this->createNotFoundException('The user does not exist');
}