「宛先」がURLにある場合、フォームリダイレクトが機能しない


20

フォームの1つで$form_state['redirect']、ユーザーがアクションボタンの1つをクリックした後、フォームがその宛先に移動するように設定しようとしています。

$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のもう1つのオプションは、目的に近いもので、次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

ありがとう!これは確かに非常に明確です。
-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

設定フォーム#action

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

-1呼び出しdrupal_goto()hook_node_insert()行うと事態が台無しになると思います(drupal_goto()呼び出しdrupal_exit()が新しいノードの保存を妨げるため)。
アンディ14

真- node_insertフックで...(答えを編集した)
レミー

1
これは、OPが要求したようにリダイレクトを発行しませんが、別のパスにフォームを送信します。
アンディ14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.