CRUD 控制器
CRUD 控制器 为 Doctrine ORM 实体提供 CRUD 操作(创建、显示、更新、删除)。每个 CRUD 控制器可以关联到一个或多个仪表盘。
从技术上讲,这些 CRUD 控制器是常规的 Symfony 控制器,因此您可以像在控制器中通常做的那样进行任何操作,例如注入服务和使用快捷方式,如 $this->render()
或 $this->isGranted()
。
CRUD 控制器必须实现 EasyCorp
接口,这确保在控制器中定义了某些方法。除了实现接口,您还可以从 AbstractCrudController
类扩展。运行以下命令以生成 CRUD 控制器的基本结构
1
$ php bin/console make:admin:crud
CRUD 控制器页面
CRUD 控制器的四个主要页面是
index
,显示实体列表,可以分页、按列排序,并使用搜索查询和过滤器进行优化;detail
,显示给定实体的内容;new
,允许创建新的实体实例;edit
,允许更新给定实体的任何属性。
这些页面是在 AbstractCrudController
控制器中使用四个同名操作生成的。此控制器定义了其他辅助操作(例如,delete
和 autocomplete
),这些操作不匹配任何页面。
CRUD 路由
当使用 漂亮的管理员 URL 时,每个 CRUD 操作都定义了一个默认遵循此名称和路径的管理员路由
CRUD 路由名称 | CRUD 路由路径 |
---|---|
*_index |
/ |
*_new |
/new |
*_batch_delete |
/batch-delete |
*_autocomplete |
/autocomplete |
*_edit |
/{entityId}/edit |
*_delete |
/{entityId}/delete |
*_detail |
/{entityId} |
例如,对于名为 ProductCrudController
的 CRUD 控制器,它属于一个路由名为 admin
且路径为 /admin
的后端,它将生成以下路由
管理路由名称 | 管理路由路径 |
---|---|
admin_product_index |
/admin/product |
admin_product_new |
/admin/product/new |
admin_product_batch_delete |
/admin/product/batch-delete |
admin_product_autocomplete |
/admin/product/autocomplete |
admin_product_edit |
/admin/product/324/edit |
admin_product_delete |
/admin/product/324/delete |
admin_product_detail |
/admin/product/324 |
提示
默认情况下,EasyAdmin 在所有仪表盘上为所有 CRUD 控制器生成路由。您可以限制每个仪表盘上可访问的控制器,以避免生成所有这些路由。
您可以使用 #[AdminDashboard]
属性的 routes
选项自定义某些仪表盘提供的所有 CRUD 控制器的操作的路由名称和/或路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14
use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminDashboard;
// ...
#[AdminDashboard(routePath: '/admin', routeName: 'admin', routes: [
'index' => ['routePath' => '/all'],
'new' => ['routePath' => '/create', 'routeName' => 'create'],
'edit' => ['routePath' => '/editing-{entityId}', 'routeName' => 'editing'],
'delete' => ['routePath' => '/remove/{entityId}'],
'detail' => ['routeName' => 'view'],
])]
class SomeDashboardController extends AbstractDashboardController
{
// ...
}
使用此配置,ProductCrudController
操作的路由将是
管理路由名称 | 管理路由路径 |
---|---|
admin_product_index |
/admin/product/all |
admin_product_create |
/admin/product/create |
admin_product_batch_delete |
/admin/product/current/batch-delete |
admin_product_autocomplete |
/admin/product/current/autocomplete |
admin_product_editing |
/admin/product/current/editing-324 |
admin_product_delete |
/admin/product/remove/324 |
admin_product_view |
/admin/product/324 |
您还可以使用带有以下选项的 #[AdminCrud]
属性自定义 CRUD 控制器的路径和/或路由名称
routePath
:表示整个路由路径中控制器的值(例如,/foo
路径将导致/admin
+/foo
+/<action>
);routeName
:表示完整路由名称中控制器的值(例如,foo_bar
路由名称将导致admin_
+foo_bar
+_<action>
)。
使用与上面相同的示例,您可以按如下方式配置控制器的路由名称和路径
1 2 3 4 5 6 7 8
use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminCrud;
// ...
#[AdminCrud(routePath: '/stock/current', routeName: 'stock')]
class ProductCrudController extends AbstractCrudController
{
// ...
}
路由名称/路径将不再是 admin_product_*
和 /admin/product/*
,而是以下内容
管理路由名称 | 管理路由路径 |
---|---|
admin_stock_index |
/admin/stock/current |
admin_stock_new |
/admin/stock/current/new |
admin_stock_batch_delete |
/admin/stock/current/batch-delete |
admin_stock_autocomplete |
/admin/stock/current/autocomplete |
admin_stock_edit |
/admin/stock/current/324/edit |
admin_stock_delete |
/admin/stock/current/324/delete |
admin_stock_detail |
/admin/stock/current/324 |
最后,您还可以使用 #[AdminAction]
属性自定义每个 CRUD 控制器操作的路由名称和/或路径
1 2 3 4 5 6 7 8 9 10 11 12 13
use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminAction;
// ...
class ProductCrudController extends AbstractCrudController
{
// ...
#[AdminAction(routePath: '/latest-products', routeName: 'latest')]
public function index(AdminContext $context)
{
// ...
}
}
此控制器的 index()
操作将不再使用 admin_product_index
路由名称和 URL 中的 /admin/product
路径。相反,路由名称将是 admin_product_latest
,路径将是 /admin/product/latest-products
。
提示
您可以组合 #[AdminDashboard]
、#[AdminCrud]
和 #[AdminAction]
属性来自定义部分或全部路由名称和路径。
页面名称和常量
某些方法需要一些 CRUD 页面的名称作为参数。您可以使用以下任何字符串:'index'
、'detail'
、'edit'
和 'new'
。如果您喜欢使用常量来表示这些值,请使用 Crud::PAGE_INDEX
、Crud::PAGE_DETAIL
、Crud::PAGE_EDIT
和 Crud::PAGE_NEW
(它们在 EasyCorp
类中定义)。
CRUD 控制器配置
CRUD 控制器的唯一强制配置选项是控制器管理的 Doctrine 实体的 FQCN。这被定义为一个公共静态方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
namespace App\Controller\Admin;
use App\Entity\Product;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class ProductCrudController extends AbstractCrudController
{
// it must return a FQCN (fully-qualified class name) of a Doctrine ORM entity
public static function getEntityFqcn(): string
{
return Product::class;
}
// ...
}
其余 CRUD 选项使用 configureCrud()
方法配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
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
->setEntityLabelInSingular('...')
->setDateFormat('...')
// ...
;
}
}
设计选项
1 2 3 4 5 6 7 8 9 10 11 12
public function configureCrud(Crud $crud): Crud
{
return $crud
// set this option if you prefer the page content to span the entire
// browser width, instead of the default design which sets a max width
->renderContentMaximized()
// set this option if you prefer the sidebar (which contains the main menu)
// to be displayed as a narrow column instead of the default expanded design
->renderSidebarMinimized()
;
}
实体选项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
public function configureCrud(Crud $crud): Crud
{
return $crud
// the labels used to refer to this entity in titles, buttons, etc.
->setEntityLabelInSingular('Product')
->setEntityLabelInPlural('Products')
// in addition to a string, the argument of the singular and plural label methods
// can be a closure that defines two nullable arguments: entityInstance (which will
// be null in 'index' and 'new' pages) and the current page name
->setEntityLabelInSingular(
fn (?Product $product, ?string $pageName) => $product ? $product->toString() : 'Product'
)
->setEntityLabelInPlural(function (?Category $category, ?string $pageName) {
return 'edit' === $pageName ? $category->getLabel() : 'Categories';
})
// the Symfony Security permission needed to manage the entity
// (none by default, so you can manage all instances of the entity)
->setEntityPermission('ROLE_EDITOR')
;
}
标题和帮助选项
默认情况下,index
和 new
页面的页面标题基于使用 setEntityLabelInSingular()
和 setEntityLabelInPlural()
方法定义的 实体选项 值。在 detail
和 edit
页面中,EasyAdmin 首先尝试将实体转换为字符串表示形式,否则回退到通用标题。
您可以使用以下方法覆盖默认页面标题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
public function configureCrud(Crud $crud): Crud
{
return $crud
// the visible title at the top of the page and the content of the <title> element
// it can include these placeholders:
// %entity_name%, %entity_as_string%,
// %entity_id%, %entity_short_id%
// %entity_label_singular%, %entity_label_plural%
->setPageTitle('index', '%entity_label_plural% listing')
// you can pass a PHP closure as the value of the title
->setPageTitle('new', fn () => new \DateTime('now') > new \DateTime('today 13:00') ? 'New dinner' : 'New lunch')
// in DETAIL and EDIT pages, the closure receives the current entity
// as the first argument
->setPageTitle('detail', fn (Product $product) => (string) $product)
->setPageTitle('edit', fn (Category $category) => sprintf('Editing <b>%s</b>', $category->getName()))
// the help message displayed to end users (it can contain HTML tags)
->setHelp('edit', '...')
;
}
EasyAdmin 将 raw
过滤器应用于模板中显示的所有标题、标签、帮助消息等。这样做是为了允许您使用 HTML 标签自定义所有内容(因为这些标签将被呈现而不是转义)。
这就是 EasyAdmin 使用的默认页面标题仅包含安全内容(如实体名称和 ID)的原因。否则,您的后端可能会受到 XSS 攻击。
如果您更改默认页面标题以包含占位符 %entity_as_string%
,请检查您是否未将用户创建的内容包含在相关实体的 __toString()
方法返回的值中。如果您无法避免这种情况,请确保使用 Symfony HtmlSanitizer 组件 对任何用户提交的数据进行清理。
日期、时间和数字格式化选项
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
public function configureCrud(Crud $crud): Crud
{
return $crud
// the argument must be either one of these strings: 'short', 'medium', 'long', 'full', 'none'
// (the strings are also available as \EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField::FORMAT_* constants)
// or a valid ICU Datetime Pattern (see https://unicode-org.github.io/icu/userguide/format_parse/datetime/)
->setDateFormat('...')
->setTimeFormat('...')
// first argument = datetime pattern or date format; second optional argument = time format
->setDateTimeFormat('...', '...')
->setDateIntervalFormat('%%y Year(s) %%m Month(s) %%d Day(s)')
->setTimezone('...')
// this option makes numeric values to be rendered with a sprintf()
// call using this value as the first argument.
// this option overrides any formatting option for all numeric values
// (e.g. setNumDecimals(), setRoundingMode(), etc. are ignored)
// NumberField and IntegerField can override this value with their
// own setNumberFormat() methods, which works in the same way
->setNumberFormat('%.2d')
// Sets the character used to separate each thousand group in a number
// e.g. if separator is ',' then 12345 is formatted as 12,345
// By default, EasyAdmin doesn't add any thousands separator to numbers;
// NumberField and IntegerField can override this value with their
// own setThousandsSeparator() methods, which works in the same way
->setThousandsSeparator(',')
// Sets the character used to separate the decimal part of a non-integer number
// e.g. if separator is '.' then 1/10 is formatted as 0.1
// by default, EasyAdmin displays the default decimal separator used by PHP;
// NumberField and IntegerField can override this value with their
// own setDecimalSeparator() methods, which works in the same way
->setDecimalSeparator('.')
;
}
搜索、排序和分页选项
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
public function configureCrud(Crud $crud): Crud
{
return $crud
// ...
// the names of the Doctrine entity properties where the search is made on
// (by default it looks for in all properties)
->setSearchFields(['name', 'description'])
// use dots (e.g. 'seller.email') to search in Doctrine associations
->setSearchFields(['name', 'description', 'seller.email', 'seller.address.zipCode'])
// set it to null to disable and hide the search box
->setSearchFields(null)
// call this method to focus the search input automatically when loading the 'index' page
->setAutofocusSearch()
// by default, the search results match all the terms (SearchMode::ALL_TERMS):
// term1 in (field1 or field2) AND term2 in (field1 or field2)
// e.g. if you look for 'lorem ipsum' in [title, description],
// results require matching 'lorem' in either title or description
// (or both) AND 'ipsum' in either title or description (or both)
->setSearchMode(SearchMode::ALL_TERMS)
// use the SearchMode::ANY_TERMS option to change the search mode to
// match at least one of the terms:
// term1 in (field1 or field2) OR term2 in (field1 or field2)
// e.g. if you look for 'lorem ipsum' in [title, description],
// results will match either 'lorem' in title or description (or both)
// OR 'ipsum' in title or description (or both)
->setSearchMode(SearchMode::ANY_TERMS)
;
}
提示
默认情况下,搜索引擎拆分所有术语(搜索 foo bar
返回包含 foo
和 bar
的项目)。您可以使用引号将全部或部分查询括起来以进行精确搜索:"foo bar"
仅返回包含该确切内容的项目,包括中间的空格。
1 2 3 4 5 6 7 8 9 10 11 12 13
public function configureCrud(Crud $crud): Crud
{
return $crud
// ...
// defines the initial sorting applied to the list of entities
// (user can later change this sorting by clicking on the table columns)
->setDefaultSort(['id' => 'DESC'])
->setDefaultSort(['id' => 'DESC', 'title' => 'ASC', 'startsAt' => 'DESC'])
// you can sort by Doctrine associations up to two levels
->setDefaultSort(['seller.name' => 'ASC'])
;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
public function configureCrud(Crud $crud): Crud
{
return $crud
// ...
// the max number of entities to display per page
->setPaginatorPageSize(30)
// the number of pages to display on each side of the current page
// e.g. if num pages = 35, current page = 7 and you set ->setPaginatorRangeSize(4)
// the paginator displays: [Previous] 1 ... 3 4 5 6 [7] 8 9 10 11 ... 35 [Next]
// set this number to 0 to display a simple "< Previous | Next >" pager
->setPaginatorRangeSize(4)
// these are advanced options related to Doctrine Pagination
// (see https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/tutorials/pagination.html)
->setPaginatorUseOutputWalkers(true)
->setPaginatorFetchJoinCollection(true)
;
}
注意
当使用 Doctrine 过滤器 时,列表可能不包含某些项目,因为这些项目已被这些全局 Doctrine 过滤器删除。当请求 URL 属于仪表盘时,使用仪表盘路由名称以不应用过滤器。您还可以通过 应用程序上下文变量 获取仪表盘路由名称。
默认情况下,执行 Doctrine 查询以获取 index
页面中显示的实体列表时,会考虑排序配置、可选的搜索查询、可选的 过滤器 和分页。如果您需要完全自定义此查询,请在您的 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
public function configureCrud(Crud $crud): Crud
{
return $crud
// this method allows to use your own template to render a certain part
// of the backend instead of using EasyAdmin default template
// the first argument is the "template name", which is the same as the
// Twig path but without the `@EasyAdmin/` prefix and the `.html.twig` suffix
->overrideTemplate('crud/field/id', 'admin/fields/my_id.html.twig')
// the theme/themes to use when rendering the forms of this entity
// (in addition to EasyAdmin default theme)
->addFormTheme('foo.html.twig')
// this method overrides all existing form themes (including the
// default EasyAdmin form theme)
->setFormThemes(['my_theme.html.twig', 'admin.html.twig'])
// this sets the options of the entire form (later, you can set the options
// of each form type via the methods of their associated fields)
// pass a single array argument to apply the same options for the new and edit forms
->setFormOptions([
'validation_groups' => ['Default', 'my_validation_group']
]);
// pass two array arguments to apply different options for the new and edit forms
// (pass an empty array argument if you want to apply no options to some form)
->setFormOptions(
['validation_groups' => ['my_validation_group']],
['validation_groups' => ['Default'], '...' => '...'],
);
;
}
其他选项
1 2 3 4 5 6 7 8 9 10 11
public function configureCrud(Crud $crud): Crud
{
return $crud
// by default, when the value of some field is `null`, EasyAdmin displays
// a label with the `null` text. You can change that by overriding
// the `label/null` template. However, if you have lots of `null` values
// and want to reduce the "visual noise" in your backend, you can use
// the following option to not display anything when some value is `null`
// (this option is applied both in the `index` and `detail` pages)
->hideNullValues()
}
创建或编辑实体后自定义重定向
默认情况下,在创建或编辑实体时单击“保存”按钮后,您将被重定向到上一页。如果您想更改此行为,请覆盖 getRedirectResponseAfterSave()
方法。
例如,如果您添加了一个名为“保存并查看详情”的 自定义操作,您可能更喜欢在保存更改后重定向到详情页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
protected function getRedirectResponseAfterSave(AdminContext $context, string $action): RedirectResponse
{
$submitButtonName = $context->getRequest()->request->all()['ea']['newForm']['btn'];
if ('saveAndViewDetail' === $submitButtonName) {
// when using pretty admin URLs
return $this->redirectToRoute('admin_product_detail', [
'entityId' => $context->getEntity()->getPrimaryKeyValue(),
]);
// when using legacy admin URLs
$url = $this->container->get(AdminUrlGenerator::class)
->setAction(Action::DETAIL)
->setEntityId($context->getEntity()->getPrimaryKeyValue())
->generateUrl();
return $this->redirect($url);
}
return parent::getRedirectResponseAfterSave($context, $action);
}
不同 CRUD 控制器中的相同配置
如果您想在所有 CRUD 控制器中执行相同的配置,则无需在每个控制器中重复配置。相反,在您的仪表盘中添加 configureCrud()
方法,所有控制器都将继承该配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminDashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
#[AdminDashboard(routePath: '/admin', routeName: 'admin')]
class DashboardController extends AbstractDashboardController
{
// ...
public function configureCrud(): Crud
{
return Crud::new()
// this defines the pagination size for all CRUD controllers
// (each CRUD controller can override this value if needed)
->setPaginatorPageSize(30)
;
}
}
字段
字段允许在每个CRUD 页面上显示 Doctrine 实体的内容。EasyAdmin 提供了内置字段来显示所有常见数据类型,但您也可以创建自己的字段。
如果您的 CRUD 控制器从 AbstractCrudController
扩展,则字段会自动配置。在 index
页面中,您将看到一些字段,在其余页面中,您将看到尽可能多的字段以显示 Doctrine 实体的所有属性。
阅读关于字段的章节,了解如何配置要在每个页面上显示的字段,如何配置每个字段的呈现方式等等。
自定义 CRUD 操作
默认的 CRUD 操作(控制器中的 index()
、detail()
、edit()
、new()
和 delete()
方法)实现了应用程序中最常用的行为。
自定义其行为的第一种方法是在您自己的控制器中覆盖这些方法。但是,原始操作非常通用,以至于它们包含相当多的代码,因此覆盖它们不是很方便。
相反,您可以覆盖其他较小的方法,这些方法实现了 CRUD 操作所需的某些功能。例如,index()
操作调用名为 createIndexQueryBuilder()
的方法来创建用于获取索引列表中显示的结果的 Doctrine 查询构建器。如果您想自定义该列表,最好覆盖 createIndexQueryBuilder()
方法,而不是整个 index()
方法。有很多这样的方法,因此您应该检查 EasyCorp
类。
自定义 CRUD 操作的另一种选择是使用 EasyAdmin 触发的事件,例如 BeforeCrudActionEvent
和 AfterCrudActionEvent
。
创建、持久化和删除实体
CRUD 控制器的大多数操作最终会创建、持久化或删除实体。如果您的 CRUD 控制器从 AbstractCrudController
扩展,则这些方法已经实现,但您可以通过覆盖方法和监听事件来自定义它们。
首先,您可以覆盖 createEntity()
、updateEntity()
、persistEntity()
和 deleteEntity()
方法。createEntity()
方法例如仅执行 return new $entityFqcn()
,因此如果您的实体需要传递构造函数参数或设置其某些属性,则需要覆盖它
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
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 createEntity(string $entityFqcn)
{
$product = new Product();
$product->createdBy($this->getUser());
return $product;
}
// ...
}
覆盖此行为的另一种方法是监听 EasyAdmin 触发的事件,当实体被创建、更新、持久化、删除等时。
将其他变量传递给 CRUD 模板
AbstractCrudController
中实现的默认 CRUD 操作不以通常的 $this->render('...')
指令结束,以呈现 Twig 模板并在 Symfony Response
对象中返回其内容。
相反,CRUD 操作返回一个 EasyCorp
对象,其中包含传递给模板的变量,该模板呈现 CRUD 操作内容。此 KeyValueStore
对象类似于 Symfony 的 ParameterBag
对象。它就像一个面向对象的数组,具有有用的方法,例如 get()
、set()
、has()
等。
在结束每个 CRUD 操作之前,它们的 KeyValueStore
对象将传递给一个名为 configureResponseParameters()
的方法,您可以在自己的控制器中覆盖该方法以添加/删除/更改这些模板变量
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
namespace App\Controller\Admin;
use App\Entity\Product;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class ProductCrudController extends AbstractCrudController
{
// ...
public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore
{
if (Crud::PAGE_DETAIL === $responseParameters->get('pageName')) {
$responseParameters->set('foo', '...');
// keys support the "dot notation", so you can get/set nested
// values separating their parts with a dot:
$responseParameters->setIfNotSet('bar.foo', '...');
// this is equivalent to: $parameters['bar']['foo'] = '...'
}
return $responseParameters;
}
}
您可以根据需要向此 KeyValueStore
对象添加任意数量的参数。唯一必需的参数是 templateName
或 templatePath
,分别用于设置要呈现为 CRUD 操作结果的模板的名称或路径。
模板名称和模板路径
EasyAdmin 用于呈现其内容的所有模板都是可配置的。这就是为什么 EasyAdmin 处理“模板名称”而不是正常的 Twig 模板路径。
模板名称与模板路径相同,但没有 @EasyAdmin
前缀和 .html.twig
后缀。例如,@EasyAdmin/layout.html.twig
指的是 EasyAdmin 提供的内置布局模板。但是,layout
指的是“配置为应用程序布局的任何模板”。
使用模板名称而不是路径使您可以完全灵活地自定义应用程序行为,同时保留所有自定义模板。在 Twig 模板中,使用 ea.templatePath()
函数获取与给定模板名称关联的 Twig 路径
1 2 3 4 5 6 7
<div id="flash-messages">
{{ include(ea.templatePath('flash_messages')) }}
</div>
{% if some_value is null %}
{{ include(ea.templatePath('label/null')) }}
{% endif %}
生成管理 URL
当使用 漂亮的管理员 URL 时,EasyAdmin 为每个仪表盘的每个 CRUD 操作生成一个路由。您可以使用以下命令列出所有路由
1
$ php bin/console debug:router
如果您看不到某些或任何管理员路由,请清除 Symfony 应用程序的缓存,以便 EasyAdmin 路由加载器可以再次生成它们
1
$ php bin/console cache:clear
由于 Symfony 提供的 实用程序用于生成 URL,您可以使用这些路由中的任何一个来生成管理 URL
1 2 3 4 5 6 7 8 9 10
// redirecting to an admin URL inside a controller
return $this->redirectToRoute('admin_product_new');
// generating an admin URL inside a service
$userProfileUrl = $this->router->generate('admin_user_detail', [
'entityId' => $user->getId(),
]);
// generating an admin URL in a Twig template
<a href="{{ path('admin_blog_post_edit', {entityId: post.id}) }}">Edit Blog Post</a>
构建管理 URL
如果您不使用 漂亮的管理员 URL,或者如果您需要动态构建路由,则可以使用 EasyAdmin 提供的 AdminUrlGenerator
来构建管理 URL。
以这种方式生成 URL 时,您不是从头开始。EasyAdmin 重用当前请求中存在的所有查询参数。这样做是有目的的,因为基于当前 URL 生成新 URL 是最常见的场景。使用 unsetAll()
方法删除所有现有查询参数
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\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
class SomeCrudController extends AbstractCrudController
{
private $adminUrlGenerator;
public function __construct(AdminUrlGenerator $adminUrlGenerator)
{
$this->adminUrlGenerator = $adminUrlGenerator;
}
// ...
public function someMethod()
{
// instead of injecting the AdminUrlGenerator service in the constructor,
// you can also get it from inside a controller action as follows:
// $adminUrlGenerator = $this->container->get(AdminUrlGenerator::class);
// the existing query parameters are maintained, so you only
// have to pass the values you want to change.
$url = $this->adminUrlGenerator->set('page', 2)->generateUrl();
// you can remove existing parameters
$url = $this->adminUrlGenerator->unset('menuIndex')->generateUrl();
$url = $this->adminUrlGenerator->unsetAll()->set('foo', 'someValue')->generateUrl();
// the URL builder provides shortcuts for the most common parameters
$url = $this->adminUrlGenerator
->setController(SomeCrudController::class)
->setAction('theActionName')
->generateUrl();
// ...
}
}
提示
如果您需要出于任何原因手动处理管理 URL,则查询字符串参数的名称在 EA 类中定义为常量。
由于 ea_url()
Twig 函数,模板中可以使用完全相同的功能。在模板中,您可以省略对 generateUrl()
方法的调用(它将自动为您调用)
1 2 3 4 5 6 7 8 9
{# both are equivalent #}
{% set url = ea_url({ page: 2 }).generateUrl() %}
{% set url = ea_url({ page: 2 }) %}
{% set url = ea_url().set('page', 2) %}
{% set url = ea_url()
.setController('App\\Controller\\Admin\\SomeCrudController')
.setAction('theActionName') %}
从 EasyAdmin 外部生成 CRUD URL
当从 EasyAdmin 外部(例如,从常规 Symfony 控制器)生成 EasyAdmin 页面的 URL 时,管理上下文变量不可用。这就是为什么您必须始终设置与 URL 关联的 CRUD 控制器。如果您有多个仪表盘,则还必须设置仪表盘
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\Controller\Admin\DashboardController;
use App\Controller\Admin\ProductCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class SomeSymfonyController extends AbstractController
{
private $adminUrlGenerator;
public function __construct(AdminUrlGenerator $adminUrlGenerator)
{
$this->adminUrlGenerator = $adminUrlGenerator;
}
public function someMethod()
{
// if your application only contains one Dashboard, it's enough
// to define the controller related to this URL
$url = $this->adminUrlGenerator
->setController(ProductCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
// in applications containing more than one Dashboard, you must also
// define the Dashboard associated to the URL
$url = $this->adminUrlGenerator
->setDashboard(DashboardController::class)
->setController(ProductCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
// some actions may require to pass additional parameters
$url = $this->adminUrlGenerator
->setController(ProductCrudController::class)
->setAction(Action::EDIT)
->setEntityId($product->getId())
->generateUrl();
// ...
}
}
这同样适用于在 Twig 模板中生成的 URL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
{# if your application defines only one Dashboard #}
{% set url = ea_url()
.setController('App\\Controller\\Admin\\ProductCrudController')
.setAction('index') %}
{# if you prefer PHP constants, use this:
.setAction(constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Action::INDEX')) #}
{# if your application defines multiple Dashboards #}
{% set url = ea_url()
.setDashboard('App\\Controller\\Admin\\DashboardController')
.setController('App\\Controller\\Admin\\ProductCrudController')
.setAction('index') %}
{# some actions may require to pass additional parameters #}
{% set url = ea_url()
.setController('App\\Controller\\Admin\\ProductCrudController')
.setAction('edit')
.setEntityId(product.id) %}