在Symfony 1.4的管理生成器中创建一个新的删除对象操作。

3

我正在使用Symfony 1.4/Doctrine的管理生成器。

有一个问题列表,我想能够在每个问题上执行自定义的object_action。

我想要模仿_delete对象操作,但在此之前进行一些计算。

所以我创建了一个新的操作:

  public function executeListDeleteAndRecalculate(sfWebrequest $request)
  {
    // Do the calculation

    // Then delete the question
  }

我将它添加到我的generator.yml文件中:

object_actions:
    delete_and_recalculate: ~

新的操作在管理生成器中显示,但删除部分不起作用。
我尝试了很多方法让它工作:
一旦所有计算都完成,我首先尝试重定向到`questionActions/delete`操作。
我还尝试将`executeDelete`代码复制到我的新操作中。
但每次我都会得到臭名昭著的
500 | 内部服务器错误 | sfValidatorErrorSchema _csrf_token [必填。]
所以我猜想Symfony在实际删除对象之前会做一些魔法。
您知道我缺少什么和实现一个deleteAndRecalculate类型的操作的最佳方法吗?
编辑:
当然,如果我删除`$request->checkCSRFProtection();`,一切都可以正常工作。但我认为这非常重要,所以我希望找到一个更好的解决方案。
1个回答

4
这是因为管理生成器中的“删除”链接使用令牌来防止 CSRF 攻击。
基本上,它会将一个令牌设置到您的会话和一个表单的隐藏字段中,然后在请求时相互检查。这是可能的,因为管理生成器中的“删除”链接实际上是一个(javascript 生成的)表单(这样做是为了添加一个sf_method隐藏字段来模拟 REST 行为)。
有关 CSRF 的工作原理以及如何预防的更多信息,请阅读维基百科:http://en.wikipedia.org/wiki/Cross-site_request_forgery 你可以做的是使用同样类型的链接,你只需要给link_to传递一个method参数以生成一个表单,看一下lib/generator/sfModelGeneratorHelper.class.php第32行,以了解在 admin-gen 中是如何完成的。
然后,您将在executeDeleteAndRecalculate方法中执行$request->checkCSRFProtection(),并继续进行您想做的任何操作,包括手动删除对象。
要正确生成链接,您需要在您的模块 Helper 类中添加一个linkToDeleteAndRecalculate方法(应该位于您的模块目录中的lib/${YourModule}GeneratorHelper.class.php文件中),并添加以下代码(直接从sfModelGeneratorHelper中获取并调整):
public function linkToDeleteAndRecalculate($object, $params)
{
  if ($object->isNew())
  {
    return '';
  }

  return '<li class="sf_admin_action_delete">'.link_to(__($params['label'], array(), 'sf_admin'), 'delete_and_recalculate', $object, array('method' => 'delete', 'confirm' => !empty($params['confirm']) ? __($params['confirm'], array(), 'sf_admin') : $params['confirm'])).'</li>';
}

请注意,您需要更改路由(默认情况下我已经放置了delete_and_recalculate,但您可能希望在其前缀中加入您的模块名称),从link_to调用中进行更改。
然后,您几乎可以像使用内置方法一样使用您的delete_and_recalculate,并传递一个来自generator.yml的标签。
现在这是较为困难的方式。
简单的方法是订阅admin.delete_object事件,例如从您的模块的预执行中,并在那里完成您的工作 :-)

感谢您的回答。但是,即使我尝试复制linkToDelete创建链接的方式,我也无法生成创建表单的onclick JavaScript事件。而且我也找不到在_delete对象操作中执行此操作的位置。关于“简单的方法”:我认为这种方法行不通,因为我还想保留默认的“删除”操作。 - Guillaume Flandre
好的,我已经编辑了我的答案,并提供了生成链接的说明,这样有帮助吗? - Geoffrey Bachelet
我快要完成了,一切似乎都没问题,直到我点击链接。我不知道我在backend/config/routing.yml中写的路由有什么问题(请参见此处:http://pastie.org/798862)。但是我收到了404“操作”supprimer_et_recalculer / 33“不存在。” - Guillaume Flandre
你的routing.yml文件中是否仍有默认的 /:module/:action 路由?如果是,并且它在你自定义路由之前,那么Symfony会优先匹配它。如果没有,默认的路由不在,完整的跟踪信息可能会有所帮助,当然还有你完整的routing.yml文件 :-) - Geoffrey Bachelet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接