Переадресация формы не работает, если «назначение» находится в URL

20

В одной из моих форм я пытаюсь установить, $form_state['redirect']чтобы форма отправлялась в это место после того, как пользователь нажимает одну из кнопок действий.

Если я проверяю $form_state['redirect']как до, так и после добавления перенаправления, он равен NULL до и после и содержит правильный массив. Вот как я настраиваю перенаправление:

$form_state['redirect'] = array(
  'my/custom/path/' . $nid,
  array('query' => drupal_get_destination()),
);

Я хочу сохранить пункт назначения от формы, которую пользователь просматривает, до следующего пути (вот почему я звоню drupal_get_destination(), который возвращает массив с 'destination' => 'some/path/here'внутренней частью.

Кажется, что, поскольку в пути текущей формы уже есть место назначения, форма перенаправляется к этому месту назначения независимо от того, что я поместил в свой собственный обработчик отправки формы (см. Код выше). Я даже пытался использовать drupal_goto (), и это также не перенаправило пользователя.

geerlingguy
источник

Ответы:

27

Когда форма обрабатывается, значение $form_state['redirect']отправляется drupal_goto()и drupal_goto()всегда имеет преимущество $_GET['destination']перед своим собственным $pathпараметром.

Ради полноты, в Drupal 6 вам не повезло, если вы не установили свои собственные заголовки в hook_exit():

function mymodule_exit($destination = NULL) {
  $my_destination = 'foo/bar';
  header('Location: ' . url($my_destination));
  exit;
}

В Drupal 7 hook_drupal_goto_alter()был добавлен для этого конкретного случая использования:

function mymodule_drupal_goto_alter(&$path, &$options, &$http_response_code) {
  $path = 'foo/bar';
}

Другой вариант для Drupal 7, который ближе к тому, что вы хотите сделать, - сбросить статический кеш для drupal_get_destination() вашего обработчика отправки с помощью drupal_static_reset():

function mymodule_form_submit($form, &$form_state) {
  // See note
  $form_state['redirect'][] = drupal_get_destination();
  $form_state['redirect'][] = 'foo/bar';

  unset($_GET['destination']);
  drupal_static_reset('drupal_get_destination');
  drupal_get_destination();
}

Поскольку вы вызываете drupal_get_destination()сразу после сброса, Drupal, к счастью, не знает о параметре адресата для остальной части сборки страницы, в том числе при вызове drupal_goto().

Примечание: я изменил код определения, $form_state['redirect']потому что вы никогда не хотите перезаписывать переменную: другие обработчики отправки могли определить свои собственные перенаправления. Drupal всегда будет использовать последний элемент в массиве, поэтому, если вы хотите foo/barпереопределить целевой параметр (и все остальные перенаправления, определенные до этого момента), он должен быть последним.


источник
Идеальное и очень хорошее объяснение. На самом деле я обнаружил немного больше, работая в потоке обработанной формы - drupal_goto (), в конечном счете, и была причиной того, что мое простое «перенаправление» не сработало. Мне также нужно было перезаписать $ _GET ['destination'].
geerlingguy
Thanx! Это действительно очень разъясняет.
Зилвердистел
4

Спасибо за это, но по какой-то причине это не сработало, когда я попробовал. Я получил фатальную ошибку - данные, отправленные в приведенном выше примере ответа, не удовлетворяют требованиямdrupal_goto()

Это может быть потому, что этот ответ довольно старый, но я смог заставить его работать с этим:

function mymodule_form_submit($form, &$form_state) {


  $form_state['redirect'] = array(
    'foo/bar', array(
      'query' => drupal_get_destination()
    )
  );

  unset($_GET['destination']);
  drupal_static_reset('drupal_get_destination');
  drupal_get_destination();

}

Я знаю, что это нарушает эту заметку:

Вы никогда не захотите перезаписать переменную: другие обработчики отправки могли определить свои собственные перенаправления.

Но в этом случае вы определенно хотите перезаписать переменную. Вы не будете устанавливать это значение, если не хотите игнорировать установленные значения другого модуля. Кроме того, я думаю, что вы должны из-за способа drupal_goto()работы с параметром запроса. Это также может быть причиной того, что первоначальный ответ приводил к фатальным ошибкам на моем сайте.

tmsimont
источник
Этот ответ помог мне понять, что в некоторых случаях вы можете полностью переопределить $form_state['redirect']или получить WSOD с конкурирующими перенаправлениями.
tyler.frankenstein
-2

установить форму #action

global $base_path;
$form['#action'] = $base_path . '/node/'.$form_state['node']->nid.'/mytab';
rémy
источник
-1 Я думаю , вызывая drupal_goto()в hook_node_insert()ввернут вещи (потому что drupal_goto()вызовы drupal_exit()предотвращения нового узла могут быть не сохранены).
Энди
true - в хуке node_insert .. (отредактировал ответ)
rémy
1
Это не вызывает перенаправления по запросу OP, но отправляет форму по другому пути.
Энди