设计
后端的设计适用于任何类型的应用程序。它使用 Bootstrap 5、Font Awesome 图标和一些自定义 CSS 和 JavaScript 代码创建;所有这些都通过 Webpack 和 Symfony 的 Webpack Encore 进行管理。
像任何其他 Symfony 扩展包一样,在安装或更新扩展包时,资源会被复制到(或符号链接自)你应用程序的 public/bundles/
目录。如果由于任何原因这不起作用,你的后端将不会显示正确的 CSS/JS 样式。在这些情况下,运行此命令手动安装这些资源
1 2
# remove the --symlink option if your system doesn't support symbolic links
$ php bin/console assets:install --symlink
根据你的需求,有几种自定义设计的方法。其中一些需要纯 CSS/JavaScript 代码,另一些则需要覆盖和/或创建新的 Twig 模板。
修改后端模板
后端页面由多个 Twig 模板和片段创建。你可以通过两种方式修改它们
- 使用 Symfony 的机制覆盖 EasyAdmin 模板(这对于所有扩展包都是一样的,不仅限于 EasyAdmin);
- 使用 EasyAdmin 功能替换 EasyAdmin 模板。
覆盖模板
提示
除了使用 Symfony 的机制来覆盖模板,你还可以考虑使用 EasyAdmin 提供的类似但更强大的功能来替换模板,如下一节所述。
按照 Symfony 的机制从扩展包中覆盖模板,你必须在你的应用程序中创建 templates/bundles/EasyAdminBundle/
目录,然后创建与原始模板路径相同的新模板。例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
your-project/
├─ ...
└─ templates/
└─ bundles/
└─ EasyAdminBundle/
├─ layout.html.twig
├─ menu.html.twig
├─ crud/
│ ├─ index.html.twig
│ ├─ detail.html.twig
│ └─ field/
│ ├─ country.html.twig
│ └─ text.html.twig
├─ label/
│ └─ null.html.twig
└─ page/
├─ content.html.twig
└─ login.html.twig
你不必从头开始创建新模板,而是可以从原始模板扩展,并仅更改要覆盖的部分。但是,你必须在 extends
内部使用特殊语法以避免无限循环
1 2 3 4 5 6 7 8 9 10 11
{# templates/bundles/EasyAdminBundle/layout.html.twig #}
{# DON'T DO THIS: it will cause an infinite loop #}
{% extends '@EasyAdmin/layout.html.twig' %}
{# DO THIS: the '!' symbol tells Symfony to extend from the original template #}
{% extends '@!EasyAdmin/layout.html.twig' %}
{% block sidebar %}
{# ... #}
{% endblock %}
替换模板
此选项允许你使用自己的 Twig 模板渲染后端的某些部分。首先,你可以在仪表盘中全局替换一些模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
class DashboardController extends AbstractDashboardController
{
// ...
public function configureCrud(): Crud
{
return Crud::new()
// ...
// the first argument is the "template name", which is the same as the
// Twig path but without the `@EasyAdmin/` prefix
->overrideTemplate('label/null', 'admin/labels/my_null_label.html.twig')
->overrideTemplates([
'crud/index' => 'admin/pages/index.html.twig',
'crud/field/textarea' => 'admin/fields/dynamic_textarea.html.twig',
])
;
}
}
你也可以为每个 CRUD 控制器替换模板(这将覆盖在仪表盘中所做的任何更改)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class ProductCrudController extends AbstractCrudController
{
// ...
public function configureCrud(Crud $crud): Crud
{
return $crud
// ...
->overrideTemplate('crud/layout', 'admin/advanced_layout.html.twig')
->overrideTemplates([
'crud/field/text' => 'admin/product/field_id.html.twig',
'label/null' => 'admin/labels/null_product.html.twig',
])
;
}
}
字段和操作模板
每个 字段(和每个 操作)都定义了一个 setTemplatePath()
方法来设置用于渲染该特定字段(或操作)的 Twig 模板
1 2 3 4 5 6 7 8 9
TextField::new('...', '...')
// ...
->setTemplatePath('custom_fields/text.html.twig');
// ...
Action::new('...', '...')
// ...
->setTemplatePath('admin/actions/my_custom_action.html.twig');
setTemplatePath()
方法仅适用于在 index
和 detail
页面上显示的字段。阅读下一节,了解如何自定义 new
和 edit
页面中的字段,这些页面使用 Symfony 表单。
表单字段模板
EasyAdmin 提供了一个基于 Bootstrap 5 的即用型表单主题。仪表盘和 CRUD 控制器定义了 addFormTheme(string $themePath)
和 setFormThemes(array $themePaths)
方法,以便你可以使用自己的表单主题自定义各个表单字段。
想象一个表单字段,你想要包含一个 <a>
元素,该元素链接到其他信息。如果该字段名为 title
并且属于 Product
实体,则配置如下所示
1 2 3 4 5
TextField::new('title')
// ...
->setFormTypeOptions([
'block_name' => 'custom_title',
]);
下一步是定义该字段使用的模板片段,这需要了解 Symfony 定义的表单片段命名规则
1 2 3 4 5 6 7 8
{# templates/admin/form.html.twig #}
{# note that the Twig block name starts with an uppercase letter
('_Product_...' instead of '_product_...') because the first part
of the block name is the unmodified entity name #}
{% block _Product_custom_title_widget %}
{# ... #}
<a href="...">More information</a>
{% endblock %}
最后,将此自定义主题添加到用于渲染后端表单的主题列表中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class ProductCrudController extends AbstractCrudController
{
// ...
public function configureCrud(Crud $crud): Crud
{
return $crud
// ...
// don't forget to add EasyAdmin's form theme at the end of the list
// (otherwise you'll lose all the styles for the rest of form fields)
->setFormThemes(['admin/form.html.twig', '@EasyAdmin/crud/form_theme.html.twig'])
;
}
}
注意
你还可以使用原始字段名称覆盖表单 widget。在上面的示例中,它看起来像这样: {% block _Product_title_widget %}
。完整语法是: {% block _<Entity name>_<Field name>_widget %}
。
添加自定义 Web 资源
在仪表盘和/或 CRUD 控制器中使用 configureAssets()
方法来添加你自己的 CSS 和 JavaScript 文件
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
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class ProductCrudController extends AbstractCrudController
{
// ...
public function configureAssets(Assets $assets): Assets
{
return $assets
// adds the CSS and JS assets associated to the given Webpack Encore entry
// it's equivalent to adding these inside the <head> element:
// {{ encore_entry_link_tags('...') }} and {{ encore_entry_script_tags('...') }}
->addWebpackEncoreEntry('admin-app')
// it's equivalent to adding this inside the <head> element:
// <link rel="stylesheet" href="{{ asset('...') }}">
->addCssFile('build/admin.css')
->addCssFile('https://example.org/css/admin2.css')
// it's equivalent to adding this inside the <head> element:
// <script src="{{ asset('...'') }}"></script>
->addJsFile('build/admin.js')
->addJsFile('https://example.org/js/admin2.js')
// use these generic methods to add any code before </head> or </body>
// the contents are included "as is" in the rendered page (without escaping them)
->addHtmlContentToHead('<link rel="dns-prefetch" href="https://assets.example.com">')
->addHtmlContentToBody('<script> ... </script>')
->addHtmlContentToBody('<!-- generated at '.time().' -->')
;
}
}
3.3
JavaScript 文件和 JavaScript Webpack Encore 条目包含在页面的 <head>
元素中。在之前的 EasyAdmin 版本中,它们包含在 <body>
元素的底部。
如果你需要自定义 <link>
和 <script>
标签的 HTML 属性或其他功能,请将 Asset
对象传递给 addCssFile()
、addJsFile()
和 addWebpackEncoreEntry()
方法
1 2 3 4 5 6 7 8 9 10 11 12 13
use EasyCorp\Bundle\EasyAdminBundle\Config\Asset;
// ...
return $assets
->addCssFile(Asset::new('build/admin.css')->preload()->nopush())
->addCssFile(Asset::new('build/admin-print.css')->htmlAttr('media', 'print'))
->addJsFile(Asset::new('build/admin.js')->defer())
->addJsFile(Asset::new('build/admin.js')->preload())
->addJsFile(Asset::new('build/admin.js')->htmlAttr('referrerpolicy', 'strict-origin'))
->addWebpackEncoreEntry(Asset::new('admin-app')->webpackEntrypointName('...'))
;
注意
如果你想卸载 EasyAdmin 包含的默认资源,请覆盖默认的 layout.html.twig
模板并清空 head_stylesheets
和 head_javascript
Twig 代码块。
自定义后端设计
后端的设计使用了很多 CSS 变量创建。这使你可以更轻松地根据自己的需求进行自定义。你将在 vendor/easycorp/easyadmin-bundle/assets/css/easyadmin-theme/variables-theme.scss
文件中找到所有变量。要覆盖它们中的任何一个,请创建一个 CSS 文件并重新定义变量值
1 2 3 4 5 6 7 8 9 10 11
/* public/css/admin.css */
:root {
/* make the backend contents as wide as the browser window */
--body-max-width: 100%;
/* change the background color of the <body> */
--body-bg: #f5f5f5;
/* make the base font size smaller */
--font-size-base: 13px;
/* remove all border radius to make corners straight */
--border-radius: 0px;
}
然后,在你的仪表盘和/或资源管理中加载此 CSS 文件
1 2 3 4 5 6 7 8 9 10 11 12
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
class DashboardController extends AbstractDashboardController
{
// ...
public function configureAssets(): Assets
{
return Assets::new()->addCssFile('css/admin.css');
}
}
注意
由于 Bootstrap 样式的定义方式,不可能使用 CSS 变量来覆盖所有样式。有时你可能还需要覆盖一些 Sass 变量的值(这些变量在assets/css/easyadmin-theme/variables-bootstrap.scss
文件)中定义。
CSS 选择器
每个后端页面的 <body>
元素都包含不同的 id
和 class
属性,以帮助你定位自己的样式。id 遵循此模式
页面 | <body> ID 属性 |
---|---|
详情 |
ea-detail-<实体名称>-<实体 ID> |
编辑 |
ea-edit-<实体名称>-<实体 ID> |
列表 |
ea-index-<实体名称> |
新建 |
ea-new-<实体名称> |
例如,如果你正在编辑 User 实体的 id = 200
的元素,则该页面的 <body>
将是 <body id="easyadmin-edit-User-200" ...>
。
class 属性的模式是不同的,因为它同时应用了多个 CSS 类
页面 | <body> CSS 类 |
---|---|
详情 |
ea-detail ea-detail-<实体名称> |
编辑 |
ea-edit ea-edit-<实体名称> |
列表 |
ea-index ea-index-<实体名称> |
新建 |
ea-new ea-new-<实体名称> |
例如,如果你正在显示 User 实体元素的列表,则该页面的 <body>
将是 <body class="ea index index-User" ...>
。
使用 Webpack 管理后端资源
EasyAdmin 使用 Webpack(通过 Symfony 的 Webpack Encore)来管理其 CSS 和 JavaScript 资源。此扩展包同时提供了所有资源的源文件和编译版本,因此你无需安装 Webpack 即可使用此扩展包。
但是,如果你想完全控制后端样式,可以使用 Webpack 集成 assets/
目录中提供的 SCSS 和 JavaScript 源文件。唯一的缺点是 EasyAdmin 在加载资源时尚未使用 Webpack Encore,因此你无法使用版本控制等功能。这将在未来版本中修复。