Создайте новое действие удаления object_action в генераторе администратора Symfony 1.4.

Я использую генератор администратора Symfony 1.4/Doctrine.

Есть список вопросов, и я хотел бы иметь возможность выполнять собственное object_action для каждого из них.

То, что я ищу, - это имитировать действие объекта _delete, но перед этим выполнить некоторые вычисления.

Итак, я создал новое действие:

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

    // Then delete the question
  }

И я добавляю его в свой генератор.yml:

object_actions:
    delete_and_recalculate: ~

новое действие отображается в генераторе администратора, но часть удаления не работает.

Я пробовал кучу вещей, чтобы заставить его работать:

  • После того, как все расчеты были сделаны, я сначала попытался перенаправить на действие questionActions/delete.
  • Я также попытался скопировать код executeDelete в свое новое действие.

Но каждый раз, когда я получаю печально известный

500 | Внутренняя ошибка сервера | sfValidatorErrorSchema _csrf_token [Обязательно.]

Итак, я предполагаю, что Symfony творит магию, прежде чем фактически удалить объект.

Знаете ли вы, что я упустил и как лучше всего реализовать действие типа удаления и пересчета?

Изменить:

Конечно, если я удалю $request->checkCSRFProtection();, все будет работать нормально. Но я предполагаю, что это очень важно, поэтому я хотел бы найти более красивое решение.


person Guillaume Flandre    schedule 28.01.2010    source источник


Ответы (1)


Это связано с тем, что ссылка delete из генератора администратора использует токен для предотвращения атак CSRF.

По сути, он устанавливает токен в ваш сеанс и в скрытое поле формы, а затем проверяет их друг против друга по запросу. Это возможно, потому что ссылка delete в генераторе администратора на самом деле является формой (сгенерированной javascript) (это делается для добавления скрытого поля sf_method для имитации поведения REST).

Для получения дополнительной информации о том, как работает CSRF и как его можно предотвратить, вы можете прочитать далее в Википедии: 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, например, из предварительного выполнения вашего модуля, и на вашу работу там :-)

person Geoffrey Bachelet    schedule 28.01.2010
comment
Спасибо за Ваш ответ. Однако, даже если я попытаюсь скопировать способ, которым linkToDelete создает ссылку, я не смогу сгенерировать событие javascript onclick, которое создает форму. И я не могу найти, где это делается для действия _delete объекта. О простом способе: я не думаю, что это сработает, так как я также хочу сохранить действие «Удалить» по умолчанию. - person Guillaume Flandre; 28.01.2010
comment
Хорошо, я отредактировал свой ответ, указав, как создать ссылку, это поможет? - person Geoffrey Bachelet; 28.01.2010
comment
Я почти у цели, вроде бы все в порядке, пока я не нажму на ссылку. я не знаю, что не так с маршрутом, который я написал (см. здесь: pastie.org/798862) в бэкенде /config/routing.yml. Но я получаю 404 Действие supprimer_et_recalculer/33 не существует. - person Guillaume Flandre; 28.01.2010
comment
У вас есть маршрут по умолчанию /:module/:action все еще в файле routing.yml? Если да, и если он находится перед вашим пользовательским маршрутом, тогда symfony будет соответствовать ему в приоритете. Если нет, то полная трассировка может помочь, как и ваш полный файл routing.yml, я думаю :-) - person Geoffrey Bachelet; 28.01.2010