ChoiceType 字段(选择下拉列表、单选按钮和复选框)
一个多用途字段,用于允许用户“选择”一个或多个选项。它可以渲染为 select
标签、单选按钮或复选框。
要使用此字段,您必须指定 或者 choices
或 choice_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
下拉列表

如果用户选择 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 字段之一,具体取决于 expanded
和 multiple
选项
元素类型 | 展开 | 多选 |
---|---|---|
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',
],
],
]);

为了更高级,请使用 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
类型:array
、callable
、string
或 PropertyPath 默认值:[]
使用此选项可为每个选项添加额外的 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
类型:callable
、string
或 PropertyPath 默认值: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
类型:string
、callable
、false
或 PropertyPath 默认值: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
(附加的 $value
与 choice_value 相关)。这将为您提供

如果您的选项值是对象,则 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
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
类型:callable
、string
或 PropertyPath 默认值: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
类型:string
、boolean
或 null
默认值:true
此选项确定是否应翻译选项值以及在哪个翻译域中翻译。
choice_translation_domain
选项的值可以是 true
(重用当前翻译域)、 false
(禁用翻译)、 null
(使用父翻译域或默认域)或表示要使用的确切翻译域的字符串。
choice_translation_parameters
类型:array
、callable
、string
或 PropertyPath 默认值:[]
选项值在显示之前被翻译,因此它可以包含 翻译占位符。此选项定义用于替换这些占位符的值。这可以是一个关联数组,其中键与选项键匹配,值是每个选项的属性,也可以是可调用对象或属性路径(就像 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
类型:callable
、string
或 PropertyPath 默认值: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,
]);
group_by
类型:string
、callable
或 PropertyPath 默认值: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>
中

如果您返回 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
类型:string
或 TranslatableMessage
或 boolean
此选项确定是否在 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
类型:array
、callable
、string
或 PropertyPath 默认值:[]
此选项允许您在列表顶部显示某些选项,并在它们与完整选项列表之间添加视觉分隔符。如果您有一个语言表单,您可以将最流行的语言列在顶部,例如 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”选项

最后,如果您的值是对象,您还可以指定对象上的属性路径字符串,该字符串将返回 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 中引入。
覆盖的选项
empty_data
类型: mixed
此选项的实际默认值取决于其他字段选项
- 如果
multiple
为false
且expanded
为false
,则为''
(空字符串); - 否则为
[]
(空数组)。
此选项确定当提交的值为空(或缺失)时,字段将返回什么值。如果视图中渲染表单时未提供初始值,则它不会设置初始值。
这意味着它可以帮助您处理带有空白字段的表单提交。例如,如果您希望在未选择任何值时,将 name
字段显式设置为 John Doe
,您可以这样做
1 2 3 4
$builder->add('name', null, [
'required' => false,
'empty_data' => 'John Doe',
]);
这仍然会渲染一个空文本框,但在提交后,将设置 John Doe
值。使用 data
或 placeholder
选项在渲染的表单中显示此初始值。
注意
如果表单是复合表单,您可以将 empty_data
设置为数组、对象或闭包。可以为您的整个表单类设置此选项,有关这些选项的更多详细信息,请参阅 如何为表单类配置空数据 文章。
警告
表单数据转换器 仍然会应用于 empty_data
值。这意味着空字符串将被强制转换为 null
。如果您明确想要返回空字符串,请使用自定义数据转换器。
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
选项始终覆盖从域数据(对象)获取的值。这意味着当表单编辑已持久化的对象时,对象值也会被覆盖,导致它在表单提交时丢失其持久化的值。
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
; - 如果违规是在
array
或ArrayAccess
对象的条目上生成的,则属性路径为[indexName]
; - 您可以通过连接嵌套属性路径来构造它们,用点分隔属性。例如:
addresses[work].matchingCityAndZipCode
; - 右侧包含表单中字段的名称。
默认情况下,任何未映射属性的错误都会冒泡到父表单。您可以使用左侧的点 (.
) 将所有未映射属性的错误映射到特定字段。例如,要将所有这些错误映射到 city
字段,请使用
1 2 3 4 5
$resolver->setDefaults([
'error_mapping' => [
'.' => 'city',
],
]);
help
类型: string
或 TranslatableInterface
默认值: 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'}
}) }}
inherit_data
类型:boolean
默认值:false
此选项确定表单是否将从其父表单继承数据。如果您有一组在多个表单中重复的字段,这将很有用。请参阅 如何使用 “inherit_data” 减少代码重复。
警告
当字段设置了 inherit_data
选项时,它将按原样使用父表单的数据。这意味着 数据转换器 将不会应用于该字段。
label
类型: string
或 TranslatableMessage
默认值: 标签是根据字段名称“猜测”的
设置渲染字段时将使用的标签。设置为 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
选项在表单主题中评估。如果您 自定义了表单主题,请确保更新您的模板。
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 设置为 true
或 null
,则此选项配置将用于为此字段渲染的任何标签或选项的确切翻译域。
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 选项中定义的 title
和 placeholder
值的内容在显示之前会被翻译,因此它可以包含 翻译占位符。此选项定义用于替换这些占位符的值。
给定此翻译消息
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 , null 或 string ,用于确定是否应翻译该值。 |
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 %}