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();一切正常。但我认为这很重要,所以我想找到一个更漂亮的解决方案。

4

1 回答 1

4

这是因为delete来自管理生成器的链接使用令牌来防止 CSRF 攻击。

基本上,它会在您的会话和表单的隐藏字段中设置一个令牌,然后根据请求将它们与另一个进行检查。这是可能的,因为delete管理生成器中的链接实际上是一个(javascript 生成的)表单(这样做是为了添加一个sf_method隐藏字段来模拟 REST 行为)。

有关 CSRF 如何工作和如何预防的更多信息,您可以在 Wikipedia 上进一步阅读:http ://en.wikipedia.org/wiki/Cross-site_request_forgery

你可以做的是使用相同类型的链接,你只需要传递一个method参数来link_to生成一个表单,看看lib/generator/sfModelGeneratorHelper.class.php第 32 行,看看它是如何在 admin-gen 中完成的。

然后,您将$request->checkCSRFProtection()在您的executeDeleteAndRecalculate方法中执行,并继续您想做的任何事情,包括手动删除对象。

要正确生成链接,您将linkToDeleteAndRecalculate在模块的 Helper 类中添加一个方法(该方法应位于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事件,例如从模块的预执行,以及在那里的工作:-)

于 2010-01-28T13:48:25.873 回答