字段
字段允许在每个 CRUD 页面上显示 Doctrine 实体的内容。 EasyAdmin 提供了内置字段来显示所有常见数据类型,但您也可以创建自己的字段。
配置要显示的字段
如果您的 CRUD 控制器 继承自 EasyAdmin 提供的 AbstractCrudController
,则字段会自动配置。在 index
页面中,您将看到一些字段,在其余页面中,您将看到显示 Doctrine 实体所有属性所需的尽可能多的字段。
在您的 CRUD 控制器中实现 configureFields()
方法以自定义要显示的字段列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
namespace App\Controller\Admin;
use App\Entity\Product;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class ProductCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Product::class;
}
public function configureFields(string $pageName): iterable
{
// ...
}
// ...
}
有几种定义要显示的字段列表的方法。
选项 1. 返回带有要显示的属性名称的字符串。 EasyAdmin 会自动为它们创建字段并应用默认配置选项
1 2 3 4 5 6 7 8 9 10
public function configureFields(string $pageName): iterable
{
return [
'title',
'description',
'price',
'stock',
'publishedAt',
];
}
选项 2. 返回为 Doctrine 实体属性创建的 Field
对象。 EasyAdmin 将这些通用 Field
对象转换为用于显示每种属性类型的特定对象
1 2 3 4 5 6 7 8 9 10 11 12
use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
public function configureFields(string $pageName): iterable
{
return [
Field::new('title'),
Field::new('description'),
Field::new('price'),
Field::new('stock'),
Field::new('publishedAt'),
];
}
选项 3. 返回适当的字段对象以显示每个属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\MoneyField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
public function configureFields(string $pageName): iterable
{
return [
TextField::new('title'),
TextEditorField::new('description'),
MoneyField::new('price')->setCurrency('EUR'),
IntegerField::new('stock'),
DateTimeField::new('publishedAt'),
];
}
字段构造函数的唯一强制参数是由此字段管理的 Doctrine 实体属性的名称。 EasyAdmin 使用 PropertyAccess 组件 来获取属性的值,因此实体可以将它们的访问定义为公共属性(例如 public $firstName
)或公共方法(例如 public function getFirstName()
, public function firstName()
)。
注意
EasyAdmin 使用 Symfony 表单来创建和编辑 Doctrine 实体。这就是为什么所有实体属性都必须可为空:它们的 setter 需要接受 null
值,并且它们的 getter 必须允许返回 null
。在数据库中,关联的字段不必可为空。
未映射字段
字段通常引用相关 Doctrine 实体的属性。但是,它们也可以引用实体的方法,这些方法不与任何属性关联。例如,如果您的 Customer
实体定义了 firstName
和 lastName
属性,您可能想要显示一个合并了这两个值的“全名”字段。
为此,请将以下方法添加到实体
1 2 3 4 5 6 7 8 9 10 11 12
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Customer
{
// ...
public function getFullName()
{
return $this->getFirstName().' '.$this->getLastName();
}
}
现在,添加一个引用此 getFullName()
方法的 fullName
字段。字段名称和方法之间的转换必须符合 PropertyAccess 组件 的规则(例如 foo_bar
-> getFooBar()
或 fooBar()
)
1 2 3 4 5 6 7
public function configureFields(string $pageName): iterable
{
return [
TextField::new('fullName'),
// ...
];
}
请注意,未映射字段是不可排序的,因为它们不存在作为数据库表列,因此无法包含在 Doctrine 查询中。在某些情况下,您可以通过使用 SQL 计算未映射字段的内容来自行克服此限制。为此,请覆盖您的 CRUD 控制器 中使用的 createIndexQueryBuilder()
方法
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
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class UserCrudController extends AbstractCrudController
{
// ...
public function configureFields(string $pageName): iterable
{
return [
TextField::new('fullName'),
// ...
];
}
public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
$queryBuilder = parent::createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters);
// if user defined sort is not set
if (0 === count($searchDto->getSort())) {
$queryBuilder
->addSelect('CONCAT(entity.first_name, \' \', entity.last_name) AS HIDDEN full_name')
->addOrderBy('full_name', 'DESC');
}
return $queryBuilder;
}
}
每页显示不同的字段
有几种方法可以根据当前页面有条件地显示字段
1 2 3 4 5 6 7 8 9 10 11
public function configureFields(string $pageName): iterable
{
return [
IdField::new('id')->hideOnForm(),
TextField::new('firstName'),
TextField::new('lastName'),
TextField::new('phone'),
EmailField::new('email')->hideOnIndex(),
DateTimeField::new('createdAt')->onlyOnDetail(),
];
}
以下是所有可用的方法
hideOnIndex()
hideOnDetail()
hideOnForm()
(在edit
和new
页面中都隐藏字段)hideWhenCreating()
hideWhenUpdating()
onlyOnIndex()
onlyOnDetail()
onlyOnForms()
(在除edit
和new
之外的所有页面中隐藏字段)onlyWhenCreating()
onlyWhenUpdating()
如果每页上要显示的字段完全不同,请使用给定的 $pageName
参数来区分它们
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
public function configureFields(string $pageName): iterable
{
$id = IdField::new('id');
$firstName = TextField::new('firstName');
$lastName = TextField::new('lastName');
$phone = TextField::new('phone');
$email = EmailField::new('email');
$createdAt = DateTimeField::new('createdAt');
if (Crud::PAGE_INDEX === $pageName) {
return [$id, $firstName, $lastName, $phone];
} elseif(Crud::PAGE_DETAIL === $pageName) {
return ['...'];
} else {
return ['...'];
}
}
如果您需要更大的控制,请考虑使用以下使用 PHP 生成器 定义字段的方式
1 2 3 4 5 6 7 8 9 10 11 12 13
public function configureFields(string $pageName): iterable
{
yield IdField::new('id')->hideOnForm();
if ('... some expression ...') {
yield TextField::new('firstName');
yield TextField::new('lastName');
}
yield TextField::new('phone');
yield EmailField::new('email')->hideOnIndex();
yield DateTimeField::new('createdAt')->onlyOnDetail();
}
字段布局
默认情况下,EasyAdmin 表单每行显示一个字段。在每一行内,字段根据其类型显示不同的宽度(例如,整数字段很窄,而代码编辑器字段非常宽)。
在本节中,您将学习如何自定义每个字段的宽度,以及借助标签页、列、字段集和行等元素自定义整个表单布局。
表单标签页
此元素旨在使非常长/复杂的表单更易于使用。它允许将字段分组到单独的标签页中,这些标签页一次可见一个。它看起来像这样

使用特殊 FormField
对象的 addTab()
方法将标签页添加到您的表单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
public function configureFields(string $pageName): iterable
{
return [
// Creates a tab: all fields following it will belong to that tab
// (until the end of the form or until you create another tab)
FormField::addTab('First Tab'),
TextField::new('firstName'),
TextField::new('lastName'),
// Creates a second tab and customizes some of its properties, such
// as its icon, CSS class and help message
FormField::addTab('Contact Information Tab')
->setIcon('phone')->addCssClass('optional')
->setHelp('Phone number is preferred'),
TextField::new('phone'),
// ...
];
}
addTab()
方法的参数是
$label
:(类型:TranslatableInterface|string|false|null
)此标签页在标签页的可点击列表中显示的文本;如果您将其设置为false
、null
或空字符串,则不会显示任何文本(确保为标签页显示图标,否则用户将无法点击它);您还可以传递string
和TranslatableInterface
变量。在这两种情况下,如果它们包含 HTML 标签,它们将被渲染而不是转义;$icon
:(类型:?string
)FontAwesome 图标的完整 CSS 类(例如far fa-folder-open
);如果您没有为标签页显示文本标签,请确保显示图标,否则用户将无法点击标签页。
注意
默认情况下,EasyAdmin 假定图标名称对应于 FontAwesome CSS 类。必要的 CSS 样式和 Web 字体也默认包含在内,因此您无需采取任何其他步骤即可使用 FontAwesome 图标。或者,您可以使用您自己的图标集而不是 FontAwesome。
在标签页内,您不仅可以包含表单字段,还可以包含以下部分中解释的所有其他表单布局字段:列、字段集和行。以下是使用所有这些元素的表单的外观

默认情况下,标签页使用特殊的 Symfony 表单类型渲染。此类型的名称是 ea_form_tab
+ 随机 ULID 值。这使得无法使用表单主题覆盖其模板。要自定义它,请使用 addTab()
方法的 propertySuffix
可选参数
1
FormField::addTab('Contact Information Tab', propertySuffix: 'contact');
按照此示例,您可以定义以下块来覆盖此标签页的设计
{% endblock _MyEntity_ea_form_tab_contact_row %}
- {% block _MyEntity_ea_form_tab_close_contact_row %}
- {# ... #} {{ block('ea_form_tab_close_row') }} {# ... #}
{% endblock _MyEntity_ea_form_tab_close_contact_row %}
4.20
propertySuffix
参数在 EasyAdmin 4.20.0 中引入。
表单列
4.8.0
表单列在 EasyAdmin 4.8.0 中引入。
在使用此选项之前,您必须熟悉 Bootstrap 网格系统,它将每一行划分为 12 个等宽列,以及 Bootstrap 断点,它们是 xs
(设备宽度 < 576px)、sm
(>= 576px)、md
(>= 768px)、lg
(>= 992px)、xl
(>= 1,200px)和 xxl
(>= 1,400px)。
表单列允许将复杂的表单分解为两列或更多列字段。除了增加信息密度外,列还允许根据字段的功能更好地分隔字段。以下是三列表单的外观

以下是一个简单的示例,它将表单分为两列(第一列跨越 12 个可用 Bootstrap 列中的 8 个,第二列跨越其他 4 个 Bootstrap 列)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
public function configureFields(string $pageName): iterable
{
return [
FormField::addColumn(8),
TextField::new('firstName'),
TextField::new('lastName'),
FormField::addColumn(4),
TextField::new('phone'),
TextField::new('email')->hideOnIndex(),
];
}
addColumn()
方法的参数是
$cols
:(类型:int|string
)列的宽度,定义为与 Bootstrap 网格系统 兼容的任何值(例如'col-6'
、'col-md-6 col-xl-4'
等)。整数值按如下方式转换:N -> 'col-N'(例如8
转换为col-8
);$label
:(类型:TranslatableInterface|string|false|null
)显示在列顶部的可选标题。如果您传递false
、null
或空字符串,则不显示标题。您还可以传递string
和TranslatableInterface
变量。在这两种情况下,如果它们包含 HTML 标签,它们将被渲染而不是转义;$icon
:(类型:?string
)FontAwesome 图标的完整 CSS 类(例如far fa-folder-open
),显示在列标签旁边;$help
:(类型:?string
)显示在列标签下方的可选内容;它主要用于描述列内容或提供进一步的说明或帮助内容。您可以包含 HTML 标签,它们将被渲染而不是转义。
注意
默认情况下,EasyAdmin 假定图标名称对应于 FontAwesome CSS 类。必要的 CSS 样式和 Web 字体也默认包含在内,因此您无需采取任何其他步骤即可使用 FontAwesome 图标。或者,您可以使用您自己的图标集而不是 FontAwesome。
借助 Bootstrap 响应式类,您可以拥有不同大小的列,甚至完全没有列,具体取决于浏览器窗口大小。在以下示例中,lg
以下的断点不显示列。此外,两列的总和不合计 12
;这允许创建比可用总空间短的列
1 2 3 4 5 6 7 8 9 10 11 12 13 14
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
public function configureFields(string $pageName): iterable
{
return [
FormField::addColumn('col-lg-8 col-xl-6'),
TextField::new('firstName'),
TextField::new('lastName'),
FormField::addColumn('col-lg-3 col-xl-2'),
TextField::new('phone'),
TextField::new('email')->hideOnIndex(),
];
}
您还可以在标签页内使用列,以进一步组织非常复杂的布局的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
public function configureFields(string $pageName): iterable
{
return [
FormField::addTab('User Data'),
FormField::addColumn('col-lg-8 col-xl-6'),
TextField::new('firstName'),
TextField::new('lastName'),
FormField::addColumn('col-lg-3 col-xl-2'),
TextField::new('phone'),
TextField::new('email')->hideOnIndex(),
FormField::addTab('Financial Information'),
// ...
];
}
注意
默认情况下,列内的所有字段都与其包含列一样宽。使用表单行(如下所述)自定义字段宽度和/或在同一行上显示多个字段。
默认情况下,列使用特殊的 Symfony 表单类型渲染。此类型的名称是 ea_form_column
+ 随机 ULID 值。这使得无法使用表单主题覆盖其模板。要自定义它,请使用 addColumn()
方法的 propertySuffix
可选参数
1
FormField::addColumn('col-lg-8 col-xl-6', propertySuffix: 'main');
按照此示例,您可以定义以下块来覆盖此列的设计
{% endblock _MyEntity_ea_form_column_main_row %}
- {% block _MyEntity_ea_form_column_close_main_row %}
- {# ... #} {{ block('ea_form_column_close_row') }} {# ... #}
{% endblock _MyEntity_ea_form_column_close_main_row %}
4.20
propertySuffix
参数在 EasyAdmin 4.20.0 中引入。
表单字段集
4.8.0
表单字段集在 EasyAdmin 4.8.0 中引入。在以前的版本中,此功能称为“表单面板”。
在显示大量字段的页面中,您可以使用字段集将它们分组。以下是它们的外观

使用特殊 FormField
对象的 addFieldset()
方法创建字段集
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 EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
public function configureFields(string $pageName): iterable
{
return [
// fieldsets usually display only a title
FormField::addFieldset('User Details'),
TextField::new('firstName'),
TextField::new('lastName'),
// fieldsets without titles only display a separation between fields
FormField::addFieldset(),
DateTimeField::new('createdAt')->onlyOnDetail(),
// fieldsets can also define their icon, CSS class and help message
FormField::addFieldset('Contact information')
->setIcon('phone')->addCssClass('optional')
->setHelp('Phone number is preferred'),
TextField::new('phone'),
TextField::new('email')->hideOnIndex(),
// fieldsets can be collapsible too (useful if your forms are long)
// this makes the fieldset collapsible but renders it expanded by default
FormField::addFieldset('Contact information')->collapsible(),
// this makes the fieldset collapsible and renders it collapsed by default
FormField::addFieldset('Contact information')->renderCollapsed(),
];
}
addFieldset()
方法的参数是
$label
:(类型:TranslatableInterface|string|false|null
)显示在字段集顶部的可选标题。如果您传递false
、null
或空字符串,则不显示标题。您还可以传递string
和TranslatableInterface
变量。在这两种情况下,如果它们包含 HTML 标签,它们将被渲染而不是转义;$icon
:(类型:?string
)FontAwesome 图标的完整 CSS 类(例如far fa-folder-open
),显示在字段集标签旁边。
注意
默认情况下,EasyAdmin 假定图标名称对应于 FontAwesome CSS 类。必要的 CSS 样式和 Web 字体也默认包含在内,因此您无需采取任何其他步骤即可使用 FontAwesome 图标。或者,您可以使用您自己的图标集而不是 FontAwesome。
当使用表单列时,其中的字段集显示略有不同的设计,以更好地对不同的字段进行分组。这就是为什么建议在您使用列时始终使用字段集。以下是它的外观

默认情况下,字段集使用特殊的 Symfony 表单类型渲染。此类型的名称是 ea_form_fieldset
+ 随机 ULID 值。这使得无法使用表单主题覆盖其模板。要自定义它,请使用 addFieldset()
方法的 propertySuffix
可选参数
1
FormField::addFieldset('Contact information', propertySuffix: 'contact');
按照此示例,您可以定义以下块来覆盖此字段集的设计
{% endblock _MyEntity_ea_form_fieldset_contact_row %}
- {% block _MyEntity_ea_form_fieldset_close_contact_row %}
- {# ... #} {{ block('ea_form_fieldset_close_row') }} {# ... #}
{% endblock _MyEntity_ea_form_fieldset_close_contact_row %}
4.20
propertySuffix
参数在 EasyAdmin 4.20.0 中引入。
表单行
在使用此选项之前,您必须熟悉 Bootstrap 网格系统,它将每一行划分为 12 个等宽列,以及 Bootstrap 断点,它们是 xs
(设备宽度 < 576px)、sm
(>= 576px)、md
(>= 768px)、lg
(>= 992px)、xl
(>= 1,200px)和 xxl
(>= 1,400px)。
表单行允许在同一行显示两个或多个字段。 它的外观如下所示

假设您想在同一行显示两个名为 startsAt
和 endsAt
的字段,每个字段跨越该行的 6 列。 这是您配置该布局的方式
1 2 3 4 5 6 7 8 9 10 11
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
public function configureFields(string $pageName): iterable
{
return [
// ...,
DateTimeField::new('startsAt')->setColumns(6),
DateTimeField::new('endsAt')->setColumns(6),
];
}
此示例在同一行上呈现这两个字段,但在 xs
和 sm
断点中除外,在这些断点中,每个字段都占据整行(因为设备宽度太小)。
如果您需要更好地控制取决于设备宽度的设计,则可以传递一个包含响应式 CSS 类的字符串,这些类定义了字段在不同断点处的宽度
1 2 3 4 5 6 7 8 9 10 11
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
public function configureFields(string $pageName): iterable
{
return [
// ...,
DateTimeField::new('startsAt')->setColumns('col-sm-6 col-lg-5 col-xxl-3'),
DateTimeField::new('endsAt')->setColumns('col-sm-6 col-lg-5 col-xxl-3'),
];
}
此示例添加了 col-sm-6
以覆盖默认的 EasyAdmin 行为,并在 sm
断点中也在同一行上显示这两个字段。 此外,它减少了较大断点(lg
和 xxl
)中的列数,以改善这些字段的呈现效果。
提示
您还可以使用与重新排序和偏移列相关的 CSS 类
1
yield DateTimeField::new('endsAt')->setColumns('col-sm-6 col-xxl-3 offset-lg-1 order-3');
由于 Bootstrap 网格的工作方式,当您手动配置字段列时,每行将包含尽可能多的字段。 如果一个字段占用 4 列,而下一个字段占用 3 列,则该行仍有 12 - 4 - 3 = 5
列来呈现其他字段。 如果下一个字段占用超过 5 列,它将在下一行呈现。
有时您需要更好地控制此自动布局。 例如,您可能希望在同一行上显示两个或多个字段,并确保该行上不显示其他字段,即使有足够的空间。 为此,请使用特殊 FormField
字段的 addRow()
方法来强制创建新行(下一个字段将强制在新行上呈现)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
public function configureFields(string $pageName): iterable
{
return [
// ...,
DateTimeField::new('startsAt')->setColumns('col-sm-6 col-lg-5 col-xxl-3'),
DateTimeField::new('endsAt')->setColumns('col-sm-6 col-lg-5 col-xxl-3'),
FormField::addRow(),
// you can pass the name of the breakpoint to add a row only on certain widths
// FormField::addRow('xl'),
// this field will always render on its own row, even if there's
// enough space for it in the previous row in `lg`, `xl` and `xxl` breakpoints
BooleanField::new('published')->setColumns(2),
];
}
默认情况下,行是使用特殊的 Symfony 表单类型呈现的。 此类型的名称是 ea_form_row
+ 随机 ULID 值。 这使得无法使用表单主题覆盖其模板。 要自定义它,请使用 addRow()
方法的 propertySuffix
可选参数
1
FormField::addRow('xl', propertySuffix: 'main');
按照此示例,您可以定义以下块来覆盖此行的设计
{% endblock _MyEntity_ea_form_row_main_row %}
- {% block _MyEntity_ea_form_row_close_main_row %}
- {# ... #} {{ block('ea_form_row_close_row') }} {# ... #}
{% endblock _MyEntity_ea_form_row_close_main_row %}
4.20
propertySuffix
参数在 EasyAdmin 4.20.0 中引入。
字段类型
这些是 EasyAdmin 提供的所有内置字段
- ArrayField
- AssociationField
- AvatarField
- BooleanField
- ChoiceField
- CodeEditorField
- CollectionField
- ColorField
- CountryField
- CurrencyField
- DateField
- DateTimeField
- EmailField
- HiddenField
- IdField
- ImageField
- IntegerField
- LanguageField
- LocaleField
- MoneyField
- NumberField
- PercentField
- SlugField
- TelephoneField
- TextareaField
- TextEditorField
- TextField
- TimeField
- TimezoneField
- UrlField
Doctrine 类型和 EasyAdmin 字段之间的映射
下表显示了根据实体属性的 Doctrine DBAL 类型 建议使用的 EasyAdmin 字段
Doctrine 类型 | 推荐的 EasyAdmin 字段 |
---|---|
array |
ArrayField |
ascii_string |
TextField |
bigint |
TextField |
binary |
(不支持) |
blob |
(不支持) |
boolean |
BooleanField |
date_immutable |
DateField |
date |
DateField |
datetime_immutable |
DateTimeField |
datetime |
DateTimeField |
datetimetz_immutable |
DateTimeField |
datetimetz |
DateTimeField |
datetinterval |
TextField |
decimal |
NumberField |
float |
NumberField |
guid |
TextField |
integer |
IntegerField |
json_array |
ArrayField |
json |
TextField , TextareaField , CodeEditorField |
object |
TextField , TextareaField , CodeEditorField |
simple_array |
ArrayField |
smallint |
IntegerField |
string |
TextField |
text |
TextareaField , TextEditorField , CodeEditorField |
time_immutable |
TimeField |
time |
TimeField |
除了这些之外,EasyAdmin 还包括用于特定值的其他字段类型
AvatarField
,ColorField
,CountryField
,CurrencyField
,EmailField
,IdField
,ImageField
,LanguageField
,LocaleField
,SlugField
,TelephoneField
,TimezoneField
和UrlField
与 Doctrine 的string
类型配合良好。MoneyField
和PercentField
与 Doctrine 的decimal
、float
和integer
配合良好,具体取决于您存储数据的方式。AssociationField
、CollectionField
和ChoiceField
是特殊字段,分别对应于 Symfony 的EntityType
、CollectionType
和ChoiceType
。
字段配置
本节显示了所有字段类型可用的配置选项。 此外,某些字段定义了其他配置选项,如 字段参考 中所示。
标签选项
字段构造函数的第二个可选参数是标签,它可以采用许多不同的值
- 如果您未显式设置标签,EasyAdmin 会根据字段名称自动生成标签(例如“firstName”->“First Name”);
- null:EasyAdmin 会根据字段名称自动生成标签(例如“firstName”->“First Name”);
- 空字符串:该字段不显示任何标签,但会呈现一个空的
<label>
元素,以免弄乱表单布局; - false:该字段不显示任何标签,也不会呈现
<label>
元素。 这对于显示特殊的全宽字段(例如使用自定义字段模板创建的地图或宽表)非常有用; - 如果您显式设置标签,EasyAdmin 将使用该值; 内容可以包含 HTML 标签,它们将被呈现,而不是转义。 此外,您可以使用
Translatable
内容(例如t('admin.form.labels.user')
)
以下是一些操作中的字段标签示例
// 未定义标签:自动生成标签(label = 'First Name') TextField::new('firstName'), // 标签为 null:自动生成标签(label = 'First Name') TextField::new('firstName', null),
// 标签为 false:不显示标签,也不呈现 <label> 元素 TextField::new('firstName', false),
// 显式设置标签:呈现其内容,包括 HTML 标签 TextField::new('firstName', 'Customer <b>Name</b>'),
设计选项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
TextField::new('firstName', 'Name')
// use this method if your field needs a specific form theme to render properly
->addFormTheme('@FOSCKEditor/Form/ckeditor_widget.html.twig')
// you can add more than one form theme using the same method
->addFormTheme('theme1.html.twig', 'theme2.html.twig', 'theme3.html.twig')
// CSS class/classes are applied to the field contents (in the 'index' page)
// or to the row that wraps the contents (in the 'detail', 'edit' and 'new' pages)
// use this method to add new classes to the ones applied by EasyAdmin
->addCssClass('text-large text-bold')
// use this other method if you want to remove any CSS class added by EasyAdmin
->setCssClass('text-large text-bold')
// this defines the Twig template used to render this field in 'index' and 'detail' pages
// (this is not used in the 'edit'/'new' pages because they use Symfony Forms themes)
->setTemplatePath('admin/fields/my_template.html.twig')
// useful for example to right-align numbers/money values (this setting is ignored in 'detail' page)
->setTextAlign('right')
;
与 CRUD 设计选项 类似,字段还可以加载 CSS 文件、Javascript 文件和 Webpack Encore 条目,并将 HTML 内容添加到后端页面的 <head>
和/或 <body>
元素中
1 2 3 4 5 6 7
TextField::new('firstName', 'Name')
->addCssFiles('bundle/some-bundle/foo.css', 'some-custom-styles.css')
->addJsFiles('admin/some-custom-code.js')
->addWebpackEncoreEntry('admin-maps')
->addHtmlContentToHead('<link rel="dns-prefetch" href="https://assets.example.com">')
->addHtmlContentToBody('<!-- generated at '.time().' -->')
;
默认情况下,这些 Web 资源在所有后端页面中加载。 如果您需要更精确的控制,请使用 Asset
类来定义资源
1 2 3 4 5 6 7 8 9 10
use EasyCorp\Bundle\EasyAdminBundle\Config\Asset;
// ...
TextField::new('firstName', 'Name')
->addCssFiles(Asset::new('bundle/some-bundle/foo.css')->ignoreOnForm()->htmlAttr('media', 'print'))
->addJsFiles(Asset::new('admin/some-custom-code.js')->onlyOnIndex()->defer())
->addWebpackEncoreEntries(Asset::new('admin-maps')->onlyWhenCreating()->preload())
// you can even define the Symfony Asset package which the asset belongs to
->addCssFiles(Asset::new('some-path/bar.css')->package('legacy_assets'))
;
格式化选项
formatValue()
方法允许在 index
和 detail
页面中呈现值之前将 PHP 可调用对象应用于该值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
IntegerField::new('stock', 'Stock')
// callbacks usually take only the current value as argument
->formatValue(function ($value) {
return $value < 10 ? sprintf('%d **LOW STOCK**', $value) : $value;
});
TextEditorField::new('description')
// callables also receives the entire entity instance as the second argument
->formatValue(function ($value, $entity) {
return $entity->isPublished() ? $value : 'Coming soon...';
});
// in PHP 7.4 and newer you can use arrow functions
// ->formatValue(fn ($value) => $value < 10 ? sprintf('%d **LOW STOCK**', $value) : $value);
// ->formatValue(fn ($value, $entity) => $entity->isPublished() ? $value : 'Coming soon...');
其他选项
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
TextField::new('firstName', 'Name')
// if TRUE, listing can be sorted by this field (default: TRUE)
// unmapped fields cannot be sorted
->setSortable(false)
// help message displayed for this field in the 'detail', 'edit' and 'new' pages
->setHelp('...')
// sets the value of the `empty_data` option in the Symfony form
// see https://symfony.ac.cn/doc/current/reference/forms/types/form.html#empty-data
->setEmptyData('Jane Doe')
// the Symfony Form type used to render this field in 'edit'/'new' pages
// (fields have good default values for this option, so you don't usually configure this)
->setFormType(TextType::class)
// an array of parameters passed to the Symfony form type
// (this only overrides the values of the passed form type options;
// it leaves all the other existing type options unchanged)
->setFormTypeOptions(['option_name' => 'option_value'])
// a custom HTML attribute added when rendering the field
// e.g. setHtmlAttribute('data-foo', 'bar') renders a 'data-foo="bar"' attribute in HTML
// On 'index' and 'detail' pages, the attribute is added to the field container:
// <td> and div.field-group respectively
// On 'new' and 'edit' pages, the attribute is added to the form field;
// it's a shortcut for the equivalent setFormTypeOption('attr.data-foo', 'bar)
->setHtmlAttribute('attribute_name', 'attribute_value')
// a key-value array of attributes to add to the HTML element
->setHtmlAttributes(['data-foo' => 'bar', 'autofocus' => 'autofocus'])
创建自定义字段
字段是一个实现 EasyCorp
的类。 尽管该接口仅要求实现一些方法,但您可能希望添加内置字段中提供的所有方法,以配置所有常见的字段选项。 您可以使用 EasyCorp
来实现此目的。
假设您想创建一个自定义 MapField
,它为给定的邮政地址呈现完整的地图。 这是您可以为该字段创建的类
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
namespace App\Admin\Field;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
final class MapField implements FieldInterface
{
use FieldTrait;
/**
* @param TranslatableInterface|string|false|null $label
*/
public static function new(string $propertyName, $label = null): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
// this template is used in 'index' and 'detail' pages
->setTemplatePath('admin/field/map.html.twig')
// this is used in 'edit' and 'new' pages to edit the field contents
// you can use your own form types too
->setFormType(TextareaType::class)
->addCssClass('field-map')
// loads the CSS and JS assets associated to the given Webpack Encore entry
// in any CRUD page (index/detail/edit/new). It's equivalent to calling
// encore_entry_link_tags('...') and encore_entry_script_tags('...')
->addWebpackEncoreEntries('admin-field-map')
// these methods allow to define the web assets loaded when the
// field is displayed in any CRUD page (index/detail/edit/new)
->addCssFiles('js/admin/field-map.css')
->addJsFiles('js/admin/field-map.js')
;
}
}
接下来,创建用于在 index
和 detail
CRUD 页面 中呈现字段的模板。 该模板可以使用任何 Twig 模板功能 和以下变量
ea
,一个EasyCorp
实例,它存储 admin 上下文,并且在所有后端模板中都可用;\Bundle \EasyAdminBundle \Context \AdminContext field
,一个EasyCorp
实例,它存储正在呈现的字段的配置和值;\Bundle \EasyAdminBundle \Dto \FieldDto entity
,一个EasyCorp
实例,它存储字段所属实体的实例以及有关该 Doctrine 实体的其他有用数据。\Bundle \EasyAdminBundle \Dto \EntityDto
注意
此模板不用于 edit
和 new
CRUD 页面,它们使用 Symfony 表单主题 来定义每个表单字段的显示方式。
就这样。 您现在可以在任何 CRUD 控制器中使用此字段
1 2 3 4 5 6 7 8 9
use App\Admin\MapField;
public function configureFields(string $pageName): iterable
{
return [
// ...
MapField::new('shipAddress'),
];
}
自定义选项
如果您的字段在任何方面都是可配置的,您可以为其添加自定义选项。 添加选项的推荐方法是将它们的名称定义为字段对象中的公共常量,并使用 FieldTrait
中定义的 setCustomOption()
方法来设置它们的值。
假设上一节中定义的 MapField
允许使用 Google Maps 或 OpenStreetMap 来呈现地图。 您可以按如下方式添加该选项
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
namespace App\Admin\Field;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
final class MapField implements FieldInterface
{
use FieldTrait;
public const OPTION_MAP_PROVIDER = 'mapProvider';
public static function new(string $propertyName, ?string $label = null): self
{
return (new self())
// ...
->setCustomOption(self::OPTION_MAP_PROVIDER, 'openstreetmap')
;
}
public function useGoogleMaps(): self
{
$this->setCustomOption(self::OPTION_MAP_PROVIDER, 'google');
return $this;
}
public function useOpenStreetMap(): self
{
$this->setCustomOption(self::OPTION_MAP_PROVIDER, 'openstreetmap');
return $this;
}
}
稍后,您可以通过字段 DTO 的 getCustomOptions()
方法访问这些选项。 例如,在 Twig 模板中
1 2 3 4 5 6 7 8 9 10 11
{# admin/field/map.html.twig #}
{% if 'google' === field.customOptions.get('mapProvider') %}
{# ... #}
{% endif %}
{# if you defined the field options as public constants, you can access
them in the template too (although resulting code is a bit verbose) #}
{% set map_provider_option = constant('App\\Admin\\MapField::OPTION_MAP_PROVIDER') %}
{% if 'google' === field.customOptions.get(map_provider_option) %}
{# ... #}
{% endif %}
字段配置器
某些字段的默认选项取决于实体属性的值,该值仅在运行时可用。 这就是为什么您可以选择定义字段配置器的原因,该配置器是一个在呈现字段之前更新字段配置的类。
EasyAdmin 为其内置字段定义了许多配置器。 您也可以创建自己的配置器(用于配置您自己的字段和/或内置字段)。 字段配置器是实现 EasyCorp
的类。
实施后,为您的配置器定义一个 Symfony 服务,并使用 ea.field_configurator
标记对其进行标记。 可选地,您可以定义标记的 priority
属性,以便在内置配置器之前或之后运行您的配置器。