最佳实践 - 删除Symfony 2的链接

时间:2014-02-13 07:21:32

标签: php rest symfony

在Symfony 2中,这是创建删除记录的链接的最佳方式吗?

我可以定义/entity/delete仅接受DELETE方法的路由,但我不知道如何从模板创建DELETE链接。创建PUT链接也是如此。

那么,你做什么的?接受GET请愿删除记录?有没有办法创建DELETE链接?

3 个答案:

答案 0 :(得分:16)

Symfony2 _method功能说明可在How to Define Route Requirements中找到。以下是我使用的解决方案。

链接

<a
    href="{{ path('my_delete_route_name', {'id': some_entity.id}) }}"
    class="as-form"
    data-method="delete"
    data-csrf="_token:{{ csrf }}"
>{{ 'delete'|trans({}, 'button') }}</a>

复制粘贴后将上述链接重新格式化为内联

附加onClick事件监听器:

<强> JS

$('.as-form').on('click',function(){
    var $form = $('<form/>').hide();

    //form options
    $form.attr({
        'action' : $(this).attr('href'),
        'method':'post'
    })

    //adding the _method hidden field
    $form.append($('<input/>',{
        type:'hidden',
        name:'_method'
    }).val($(this).data('method')));

    //adding a CSRF if needs
    if ($(this).data('csrf'))
    {
        var csrf = $(this).data('csrf').split(':');
        $form.append($('<input/>',{
            type:'hidden',
            name:csrf[0]
        }).val(csrf[1]));
    }

    //add form to parent node
    $(this).parent().append($form);

    $form.submit();

    return false;
});

<强>控制器

class MyCustomController extends Controller
{
    /**
    * @Route("/delete/{id}",name="my_delete_route_name")
    * @Method("DELETE")
    * @ParamConverter("entity", class="MyEntityClass")
    * @CsrfProtector(intention="my_csrf_intention", name="_token")
    */
    public function deleteAction(Request $request, $entity)
    {
        // do whatever you need
    }
}

注意

@CsrfProtector是我的自定义注释,用于在运行控制器方法之前验证请求中传递的CSRF令牌。

答案 1 :(得分:11)

锚点只能触发GET请求。由于GET请求可以被缓存,并且在某些将来(当您实现严格的缓存时)可能根本无法访问您的应用程序代码,因此使用GET更改修改应用程序状态的任何内容都是不好的做法。这是我在我的项目中所做的。有了这两个,您就可以在模板中执行以下操作:

<a href="{{ path('my_entity_destroy') }}" {{ delete_link(myEntity) }}>Delete</a>

如何运作

假设您的实体删除路径为:/my_entity,方法:[DELETE]

原则很简单。 delete_link扩展方法将在锚点上创建data-attribute,因此编译后的锚点将如下所示:

<a href="/my_entity" data-delete-link="3964">Delete</a>

然后,当有人点击该链接时,javascript将捕获该点击,创建一个表单并触发data-delete-link属性中提供ID的DELETE请求。

是什么让它起作用

以下是LinkHelper Twig扩展的可能性:

<?php

namespace Me\MyBundle\Twig;

class LinkHelperExtension extends \Twig_Extension
{
    public function getFunctions()
    {
        return [
            new \Twig_SimpleFunction('delete_link', [$this, 'fnDeleteLink'], ['is_safe' => ['all']]),
        ];
    }

    public function fnDeleteLink($target)
    {
        if (is_object($target)) {
            $target = $target->getId();
        }
        return "data-delete-link='$target'";
    }

    public function getName()
    {
        return 'link_helper';
    }
} 

我的基本模板中有一个JavaScript:

$(function () {
    var createForm = function (action, data) {
        var $form = $('<form action="' + action + '" method="POST"></form>');
        for (input in data) {
            if (data.hasOwnProperty(input)) {
                $form.append('<input name="' + input + '" value="' + data[input] + '">');
            }
        }

        return $form;
    };

    $(document).on('click', 'a[data-delete-link]', function (e) {
        e.preventDefault();
        var $this = $(this);

        var $form = createForm($this.attr('href'), {
            id: $this.attr('data-delete-link'),
            _method: 'DELETE'
        }).hide();

        $('body').append($form); // Firefox requires form to be on the page to allow submission
        $form.submit();
    });
});

限制

它仅适用于具有名为id的主键的实体。但是,您可以很容易地修改它以满足您的需要并支持复合主键等。

答案 2 :(得分:3)

如果没有启用JavaScript,这些解决方案将无效。如果您只需要编辑表单中的“删除按钮”,则还可以创建第二个带有删除名称的提交,并在Controller中的updateAction中重定向到deleteAction,如果单击“delete-submit”。