跳到内容

ChoiceType 字段(选择下拉列表、单选按钮和复选框)

编辑此页

一个多用途字段,用于允许用户“选择”一个或多个选项。它可以渲染为 select 标签、单选按钮或复选框。

要使用此字段,您必须指定 或者 choiceschoice_loader 选项。

渲染为 可以是各种标签(见下文)
默认无效消息 所选选项无效。
父类型 FormType
ChoiceType

提示

要查看此表单类型定义和继承的完整选项列表,请在您的应用中运行以下命令

1
2
# replace 'FooType' by the class name of your form type
$ php bin/console debug:form FooType

用法示例

使用此字段的最简单方法是定义 choices 选项,以指定选项为关联数组,其中键是显示给最终用户的标签,而数组值是在表单字段中使用的内部值

1
2
3
4
5
6
7
8
9
10
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('isAttending', ChoiceType::class, [
    'choices'  => [
        'Maybe' => null,
        'Yes' => true,
        'No' => false,
    ],
]);

这将创建一个如下所示的 select 下拉列表

A choice list form input with the options "Maybe", "Yes" and "No".

如果用户选择 No,则表单将为此字段返回 false。 同样,如果此字段的起始数据为 true,则将自动选择 Yes。换句话说,每个项目的选项是您要在 PHP 代码中获取/设置的值,而是显示给用户的标签

高级示例(使用对象!)

此字段有很多选项,大多数选项控制字段的显示方式。在此示例中,底层数据是一些 Category 对象,该对象具有 getName() 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
use App\Entity\Category;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('category', ChoiceType::class, [
    'choices' => [
        new Category('Cat1'),
        new Category('Cat2'),
        new Category('Cat3'),
        new Category('Cat4'),
    ],
    // "name" is a property path, meaning Symfony will look for a public
    // property or a public method like "getName()" to define the input
    // string value that will be submitted by the form
    'choice_value' => 'name',
    // a callback to return the label for a given choice
    // if a placeholder is used, its empty value (null) may be passed but
    // its label is defined by its own "placeholder" option
    'choice_label' => function (?Category $category): string {
        return $category ? strtoupper($category->getName()) : '';
    },
    // returns the html attributes for each option input (may be radio/checkbox)
    'choice_attr' => function (?Category $category): array {
        return $category ? ['class' => 'category_'.strtolower($category->getName())] : [];
    },
    // every option can use a string property path or any callable that get
    // passed each choice as argument, but it may not be needed
    'group_by' => function (): string {
        // randomly assign things into 2 groups
        return rand(0, 1) === 1 ? 'Group A' : 'Group B';
    },
    // a callback to return whether a category is preferred
    'preferred_choices' => function (?Category $category): bool {
        return $category && 100 < $category->getArticleCounts();
    },
]);

您还可以自定义每个选项的 choice_name。您可以在以下部分中了解有关所有这些选项的更多信息。

警告

占位符是一个特定字段,当选项是可选的时,列表中的第一项必须为空,以便用户可以取消选择。使用回调时,请务必始终处理空选项 null

选择标签、复选框或单选按钮

此字段可以渲染为多个 HTML 字段之一,具体取决于 expandedmultiple 选项

元素类型 展开 多选
select 标签 false false
select 标签(带有 multiple 属性) false true
单选按钮 true false
复选框 true true

自定义每个选项的文本(标签)

通常,choices 选项中每个项目的数组键用作显示给用户的文本。但这可以通过 choice_label 选项完全自定义。查看它以获取更多详细信息。

分组选项

您可以通过传递多维 choices 数组将 <select><option> 元素分组到 <optgroup>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('stockStatus', ChoiceType::class, [
    'choices' => [
        'Main Statuses' => [
            'Yes' => 'stock_yes',
            'No' => 'stock_no',
        ],
        'Out of Stock Statuses' => [
            'Backordered' => 'stock_backordered',
            'Discontinued' => 'stock_discontinued',
        ],
    ],
]);
A choice list with the options "Yes" and "No" grouped under "Main Statuses" and the options "Backordered" and "Discontinued" under "Out of Stock Statuses".

为了更高级,请使用 group_by 选项代替。

字段选项

choices

类型array 默认值[]

这是指定此字段应使用的选项的最基本方法。choices 选项是一个数组,其中数组键是项目的标签,而数组值是项目的值

1
2
3
4
5
6
7
8
9
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('inStock', ChoiceType::class, [
    'choices' => [
        'In Stock' => true,
        'Out of Stock' => false,
    ],
]);

如果存在非标量选项值或字符串化表示不是唯一的,Symfony 将使用递增的整数作为值。当表单提交时,具有正确类型的正确值将分配给模型。

choice_attr

类型arraycallablestringPropertyPath 默认值[]

使用此选项可为每个选项添加额外的 HTML 属性。这可以是一个关联数组,其中键与选项键匹配,值是每个选项的属性,也可以是可调用对象或属性路径(就像 choice_label 一样)。

如果是数组,则必须使用 choices 数组的键作为键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('fruits', ChoiceType::class, [
    'choices' => [
        'Apple' => 1,
        'Banana' => 2,
        'Durian' => 3,
    ],
    'choice_attr' => [
        'Apple' => ['data-color' => 'Red'],
        'Banana' => ['data-color' => 'Yellow'],
        'Durian' => ['data-color' => 'Green'],
    ],
]);

// or use a callable
$builder->add('attending', ChoiceType::class, [
    'choices' => [
        'Yes' => true,
        'No' => false,
        'Maybe' => null,
    ],
    'choice_attr' => function ($choice, string $key, mixed $value) {
        // adds a class like attending_yes, attending_no, etc
        return ['class' => 'attending_'.strtolower($key)];
    },
]);

提示

定义自定义类型时,应使用 ChoiceList 类助手

1
2
3
4
5
6
7
8
9
use App\Entity\Category;
use Symfony\Component\Form\ChoiceList\ChoiceList;

// ...
$builder->add('choices', ChoiceType::class, [
    'choice_attr' => ChoiceList::attr($this, function (?Category $category): array {
        return $category ? ['data-uuid' => $category->getUuid()] : [];
    }),
]);

请参阅 “choice_loader”选项文档

choice_filter

类型callablestringPropertyPath 默认值null

当使用来自 Symfony 核心或供应商库的预定义选项类型(即 CountryType)时,此选项允许您定义一个可调用对象,该对象将每个选项作为唯一参数,并且必须返回 true 以保留它或返回 false 以丢弃它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// src/Form/Type/AddressType.php
namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CountryType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AddressType extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver
            ->setDefaults([
                // enable this type to accept a limited set of countries
                'allowed_countries' => null,
            ])
        ;
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $allowedCountries = $options['allowed_countries'];

        $builder
            // ...
            ->add('country', CountryType::class, [
                // if the AddressType "allowed_countries" option is passed,
                // use it to create a filter
                'choice_filter' => $allowedCountries ? function ($countryCode) use ($allowedCountries): bool {
                    return in_array($countryCode, $allowedCountries, true);
                } : null,

            ])
        ;
    }

当选项是对象时,该选项可以是可调用对象或属性路径

1
2
3
4
5
6
7
// ...
$builder
    ->add('category', ChoiceType::class, [
        // ...
        'choice_filter' => 'isSelectable',
    ])
;

提示

考虑到此 AddressType 可能是 CollectionType 的条目,您应该使用 ChoiceList 类助手来启用缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Form/Type/AddressType.php
// ...
use Symfony\Component\Form\ChoiceList\ChoiceList;

// ...
'choice_filter' => $allowedCountries ? ChoiceList::filter(
    // pass the type as first argument
    $this,
    function (string $countryCode) use ($allowedCountries): bool {
        return in_array($countryCode, $allowedCountries, true);
    },
    // pass the option that makes the filter "vary" to compute a unique hash
    $allowedCountries
) : null,
// ...

choice_label

类型stringcallablefalsePropertyPath 默认值null

默认情况下,choices 选项中每个项目的数组键用作显示给用户的文本。choice_label 选项允许您进行更多控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('attending', ChoiceType::class, [
    'choices' => [
        'yes' => true,
        'no' => false,
        'maybe' => null,
    ],
    'choice_label' => function ($choice, string $key, mixed $value): TranslatableMessage|string {
        if (true === $choice) {
            return 'Definitely!';
        }

        return strtoupper($key);

        // or if you want to translate some key
        //return 'form.choice.'.$key;
        //return new TranslatableMessage($key, false === $choice ? [] : ['%status%' => $value], 'store');
    },
]);

此方法为每个选项调用,从 choices 数组中传递 $choice$key (附加的 $valuechoice_value 相关)。这将为您提供

A choice list with the options "Definitely!", "NO" and "MAYBE".

如果您的选项值是对象,则 choice_label 也可以是 属性路径。假设您有一些带有 getDisplayName() 方法的 Status

1
2
3
4
5
6
7
8
9
10
11
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('attending', ChoiceType::class, [
    'choices' => [
        new Status(Status::YES),
        new Status(Status::NO),
        new Status(Status::MAYBE),
    ],
    'choice_label' => 'displayName',
]);

如果设置为 false,则将为单选或复选框输入丢弃所有标签标签。您还可以从可调用对象返回 false 以丢弃某些标签。

提示

定义自定义类型时,应使用 ChoiceList 类助手

1
2
3
4
5
6
use Symfony\Component\Form\ChoiceList\ChoiceList;

// ...
$builder->add('choices', ChoiceType::class, [
    'choice_label' => ChoiceList::label($this, 'displayName'),
]);

请参阅 “choice_loader”选项文档

choice_loader

类型ChoiceLoaderInterface

choice_loader 选项可以代替 choices 选项使用。它允许在仅获取一组提交值的选项时延迟或部分创建列表(即,查询像 ElasticSearch 这样的搜索引擎可能是一个繁重的过程)。

如果您想利用延迟加载,可以使用 CallbackChoiceLoader 的实例

1
2
3
4
5
6
7
8
9
10
use App\StaticClass;
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('loaded_choices', ChoiceType::class, [
    'choice_loader' => new CallbackChoiceLoader(static function (): array {
        return StaticClass::getConstants();
    }),
]);

如果请求被重定向并且没有预设或提交的数据,这将导致 StaticClass::getConstants() 的调用不会发生。否则,将需要解析选项,从而触发回调。

如果内置的 CallbackChoiceLoader 不符合您的需求,您可以实现 ChoiceLoaderInterface 或扩展 AbstractChoiceLoader 来创建您自己的加载器。此抽象类通过实现接口的某些方法来节省您的一些样板代码,因此您只需实现 loadChoices() 方法即可拥有一个功能齐全的选项加载器。

当您定义一个可以在许多字段(如集合的条目)中重用或在多个表单中一次重用的自定义选项类型时,您应该使用 ChoiceList 静态方法来包装加载器,并使选项列表可缓存以获得更好的性能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use App\Form\ChoiceList\CustomChoiceLoader;
use App\StaticClass;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\ChoiceList;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ConstantsType extends AbstractType
{
    public function getParent(): string
    {
        return ChoiceType::class;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            // the example below will create a CallbackChoiceLoader from the callable
            'choice_loader' => ChoiceList::lazy($this, function () {
                return StaticClass::getConstants();
            }),

            // you can pass your own loader as well, depending on other options
            'some_key' => null,
            'choice_loader' => function (Options $options): ChoiceLoaderInterface {
                return ChoiceList::loader(
                    // pass the instance of the type or type extension which is
                    // currently configuring the choice list as first argument
                    $this,
                    // pass the other option to the loader
                    new CustomChoiceLoader($options['some_key']),
                    // ensure the type stores a loader per key
                    // by using the special third argument "$vary"
                    // an array containing anything that "changes" the loader
                    [$options['some_key']]
                );
            },
        ]);
    }
}

choice_lazy

类型boolean 默认值false

7.2

choice_lazy 选项在 Symfony 7.2 中引入。

当处理大量选项时,choice_lazy 选项特别有用,因为一次加载所有选项可能会导致性能问题或延迟

1
2
3
4
5
6
7
use App\Entity\User;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;

$builder->add('user', EntityType::class, [
    'class' => User::class,
    'choice_lazy' => true,
]);

当设置为 true 并与 choice_loader 选项一起使用时,表单将仅加载和渲染预设为默认值或提交的选项。这会延迟加载完整的选项列表,从而有助于提高表单的性能。

警告

请记住,当使用 choice_lazy 时,您负责为选择选项提供用户界面,通常是通过能够动态加载选项的 JavaScript 插件。

choice_name

类型callablestringPropertyPath 默认值null

控制选项的内部字段名称。您通常不关心这一点,但在某些高级情况下,您可能会关心。例如,此“名称”成为模板中选项视图的索引,并用作字段名称属性的一部分。

这可以是可调用对象或属性路径。有关类似用法,请参阅 choice_label。默认情况下,可以使用选项键或递增的整数(从 0 开始)。

提示

定义自定义类型时,应使用 ChoiceList 类助手

1
2
3
4
5
6
use Symfony\Component\Form\ChoiceList\ChoiceList;

// ...
$builder->add('choices', ChoiceType::class, [
    'choice_name' => ChoiceList::fieldName($this, 'name'),
]);

请参阅 “choice_loader”选项文档

警告

配置的值必须是有效的表单名称。使用可调用对象时,请确保仅返回有效名称。有效的表单名称必须由字母、数字、下划线、破折号和冒号组成,并且不得以破折号或冒号开头。

choice_translation_domain

类型stringbooleannull 默认值true

此选项确定是否应翻译选项值以及在哪个翻译域中翻译。

choice_translation_domain 选项的值可以是 true (重用当前翻译域)、 false (禁用翻译)、 null (使用父翻译域或默认域)或表示要使用的确切翻译域的字符串。

choice_translation_parameters

类型arraycallablestringPropertyPath 默认值[]

选项值在显示之前被翻译,因此它可以包含 翻译占位符。此选项定义用于替换这些占位符的值。这可以是一个关联数组,其中键与选项键匹配,值是每个选项的属性,也可以是可调用对象或属性路径(就像 choice_label 一样)。

给定此翻译消息

1
2
3
# translations/messages.en.yaml
form.order.yes: 'I confirm my order to the company %company%'
form.order.no: 'I cancel my order'

您可以按如下方式指定占位符值

1
2
3
4
5
6
7
8
9
10
11
12
13
$builder->add('id', null, [
    'choices' => [
        'form.order.yes' => true,
        'form.order.no' => false,
    ],
    'choice_translation_parameters' => function ($choice, string $key, mixed $value): array {
        if (false === $choice) {
            return [];
        }

        return ['%company%' => 'ACME Inc.'];
    },
]);

如果是数组,则必须使用 choices 数组的键作为键

1
2
3
4
5
6
7
8
9
10
$builder->add('id', null, [
    'choices' => [
        'form.order.yes' => true,
        'form.order.no' => false,
    ],
    'choice_translation_parameters' => [
        'form.order.yes' => ['%company%' => 'ACME Inc.'],
        'form.order.no' => [],
    ],
]);

子字段的翻译参数与其父字段的相同选项合并,因此子字段可以重用和/或覆盖任何父占位符。

choice_value

类型callablestringPropertyPath 默认值null

为每个选项返回字符串“value”,该字符串在所有选项中必须是唯一的。这在 HTML 中的 value 属性中使用,并在 POST/PUT 请求中提交。您通常不需要担心这一点,但在处理 API 请求时可能会很方便(因为您可以配置将在 API 请求中发送的值)。

这可以是可调用对象或属性路径。默认情况下,如果选项可以转换为字符串,则使用选项。否则,将使用递增的整数(从 0 开始)。

如果您传递可调用对象,它将接收一个参数:选项本身。当使用 EntityType Field 时,参数将是每个选项的实体对象,或者如果使用占位符,则为 null,您需要处理这种情况

1
2
3
'choice_value' => function (?MyOptionEntity $entity): string {
    return $entity ? $entity->getId() : '';
},

提示

定义自定义类型时,应使用 ChoiceList 类助手

1
2
3
4
5
6
use Symfony\Component\Form\ChoiceList\ChoiceList;

// ...
$builder->add('choices', ChoiceType::class, [
    'choice_value' => ChoiceList::value($this, 'uuid'),
]);

请参阅 “choice_loader”选项文档

duplicate_preferred_choices

类型boolean 默认值true

当使用 preferred_choices 选项时,默认情况下,这些首选选项会显示两次:在列表的顶部和下面的完整列表中。将此选项设置为 false,仅在列表顶部显示首选选项

1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('language', ChoiceType::class, [
    'choices' => [
        'English' => 'en',
        'Spanish' => 'es',
        'Bork' => 'muppets',
        'Pirate' => 'arr',
    ],
    'preferred_choices' => ['muppets', 'arr'],
    'duplicate_preferred_choices' => false,
]);

expanded

类型boolean 默认值false

如果设置为 true,将渲染单选按钮或复选框(取决于 multiple 值)。如果为 false,则将渲染 select 元素。

group_by

类型stringcallablePropertyPath 默认值null

您可以通过将多维数组传递给 choices 来将 <select><option> 元素分组到 <optgroup> 中。请参阅关于此的 分组选项 部分。

group_by 选项是分组选项的另一种方法,它可以为您提供更大的灵活性。

以下面的示例为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('publishAt', ChoiceType::class, [
    'choices' => [
        'now' => new \DateTime('now'),
        'tomorrow' => new \DateTime('+1 day'),
        '1 week' => new \DateTime('+1 week'),
        '1 month' => new \DateTime('+1 month'),
    ],
    'group_by' => function($choice, $key, $value) {
        if ($choice <= new \DateTime('+3 days')) {
            return 'Soon';
        }

        return 'Later';
    },
]);

这会将 3 天内的日期分组到“Soon”中,并将其他所有日期分组到“Later” <optgroup>

A choice list with "now" and "tomorrow" grouped under "Soon", and "1 week" and "1 month" grouped under "Later".

如果您返回 null,则该选项将不会分组。您还可以传递一个字符串“属性路径”,该路径将被调用以获取组。有关使用属性路径的详细信息,请参阅 choice_label

提示

定义自定义类型时,应使用 ChoiceList 类助手

1
2
3
4
5
6
use Symfony\Component\Form\ChoiceList\ChoiceList;

// ...
$builder->add('choices', ChoiceType::class, [
    'group_by' => ChoiceList::groupBy($this, 'category'),
]);

请参阅 “choice_loader”选项文档

multiple

类型boolean 默认值false

如果为 true,用户将能够选择多个选项(而不是仅选择一个选项)。根据 expanded 选项的值,如果为 true,这将渲染 select 标签或复选框;如果为 false,则渲染 select 标签或单选按钮。返回的值将是一个数组。

placeholder

类型stringTranslatableMessageboolean

此选项确定是否在 select 小部件的顶部显示特殊的“空”选项(例如“选择一个选项”)。此选项仅在 multiple 选项设置为 false 时适用。

  • 添加一个空值,文本为“选择一个选项”

    1
    2
    3
    4
    5
    6
    7
    8
    9
    use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
    // ...
    
    $builder->add('states', ChoiceType::class, [
        'placeholder' => 'Choose an option',
    
        // or if you want to translate the text
        'placeholder' => new TranslatableMessage('form.placeholder.select_option', [], 'form'),
    ]);
  • 保证不显示“空”值选项

    1
    2
    3
    4
    5
    6
    use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
    // ...
    
    $builder->add('states', ChoiceType::class, [
        'placeholder' => false,
    ]);

如果您不设置 placeholder 选项,那么当且仅当 required 选项为 false 时,才会自动添加一个空白(无文本)选项

1
2
3
4
5
6
7
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

// a blank (with no text) option will be added
$builder->add('states', ChoiceType::class, [
    'required' => false,
]);

placeholder_attr

类型array 默认值[]

使用此选项为占位符选项添加额外的 HTML 属性

1
2
3
4
5
6
7
8
9
10
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('fruits', ChoiceType::class, [
    // ...
    'placeholder' => '...',
    'placeholder_attr' => [
        ['title' => 'Choose an option'],
    ],
]);

preferred_choices

类型arraycallablestringPropertyPath 默认值[]

此选项允许您在列表顶部显示某些选项,并在它们与完整选项列表之间添加视觉分隔符。如果您有一个语言表单,您可以将最流行的语言列在顶部,例如 Bork 和 Pirate

1
2
3
4
5
6
7
8
9
10
11
12
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('language', ChoiceType::class, [
    'choices' => [
        'English' => 'en',
        'Spanish' => 'es',
        'Bork' => 'muppets',
        'Pirate' => 'arr',
    ],
    'preferred_choices' => ['muppets', 'arr'],
]);

此选项也可以是一个回调函数,以便为您提供更大的灵活性。如果您的值是对象,这可能特别有用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...

$builder->add('publishAt', ChoiceType::class, [
    'choices' => [
        'now' => new \DateTime('now'),
        'tomorrow' => new \DateTime('+1 day'),
        '1 week' => new \DateTime('+1 week'),
        '1 month' => new \DateTime('+1 month'),
    ],
    'preferred_choices' => function ($choice, $key, $value): bool {
        // prefer options within 3 days
        return $choice <= new \DateTime('+3 days');
    },
]);

这将“首选”仅“now”和“tomorrow”选项

A choice list with "now" and "tomorrow" on top, separated by a line from "1 week" and "1 month".

最后,如果您的值是对象,您还可以指定对象上的属性路径字符串,该字符串将返回 true 或 false。

首选选项仅在渲染 select 元素(即 expanded 为 false)时才有意义。首选选项和普通选项在视觉上由一组虚线分隔(即 -------------------)。这可以在渲染字段时进行自定义

1
{{ form_widget(form.publishAt, { 'separator': '=====' }) }}

提示

定义自定义类型时,应使用 ChoiceList 类助手

1
2
3
4
5
6
use Symfony\Component\Form\ChoiceList\ChoiceList;

// ...
$builder->add('choices', ChoiceType::class, [
    'preferred_choices' => ChoiceList::preferred($this, 'taggedAsFavorite'),
]);

请参阅 “choice_loader”选项文档

separator

类型: string 默认值: -------------------

此选项允许您自定义在首选选项之后显示的视觉分隔符。您可以使用 HTML 元素,如 <hr> 来显示更现代的分隔符,但您还需要将 separator_html 选项设置为 true

7.1

separator 选项在 Symfony 7.1 中引入。

separator_html

类型boolean 默认值false

如果此选项为 true,则 separator 选项将显示为 HTML 而不是文本。当使用 HTML 元素(例如 <hr>)作为更现代的视觉分隔符时,这很有用。

7.1

separator_html 选项在 Symfony 7.1 中引入。

覆盖的选项

compound

类型: boolean 默认值: 与 expanded 选项相同的值

此选项指定表单是否为复合表单。默认情况下,该值会被 expanded 选项的值覆盖。

empty_data

类型: mixed

此选项的实际默认值取决于其他字段选项

  • 如果 multiplefalseexpandedfalse,则为 '' (空字符串);
  • 否则为 [] (空数组)。

此选项确定当提交的值为空(或缺失)时,字段将返回什么值。如果视图中渲染表单时未提供初始值,则它不会设置初始值。

这意味着它可以帮助您处理带有空白字段的表单提交。例如,如果您希望在未选择任何值时,将 name 字段显式设置为 John Doe,您可以这样做

1
2
3
4
$builder->add('name', null, [
    'required'   => false,
    'empty_data' => 'John Doe',
]);

这仍然会渲染一个空文本框,但在提交后,将设置 John Doe 值。使用 dataplaceholder 选项在渲染的表单中显示此初始值。

注意

如果表单是复合表单,您可以将 empty_data 设置为数组、对象或闭包。可以为您的整个表单类设置此选项,有关这些选项的更多详细信息,请参阅 如何为表单类配置空数据 文章。

警告

表单数据转换器 仍然会应用于 empty_data 值。这意味着空字符串将被强制转换为 null。如果您明确想要返回空字符串,请使用自定义数据转换器。

error_bubbling

类型boolean 默认值false

设置此字段上的错误必须附加到该字段,而不是父字段(在大多数情况下是表单)。

trim

类型boolean 默认值false

默认情况下禁用修剪,因为所选值或多个值必须与给定的选择值完全匹配(并且它们可能包含空格)。

invalid_message

类型: string 默认值: This value is not valid

如果输入到此字段的数据没有意义(即,验证失败),则会使用此验证错误消息。

例如,如果用户在 TimeType 字段中输入无法转换为实际时间的无意义字符串,或者如果用户在数字字段中输入字符串(例如 apple),则可能会发生这种情况。

正常的(业务逻辑)验证(例如设置字段的最小长度)应使用带有验证规则的验证消息来设置(参考)。

继承的选项

这些选项继承自 FormType

attr

类型array 默认值[]

如果您想向 HTML 字段表示形式添加额外的属性,可以使用 attr 选项。它是一个关联数组,其中 HTML 属性作为键。当您需要为某些小部件设置自定义类时,这可能很有用

1
2
3
$builder->add('body', TextareaType::class, [
    'attr' => ['class' => 'tinymce'],
]);

另请参阅

如果您想将这些属性添加到 表单类型行 元素,请使用 row_attr 选项。

by_reference

类型boolean 默认值true

在大多数情况下,如果您有一个 author 字段,那么您希望在底层对象上调用 setAuthor()。但是,在某些情况下,可能不会调用 setAuthor()。将 by_reference 设置为 false 可确保在所有情况下都调用 setter。

为了进一步解释这一点,这是一个简单的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
// ...

$builder = $this->createFormBuilder($article);
$builder
    ->add('title', TextType::class)
    ->add(
        $builder->create('author', FormType::class, ['by_reference' => ?])
            ->add('name', TextType::class)
            ->add('email', EmailType::class)
    )

如果 by_reference 为 true,则当您在表单上调用 submit() (或 handleRequest()) 时,幕后会发生以下情况

1
2
3
$article->setTitle('...');
$article->getAuthor()->setName('...');
$article->getAuthor()->setEmail('...');

请注意,setAuthor() 未被调用。作者是通过引用修改的。

如果您将 by_reference 设置为 false,则提交看起来像这样

1
2
3
4
5
$article->setTitle('...');
$author = clone $article->getAuthor();
$author->setName('...');
$author->setEmail('...');
$article->setAuthor($author);

因此,by_reference=false 真正做的就是克隆对象,这强制框架在父对象上调用 setter。

同样,如果您正在使用 CollectionType 字段,其中您的底层集合数据是一个对象(例如使用 Doctrine 的 ArrayCollection),那么如果您需要调用 adder 和 remover(例如 addAuthor()removeAuthor()),则必须将 by_reference 设置为 false

data

类型: mixed 默认值: 默认为底层结构的字段。

当您创建表单时,每个字段最初显示表单域数据的相应属性值(例如,如果您将对象绑定到表单)。如果您想覆盖表单或单个字段的此初始值,可以在 data 选项中设置它

1
2
3
4
5
6
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
// ...

$builder->add('token', HiddenType::class, [
    'data' => 'abcdef',
]);

警告

渲染时,data 选项始终覆盖从域数据(对象)获取的值。这意味着当表单编辑已持久化的对象时,对象值也会被覆盖,导致它在表单提交时丢失其持久化的值。

disabled

类型boolean 默认值false

如果您不希望用户修改字段的值,可以将 disabled 选项设置为 true。任何提交的值都将被忽略。

error_mapping

类型array 默认值[]

此选项允许您修改验证错误的目标。

假设您有一个名为 matchingCityAndZipCode() 的自定义方法,用于验证城市和邮政编码是否匹配。不幸的是,您的表单中没有 matchingCityAndZipCode 字段,因此 Symfony 所能做的就是在表单顶部显示错误。

通过自定义错误映射,您可以做得更好:将错误映射到城市字段,以便它显示在其上方

1
2
3
4
5
6
7
8
public function configureOptions(OptionsResolver $resolver): void
{
    $resolver->setDefaults([
        'error_mapping' => [
            'matchingCityAndZipCode' => 'city',
        ],
    ]);
}

以下是映射的左侧和右侧的规则

  • 左侧包含属性路径;
  • 如果违规是在类的属性或方法上生成的,则其路径为 propertyName
  • 如果违规是在 arrayArrayAccess 对象的条目上生成的,则属性路径为 [indexName]
  • 您可以通过连接嵌套属性路径来构造它们,用点分隔属性。例如:addresses[work].matchingCityAndZipCode
  • 右侧包含表单中字段的名称。

默认情况下,任何未映射属性的错误都会冒泡到父表单。您可以使用左侧的点 (.) 将所有未映射属性的错误映射到特定字段。例如,要将所有这些错误映射到 city 字段,请使用

1
2
3
4
5
$resolver->setDefaults([
    'error_mapping' => [
        '.' => 'city',
    ],
]);

help

类型: stringTranslatableInterface 默认值: null

允许您为表单字段定义帮助消息,默认情况下该消息显示在字段下方

1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\Translation\TranslatableMessage;

$builder
    ->add('zipCode', null, [
        'help' => 'The ZIP/Postal code for your credit card\'s billing address.',
    ])

    // ...

    ->add('status', null, [
        'help' => new TranslatableMessage('order.status', ['%order_id%' => $order->getId()], 'store'),
    ])
;

help_attr

类型array 默认值[]

设置用于显示表单字段帮助消息的元素的 HTML 属性。其值是关联数组,其中 HTML 属性名称作为键。这些属性也可以在模板中设置

1
2
3
{{ form_help(form.name, 'Your name', {
    'help_attr': {'class': 'CUSTOM_LABEL_CLASS'}
}) }}

help_html

类型boolean 默认值false

默认情况下,help 选项的内容在模板中渲染之前会被转义。将此选项设置为 true 以不转义它们,这在帮助包含 HTML 元素时很有用。

inherit_data

类型boolean 默认值false

此选项确定表单是否将从其父表单继承数据。如果您有一组在多个表单中重复的字段,这将很有用。请参阅 如何使用 “inherit_data” 减少代码重复

警告

当字段设置了 inherit_data 选项时,它将按原样使用父表单的数据。这意味着 数据转换器 将不会应用于该字段。

label

类型: stringTranslatableMessage 默认值: 标签是根据字段名称“猜测”的

设置渲染字段时将使用的标签。设置为 false 将抑制标签

1
2
3
4
5
6
7
8
use Symfony\Component\Translation\TranslatableMessage;

$builder
    ->add('zipCode', null, [
        'label' => 'The ZIP/Postal code',
        // optionally, you can use TranslatableMessage objects as the label content
        'label' => new TranslatableMessage('address.zipCode', ['%country%' => $country], 'address'),
    ])

标签也可以在模板中设置

1
{{ form_label(form.name, 'Your name') }}

label_attr

类型array 默认值[]

设置 <label> 元素的 HTML 属性,该元素将在渲染字段标签时使用。它是一个关联数组,其中 HTML 属性作为键。这些属性也可以直接在模板中设置

1
2
3
{{ form_label(form.name, 'Your name', {
    'label_attr': {'class': 'CUSTOM_LABEL_CLASS'}
}) }}

label_html

类型boolean 默认值false

默认情况下,label 选项的内容在模板中渲染之前会被转义。将此选项设置为 true 以不转义它们,这在标签包含 HTML 元素时很有用。

label_format

类型: string 默认值: null

配置用作字段标签的字符串,以防未设置 label 选项。当使用 关键字翻译消息 时,这很有用。

如果您使用关键字翻译消息作为标签,您通常最终会为同一标签设置多个关键字消息(例如 profile_address_street, invoice_address_street)。这是因为标签是为字段的每个“路径”构建的。为了避免重复的关键字消息,您可以将标签格式配置为静态值,例如

1
2
3
4
5
6
7
8
// ...
$profileFormBuilder->add('address', AddressType::class, [
    'label_format' => 'form.address.%name%',
]);

$invoiceFormBuilder->add('invoice', AddressType::class, [
    'label_format' => 'form.address.%name%',
]);

此选项由子类型继承。使用上面的代码,两个表单的 street 字段的标签都将使用 form.address.street 关键字消息。

标签格式中提供两个变量

%id%
字段的唯一标识符,由字段的完整路径和字段名称组成(例如 profile_address_street);
%name%
字段名称(例如 street)。

默认值 (null) 会生成字段名称的 “人性化”版本

注意

label_format 选项在表单主题中评估。如果您 自定义了表单主题,请确保更新您的模板。

mapped

类型boolean 默认值true

如果您希望在读取或写入对象时忽略该字段,可以将 mapped 选项设置为 false

required

类型boolean 默认值true

如果为 true,则将渲染 HTML5 required 属性。相应的 label 也将使用 required 类进行渲染。

这是表面的,并且独立于验证。在最好的情况下,如果您让 Symfony 猜测您的字段类型,那么此选项的值将从您的验证信息中猜测出来。

注意

required 选项还会影响如何处理每个字段的空数据。有关更多详细信息,请参阅 empty_data 选项。

row_attr

类型array 默认值[]

添加到用于渲染 表单类型行 的元素的 HTML 属性的关联数组

1
2
3
$builder->add('body', TextareaType::class, [
    'row_attr' => ['class' => 'text-editor', 'id' => '...'],
]);

另请参阅

如果您想将这些属性添加到 表单类型小部件 元素,请使用 attr 选项。

translation_domain

类型: string 默认值: messages

如果 choice_translation_domain 设置为 truenull,则此选项配置将用于为此字段渲染的任何标签或选项的确切翻译域。

label_translation_parameters

类型array 默认值[]

label 选项的内容在显示之前会被翻译,因此它可以包含 翻译占位符。此选项定义用于替换这些占位符的值。

给定此翻译消息

1
2
# translations/messages.en.yaml
form.order.id: 'Identifier of the order to %company%'

您可以按如下方式指定占位符值

1
2
3
4
5
6
$builder->add('id', null, [
    'label' => 'form.order.id',
    'label_translation_parameters' => [
        '%company%' => 'ACME Inc.',
    ],
]);

子字段的 label_translation_parameters 选项与其父字段的相同选项合并,因此子字段可以重用和/或覆盖任何父占位符。

attr_translation_parameters

类型array 默认值[]

attr 选项中定义的 titleplaceholder 值的内容在显示之前会被翻译,因此它可以包含 翻译占位符。此选项定义用于替换这些占位符的值。

给定此翻译消息

1
2
3
# translations/messages.en.yaml
form.order.id.placeholder: 'Enter unique identifier of the order to %company%'
form.order.id.title: 'This will be the reference in communications with %company%'

您可以按如下方式指定占位符值

1
2
3
4
5
6
7
8
9
$builder->add('id', null, [
    'attr' => [
        'placeholder' => 'form.order.id.placeholder',
        'title' => 'form.order.id.title',
    ],
    'attr_translation_parameters' => [
        '%company%' => 'ACME Inc.',
    ],
]);

子字段的 attr_translation_parameters 选项与其父字段的相同选项合并,因此子字段可以重用和/或覆盖任何父占位符。

help_translation_parameters

类型array 默认值[]

help 选项的内容在显示之前会被翻译,因此它可以包含 翻译占位符。此选项定义用于替换这些占位符的值。

给定此翻译消息

1
2
# translations/messages.en.yaml
form.order.id.help: 'This will be the reference in communications with %company%'

您可以按如下方式指定占位符值

1
2
3
4
5
6
$builder->add('id', null, [
    'help' => 'form.order.id.help',
    'help_translation_parameters' => [
        '%company%' => 'ACME Inc.',
    ],
]);

子字段的 help_translation_parameters 选项与其父字段的相同选项合并,因此子字段可以重用和/或覆盖任何父占位符。

字段变量

变量 类型 用法
multiple boolean multiple 选项的值。
expanded boolean expanded 选项的值。
preferred_choices array 一个嵌套数组,包含应优先呈现给用户的选项的 ChoiceView 对象。
choices array 一个嵌套数组,包含其余选项的 ChoiceView 对象。
separator string 在选项组之间使用的分隔符。
placeholder mixed 如果空值尚未在列表中,则为空值,否则为 null
placeholder_attr array placeholder_attr 选项的值。
choice_translation_domain mixed boolean, nullstring,用于确定是否应翻译该值。
is_selected callable 一个可调用对象,它接受 ChoiceView 和选定的值,并返回该选项是否在选定的值中。
placeholder_in_choices boolean 空值是否在选项列表中。

提示

在 Twig 模板中,与其使用 is_selected(),不如使用 selectedchoice 测试,速度要快得多。

访问表单选项数据

每个选项条目的 form.vars 变量都保存着数据,例如选项是否被选中。如果您需要获取选项数据和值的完整列表,请使用选项条目的父表单(即 ChoiceType 本身)中的 choices 变量,即 form.parent.vars.choices

1
2
3
4
5
6
7
8
{# `true` or `false`, whether the current choice is selected as radio or checkbox #}
{{ form.vars.data }}

{# the current choice value (i.e a category name when `'choice_value' => 'name'` #}
{{ form.vars.value }}

{# a map of `ChoiceView` or `ChoiceGroupView` instances indexed by choice values or group names #}
{{ form.parent.vars.choices }}

按照上面相同的高级示例(其中选项值是实体),Category 对象位于 form.parent.vars.choices[key].data

1
2
3
4
5
6
7
8
9
10
11
{% block _form_categories_entry_widget %}
    {% set entity = form.parent.vars.choices[form.vars.value].data %}

    <tr>
        <td>{{ form_widget(form) }}</td>
        <td>{{ form.vars.label }}</td>
        <td>
            {{ entity.name }} | {{ entity.group }}
        </td>
    </tr>
{% endblock %}
这项工作,包括代码示例,根据 Creative Commons BY-SA 3.0 许可获得许可。
TOC
    版本