将自己的操作添加到 SonataAdminBundle 下拉菜单

Adding own action to SonataAdminBundle dropdown menu

我们将 SonataAdminBundle 与我们的 Symfony2 应用程序一起使用。在编辑实体时,我想在位于右上角的下拉菜单中添加一个自己的操作,但我不知道它是如何工作的。

我知道我可以通过 configureRoutes(RouteCollection $collection) 添加自己的路线以及如何添加批处理操作或在列表视图中的实体后面添加自己的操作,但是我如何在操作中添加自己的 link编辑视图中的下拉菜单?

它基本上只是一个link,就像"Show me this entity in the frontend",所以不需要大逻辑。

一种方法是覆盖编辑时使用的模板。现在,您需要做的是:

  • app/Resources 中创建名为 SonataAdminBundle 的新目录(如果您还没有)。在里面,创建另一个名为 views 的。这将创建一个类似于 app/Resources/SonataAdminBundle/views 的路径。这是 Symfony 基本模板覆盖。您可以阅读有关该主题的更多信息 here.

  • 现在,您应该按照与原始包内相同的路径复制原始模板。我们这里感兴趣的模板文件位于sonata-project/admin-bundle/Resources/views/CRUD/base_edit.html.twig。这意味着您必须在 views 中创建另一个文件夹(我们刚刚在 app 中创建的文件夹,名为 CRUD。因此,现在我们必须遵循路径 app/Resources/SonataAdminBundle/views/CRUD。粘贴里面的模板 (base_edit.html.twig),我们就可以开始编辑了。

请记住,您的每个编辑操作都会使用以下模板。因此,是否要在每个 edit_action 中显示 link 取决于您。我将向您展示一种限制特定操作的方法。

您要编辑的块是 {% block actions %},它负责呈现下拉菜单。这是现在的样子:

{% block actions %}
    <li>{% include 'SonataAdminBundle:Button:show_button.html.twig' %}</li>
    <li>{% include 'SonataAdminBundle:Button:history_button.html.twig' %}</li>
    <li>{% include 'SonataAdminBundle:Button:acl_button.html.twig' %}</li>
    <li>{% include 'SonataAdminBundle:Button:list_button.html.twig' %}</li>
    <li>{% include 'SonataAdminBundle:Button:create_button.html.twig' %}</li>
{% endblock %}

现在剩下要做的就是在最后一个 <li> 标签后插入 link。

{% if admin.id(object) is not null and app.request.get('_route') == 'my_route' %}
<li>
    <a href="/generate/path/with/your/route">View in Frontend</a>
</li>
{% endif %}

admin.id(object) 将 return 您编辑的项目的当前 ID。 app.request.get('_route') 将 return 编辑操作的路径。如果您希望 link 在所有编辑操作中显示,您可以删除它。使用 admin.id(object)<a href="/generate/path/with/your/route">View in Frontend</a> 更改为您的路线名称,您应该可以开始了。

另一种方法是覆盖对象管理 class 中的方法 generateObjectUrl()

/**
 * @see \Sonata\AdminBundle\Admin\Admin::generateObjectUrl()
 */
public function generateObjectUrl($name, $object, array $parameters = array(), $absolute = false)
{
    if ('show' == $name) {
        return $this->getRouteGenerator()->generate('your_route_to_public_facing_view', [
            'id' => $this->getUrlsafeIdentifier($object),
        ], $absolute );
    }
    $parameters['id'] = $this->getUrlsafeIdentifier($object);
    return $this->generateUrl($name, $parameters, $absolute);
}

就是这样。不要乱用模板。并且没有模板代码会 运行 对每个其他管理员。

要让 link 自动出现,您必须通过 configureShowFields()$showMapper 添加内容。 (如果有人知道更好的方法,请告诉。)

覆盖 generateObjectUrl() 还有另一个好处:如果您在 $listMapper 上显示 show 按钮,URL 也会在那里更新。

编辑说:由于这会覆盖 show 路由,您将无法再使用该 built-in 功能。这对我来说没问题,因为我需要查看我的对象并加载所有 front-end css 和 js。

在您的管理员 class 中,覆盖以下方法:

public function getActionButtons($action, $object = null)
{
    $list = parent::getActionButtons($action, $object);

    $list['upload'] = [
        'template' => ':admin:my_upload_button.html.twig',
    ];

    return $list;
}

这将在此管理员的所有页面上添加一个自定义操作按钮。您可以在此处添加任何逻辑来决定要在哪些页面 ($action-s) 上显示按钮。

你可以在模板中做你想做的,但只是为了完成我的例子并显示与我的自定义操作的联系:

<li>
    <a class="sonata-action-element" href="{{ admin.generateUrl('upload') }}">
        <i class="fa fa-cloud-upload" aria-hidden="true"></i>
        Upload stuff
    </a>
</li>