在Symfony 2中,这是创建删除记录的链接的最佳方式吗?
我可以定义/entity/delete
仅接受DELETE
方法的路由,但我不知道如何从模板创建DELETE
链接。创建PUT
链接也是如此。
那么,你做什么的?接受GET
请愿删除记录?有没有办法创建DELETE
链接?
答案 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”。