Symfony2 设置默认的选择字段选项

69
我正在以下方式创建一个表单:
$form = $this->createFormBuilder($breed)
             ->add('species', 'entity', array(
                  'class' => 'BFPEduBundle:Item',
                  'property' => 'name',
                  'query_builder' => function(ItemRepository $er){
                      return $er->createQueryBuilder('i')
                                ->where("i.type = 'species'")
                                ->orderBy('i.name', 'ASC');
                  }))
             ->add('breed', 'text', array('required'=>true))
             ->add('size', 'textarea', array('required' => false))
             ->getForm()

如何为物种下拉列表设置默认值?


谢谢您的回复,我很抱歉,我认为我应该重新表达我的问题。一旦我从模型中检索到一个值,如何将该值设置为物种选择列表中相应值的SELECTED="yes"?

因此,TWIG视图输出的选择选项将显示如下:

<option value="174" selected="yes">Dog</option>

@Mat 我不确定所选的(看到我做了什么吗?)答案是最好的选择? - crmpicco
12个回答

115

你可以从"data"属性中定义默认值。这是抽象的“field”类型的一部分(http://symfony.com/doc/2.0/reference/forms/types/field.html)。

$form = $this->createFormBuilder()
            ->add('status', 'choice', array(
                'choices' => array(
                    0 => 'Published',
                    1 => 'Draft'
                ),
                'data' => 1
            ))
            ->getForm();

在这个例子中,“草稿”将被设置为默认选定值。


这对我有用。我在“数据”属性中提供了一组默认值,也起作用了。谢谢! - Nils Luxton
3
似乎对于单选按钮无法起作用,可能只是我自己的问题。 - Jason Swett
2
数据必须引用选择数组的键。如果您有多个选择:array('foo1' => 'bar1', 'foo2' => 'bar2',...),那么您必须指定'data' => array('foo1', 'foo2',...)。Jason,也许这就是你的问题所在。 - Julien
我认为这应该是首选答案。它非常易于使用。 - Alvin Bunk
如果您将任何实体传递给表单(例如编辑页面),则会覆盖从实体获取的值,这不是一个好方法。 - Vincent Decaux

60

如果您使用Cristian的解决方案,您需要将EntityManager注入到您的FormType类中。这是一个简化的示例:

class EntityType extends AbstractType{
    public function __construct($em) {
        $this->em = $em;
    }

    public function buildForm(FormBuilderInterface $builder, array $options){
         $builder
             ->add('MyEntity', 'entity', array(
                     'class' => 'AcmeDemoBundle:Entity',
                     'property' => 'name',
                     'query_builder' => function(EntityRepository $er) {
                         return $er->createQueryBuilder('e')
                             ->orderBy('e.name', 'ASC');
                     },
                     'data' => $this->em->getReference("AcmeDemoBundle:Entity", 3)
        ));
    }
}

你的控制器:

 // ...    

 $form = $this->createForm(new EntityType($this->getDoctrine()->getManager()), $entity);

// ...

来自Doctrine文档:

方法EntityManager#getReference($entityName, $identifier)允许您获取一个对实体的引用,其标识符已知,而无需从数据库加载该实体。例如,当您想要建立与具有标识符的实体的关联时,这非常有用作为性能增强。


5
Symfony2中预选选择字段的完美答案 - Ajay Patel
1
这也可以用来创建一个数组,该数组可用于实体字段类型的“preferred_choices”。 - j_goldman
Symfony2.0中替代选项data的是什么? - smarber
1
如果这个解决方案对您有帮助,请务必去给Cristian的解决方案点个赞 :) - Carrie Kendall
你会如何在Symfony3中实现这个?你不能再注入实体管理器了,是吗? - Roubi

23

解决方案:对于实体类型,请使用选项"data",但值为对象。例如:

$em = $this->getDoctrine()->getEntityManager();

->add('sucursal', 'entity', array
(

    'class' => 'TestGeneralBundle:Sucursal',
    'property'=>'descripcion',
    'label' => 'Sucursal',
    'required' => false,
    'data'=>$em->getReference("TestGeneralBundle:Sucursal",3)           

))

7

我认为你应该简单地使用$breed->setSpecies($species),例如在我的表单中:

$m = new Member();
$m->setBirthDate(new \DateTime);
$form = $this->createForm(new MemberType, $m);

这会将我的默认选择设置为当前日期,对于外部实体应该以相同的方式工作...


我的问题与DateType完全相同 - 但我的故事是将"" => "Choose..."添加为默认选定选项,以强制出生日期的合理选择。我可以让"Choose"显示在选项中,但无法将其设置为默认值。无论我尝试哪种方式,Symfony都会抱怨它期望一个DateTime类型的参数。我使用的是较旧版本的Symfony2;我认为他们通过新的占位符选项进行了改进。 - phpguru

5
如果你想传入一个Doctrine实体数组,可以尝试以下方法(Symfony 3.0+):
protected $entities;
protected $selectedEntities;

public function __construct($entities = null, $selectedEntities = null)
{
    $this->entities = $entities;
    $this->selectedEntities = $selectedEntities;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('entities', 'entity', [
        'class' => 'MyBundle:MyEntity',
        'choices' => $this->entities,
        'property' => 'id',
        'multiple' => true,
        'expanded' => true,
        'data' => $this->selectedEntities,
    ]);
}

1
很好的解决方案,当将实体渲染为复选框并且需要根据实体的某个属性值设置一些选中时,非常有效。 - TheGhost
在Symfony 2.8+中不起作用,您需要提供类名而不是对象。 - user3676604

3
我认为你不应该使用data选项,因为它不仅仅是设置默认值。你还覆盖了在表单创建期间传递给表单的任何数据。所以基本上,你破坏了该功能的支持。- 当你让用户创建数据时可能无关紧要,但当你想要(某天)使用该表单更新数据时就很重要。
请参阅http://symfony.com/doc/current/reference/forms/types/choice.html#data 我认为最好在控制器中在表单创建期间传递任何默认数据。
例如,你可以传递一个类并在类本身中定义默认值。(当使用默认的Symfony\Bundle\FrameworkBundle\Controller\Controller时)
$form = $this->createForm(AnimalType::class, [
    'species' => 174 // this id might be substituted by an entity
]);

或者当使用对象时:

$dog = new Dog();
$dog->setSpecies(174); // this id might be substituted by an entity

$form = $this->createForm(AnimalType::class, $dog);

使用工厂模式更好: (其中的dog很可能是从animal继承而来)
$form = $this->createForm(AnimalType::class, DogFactory::create());

这将使您能够将表单结构和内容分开,使您的表单在更多情况下可重用。


或者,使用preferred_choices选项,但这会导致默认选项移动到表单顶部。

参见:http://symfony.com/doc/current/reference/forms/types/choice.html#preferred-choices

$builder->add(
    'species', 
    'entity', 
    [
        'class' => 'BFPEduBundle:Item',
        'property' => 'name',
        'query_builder' => ...,
        'preferred_choices' => [174] // this id might be substituted by an entity
     ]
 );

2

我不确定你在这里做错了什么,当我使用表单类构建表单时,Symfony会自动选择列表中的正确选项。以下是一个有效的表单示例。

在编辑操作的控制器中:

$entity = $em->getRepository('FooBarBundle:CampaignEntity')->find($id);

if (!$entity) {
throw $this->createNotFoundException('Unable to find CampaignEntity entity.');
}


$editForm = $this->createForm(new CampaignEntityType(), $entity);
$deleteForm = $this->createDeleteForm($id);

return $this->render('FooBarBundle:CampaignEntity:edit.html.twig', array(
        'entity'      => $entity,
        'edit_form'   => $editForm->createView(),
        'delete_form' => $deleteForm->createView(),
    ));

活动实体类型类(源代码:Foo\BarBundle\Form\CampaignEntityType.php):

namespace Foo\BarBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Doctrine\ORM\EntityRepository;

class CampaignEntityType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
        ->add('store', 'entity', array('class'=>'FooBarBundle:Store', 'property'=>'name', 'em'=>'my_non_default_em','required'  => true, 'query_builder' => function(EntityRepository $er) {return $er->createQueryBuilder('s')->orderBy('s.name', 'ASC');}))
        ->add('reward');
    }
    public function getName()
    {
        return 'foo_barbundle_campaignentitytype';
    }
}

我觉得我可能在错误地构建表单,非常感谢您的示例,我会尝试一下并告诉您结果! - Matt G
嗨,Chris,我有点困惑,你似乎在一个视图中创建了两个表单,你能否提供一个Twig模板的示例以及如何在Twig模板中处理这两个表单? - Matt G
抱歉回复晚了...没看到你的评论 :( 关于编辑/删除表单,这是我在twig中拥有的内容:
{{ form_widget(edit_form) }}

{{ form_widget(delete_form) }}
- Chris
д»ҘдёӢжҳҜ createDeleteForm еҮҪж•°зҡ„д»Јз Ғпјҡprivate function createDeleteForm($id) { return $this->createFormBuilder(array('id' => $id)) ->add('id', 'hidden') ->getForm() ; } - Chris

2

来自文档:

public Form createNamed(string|FormTypeInterface $type, string $name, mixed $data = null, array $options = array())

参数 mixed $data = null 是默认选项。例如,我有一个名为 status 的字段,我将其实现如下:

$default = array('Status' => 'pending');

$filter_form = $this->get('form.factory')->createNamedBuilder('filter', 'form', $default)
        ->add('Status', 'choice', array(
            'choices' => array(
                '' => 'Please Select...',
                'rejected' => 'Rejected',
                'incomplete' => 'Incomplete',
                'pending' => 'Pending',
                'approved' => 'Approved',
                'validated' => 'Validated',
                'processed' => 'Processed'
            )
        ))->getForm();

2

为Symfony2单选按钮设置默认选项

            $builder->add('range_options', 'choice', array(
                'choices' => array('day'=>'Day', 'week'=>'Week', 'month'=>'Month'),
                'data'=>'day', //set default value 
                'required'=>true,
                'empty_data'=>null,
                'multiple'=>false,
                'expanded'=> true                   
        ))

2
如果您编辑现有实体,则该选项将始终被选择,这将导致无法正常工作。 - the_nuts
请使用“empty_data”而不是“data”设置默认值,仍然可以编辑实体。 - Ryguydg
不,empty_data在表单中并不显示任何默认值,只有在提交表单时才会使用。 - Vincent Decaux

1
表单应该自动将物种->id值映射到所选实体选择字段。例如,如果您有一个品种实体,它与一个在名为“breed_species”的联接表中具有一对一关系的物种实体相对应:
class Breed{

    private $species;

    /**
    * @ORM\OneToOne(targetEntity="BreedSpecies", mappedBy="breed")
    */
    private $breedSpecies;

    public function getSpecies(){
       return $breedSpecies->getSpecies();
    }

    private function getBreedSpecies(){
       return $this->$breedSpecies;
    }
}

表单类中的字段'species'应该从传递给表单的Breed类中的'species'属性对象中获取species->id的值。
或者,您可以通过使用SetData()将species实体显式地传递到表单来明确设置该值:
    $breedForm = $this->createForm( new BreedForm(), $breed );
    $species   = $breed->getBreedSpecies()->getSpecies();

    $breedForm->get('species')->setData( $species );

    return $this->render( 'AcmeBundle:Computer:edit.html.twig'
                        , array( 'breed'     => $breed
                               , 'breedForm' => $breedForm->createView()
            )
    );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接