我有一个来自数据库的条目列表。我想在每一行的末尾都有一个“删除按钮”,这样用户就不必先进入编辑/显示页面来删除该条目。
我尝试使用csrf标记创建一个隐藏的输入字段,如下所示:
return $this->createFormBuilder()
->getForm()
;
这将输出:
<div id="form">
<input type="hidden" id="form__token" name="form[_token]" value="6c98ebfa9df07.....">
</div>
表单的其余部分我在twig模板中放置,以便每个表单根据条目的id有自己的操作路径。
不幸的是,在树枝模板中只有第一个{{ form_widget(delete_form) }}
将被渲染。
我如何更频繁地使用此隐藏字段? 或者有没有办法以不同的方式完成这一切?
感谢您的帮助
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$deleteForm = $this->createDeleteForms();
$entities = $em->getRepository('IntranetServicesBundle:Laender')->findAll();
return $this->render('IntranetServicesBundle:Laender:index.html.twig', array(
'entities' => $entities,
'delete_form' => $deleteForm->createView(),
));
}
private function createDeleteForms()
{
return $this->createFormBuilder()
->add('id', 'hidden')
->getForm()
;
}
答案 0 :(得分:3)
您可以使用以下内容呈现单个令牌:
{{ form_widget(form._token) }}
或特别针对您的情况:
{{ form_widget(delete_form._token) }}
但是,我认为你可以更好地制作一系列表格并完全呈现每一种形式:
在您的控制器中:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$rep= $em->getRepository('IntranetServicesBundle:Laender')
->createQueryBuilder('l');
var_dump($rep->getQuery()->getDql());
$entities=$rep->getQuery()->getResult();
$delete_forms = array_map(
function($element){
return $this->createDeleteForm($element->getId());}
,$entities->toArray()
);
return $this->render('IntranetServicesBundle:Laender:index.html.twig'
, array(
'entities' => $entities,
'delete_forms' => $delete_forms
));
}
private function createDeleteForms($id)
{
return $this->createFormBuilder(array('id' => $id)))
->add('id', 'hidden')
->getForm()
;
}
public function deleteAction(Request $request, $id)
{
$form = $this->createDeleteForm($id);
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('IntranetServicesBundle:Laender')
->find($id);
// this line might need to be changed to point to the proper repository
if (!$entity) {
throw $this->createNotFoundException('Unable to find Laender entity.');
}
$em->remove($entity);
$em->flush();
}
return $this->redirect($this->generateUrl('laender_index'));
// this line might need to be changed to point to the proper
// post-delete route
}
在你的树枝上做一些事情:
{% for form in delete_forms %}{{form_widget(form)}}{% endfor %}
答案 1 :(得分:3)
@Lighthart的回答让我得到了正确答案:
在你的控制器中生成一个表单视图数组并将其交给视图:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('AppBundle:Entity')->findAll();
$delete_forms = array_map(
function ($element) {
return $this->createDeleteForm($element->getId())->createView();
}
, $entities
);
return $this->render('AppBundle:Entity:index.html.twig', array(
'entities' => $entities,
'delete_forms' => $delete_forms
));
}
现在您必须在视图中访问它。因此,您可以使用表单函数和特殊循环变量:
{% extends '::base.html.twig' %}
{% block body %}
{% for entity in entities %}
{# Access the delete form for this entity using the loop index ... #}
{% set delete_form = delete_forms[loop.index0] %}
{# ... and display the form using the form tags. #}
{{ form_start(delete_form) }}
<input type="submit" value="Delete" />
{{ form_end(delete_form) }}
{% endfor %}
{% endblock %}
那就是它。
答案 2 :(得分:0)
我遇到了类似的情况,我想在使用csrf保护时删除产品。我还想使用 ajax 来发出DELETE请求。
所以,要做到这一点,我的查看, index.html 就是这样:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let inner = UIView()
inner.backgroundColor = .yellow
inner.translatesAutoresizingMaskIntoConstraints = false
let outer = UIView()
outer.backgroundColor = .blue
outer.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(outer)
view.addSubview(inner)
// get these from somewhere, e.g. outerWidth.frame.size
let outerWidth = CGFloat(200)
let outerHeight = CGFloat(400)
let outerAnchor: NSLayoutDimension
if outerWidth >= outerHeight {
outerAnchor = outer.heightAnchor
} else {
outerAnchor = outer.widthAnchor
}
let imageScale = CGFloat(0.5)
NSLayoutConstraint.activate([
outer.widthAnchor.constraint(equalToConstant: outerWidth),
outer.heightAnchor.constraint(equalToConstant: outerHeight),
outer.centerXAnchor.constraint(equalTo: view.centerXAnchor),
outer.centerYAnchor.constraint(equalTo: view.centerYAnchor),
inner.centerXAnchor.constraint(equalTo: outer.centerXAnchor),
inner.centerYAnchor.constraint(equalTo: outer.centerYAnchor),
inner.widthAnchor.constraint(equalTo: outerAnchor, multiplier: imageScale),
inner.heightAnchor.constraint(equalTo: inner.widthAnchor)
])
}
}
如上所示, // html for displaying a products table with delete btn for each row
// ...
// Retrieve csrf token and store it somewhere in DOM (preferably outside table),
// We do this so that we can send the token via ajax later
<span id="csrf_token" data-token="{{ csrf_token('form') }}"></span>
<script>
// Make an ajax request on the on-click handler of our delete btn
$.ajax({
url: localhost/admin/product/4545, // generated dynamically, the last segment being the ID of the item to be deleted.
type: 'POST',
data: {
"_method": "DELETE",
"form[_token]": $("#csrf_token").data("token") // passed csrf token here
},
success: function(result) {
// Do something with the result
}
});
</script>
实际上是在树枝内部为您提供 csrf令牌。
我的控制器:
{{ csrf_token('form') }}
这应该按预期删除所需的行!
答案 3 :(得分:0)
@Phidelux 的回答让我找到了以下解决方案:
在树枝中我创建了删除表单:
<form method="post" action="{{ path('page_delete', {'id': page.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ page.id) }}">
<button type="submit" class="btn btn-icon">
<i class="far fa-trash-alt"></i>
</button>
</form>
创建列表视图的代码是:
/**
* @Route("/", name="page-list", methods={"GET"})
*/
public function index(PageRepository $pageRepository): Response
{
$pages = $pageRepository->findAll();
$delete_forms = array_map(
function ($element) {
return $this->render('admin/page/_delete_form.html.twig', [
'page' => $element,
]);
}
, $pages
);
return $this->render('admin/page/index.html.twig', [
'pages' => $pages,
'delete_forms' => $delete_forms
]);
}
然后在我的列表视图中我添加了删除按钮:
{% for key, page in pages %}
...
{{ delete_forms[key].content | raw }}
{% endfor %}
在我的编辑页面表单中,我可以使用:
{{ include('admin/sjabloon/_delete_form.html.twig') }}
解决了删除时不允许消息的方法