Перенаправлення форми не працює, якщо в 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 (), і це не перенаправляло користувача.

Відповіді:


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 ['призначення'].
geerlingguy

Дякую! Це дійсно дуже з’ясовує.
zilverdistel

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()працює з параметром запиту. Це також може бути причиною того, що оригінальна відповідь кинула фатальні помилки на моєму сайті.


Ця відповідь допомогла мені зрозуміти, що в деяких обставинах ви можете повністю змінити $form_state['redirect']або ви можете отримати WSOD з конкуруючими переадресаціями.
tyler.frankenstein

-2

встановити форму # діяння

global $base_path;
$form['#action'] = $base_path . '/node/'.$form_state['node']->nid.'/mytab';

-1 Я думаю, що при вході drupal_goto()в дію hook_node_insert()накрутять справи (адже drupal_goto()дзвінки, що drupal_exit()перешкоджають збереженню нового вузла).
Енді

true - у node_insert гачок .. (відредаговано відповідь)
rémy

1
Це не видає переспрямування, як запитував ОП, але подає форму в інший шлях.
Енді
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.