Przekierowanie formularza nie działa, jeśli „miejsce docelowe” znajduje się w adresie URL

20

W jednym z moich formularzy próbuję ustawić $form_state['redirect']tak, aby formularz trafił do tego miejsca docelowego po kliknięciu przez użytkownika jednego z przycisków akcji.

Jeśli sprawdzę $form_state['redirect']zarówno przed, jak i po dodaniu przekierowania, ma on wartość NULL przed, a następnie zawiera odpowiednią tablicę. Oto jak konfiguruję przekierowanie:

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

Chcę zachować miejsce docelowe z formularza wyświetlanego przez użytkownika do następnej ścieżki (dlatego dzwonię drupal_get_destination(), która zwraca tablicę z 'destination' => 'some/path/here'wewnątrz.

Wygląda na to, że ponieważ w ścieżce bieżącego formularza znajduje się już miejsce docelowe, formularz przekierowuje do tego miejsca docelowego bez względu na to, co wstawiłem w module obsługi przesyłania formularza (patrz powyższy kod). Próbowałem nawet użyć drupal_goto () i to też nie przekierowało użytkownika.

geerlingguy
źródło

Odpowiedzi:

27

Podczas przetwarzania formularza wartość $form_state['redirect']jest wysyłana do drupal_goto()i drupal_goto()zawsze preferuje $_GET['destination']własny $pathparametr.

Dla kompletności, w Drupal 6 nie miałeś szczęścia, nie ustawiając własnych nagłówków hook_exit():

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

W Drupal 7 hook_drupal_goto_alter()dodano dla tego konkretnego przypadku użycia:

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

Inną opcją dla Drupala 7, która jest bliższa temu, co chcesz zrobić, jest zresetowanie statycznej pamięci podręcznej drupal_get_destination() w module obsługi przesyłania za pomocą 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();
}

Ponieważ dzwonisz drupal_get_destination()natychmiast po zresetowaniu, Drupal błogo nie zna parametru docelowego dla reszty kompilacji strony, w tym także wtedy, gdy dzwoni drupal_goto().

Uwaga: Zmieniłem kod definiowania, $form_state['redirect']ponieważ nigdy nie chcesz zastąpić zmiennej: inne procedury obsługi przesyłania mogły zdefiniować własne przekierowania. Drupal zawsze użyje ostatniego elementu w tablicy, więc jeśli chcesz foo/barprzesłonić parametr docelowy (i każde inne przekierowanie zdefiniowane do tego momentu), musi on być ostatni.


źródło
Idealne i bardzo dobre wytłumaczenie. Właściwie znalazłem trochę więcej, pracując nad przepływem przetworzonej formy - drupal_goto () jest ostatecznie przyczyną, dla której moje proste „przekierowanie” nie działało. Musiałem też zastąpić $ _GET ['destination'].
geerlingguy
Dzięki! To rzeczywiście bardzo wyjaśnia.
zilverdistel
4

Dzięki za to, ale z jakiegoś powodu to nie działało, kiedy próbowałem. Wystąpił błąd krytyczny - dane wysłane w powyższej przykładowej odpowiedzi nie spełniają wymagańdrupal_goto()

Może dlatego, że ta odpowiedź jest dość stara, ale zamiast tego mogłem ją uruchomić z tym:

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();

}

Wiem, że to narusza tę notatkę:

nigdy nie chcesz zastąpić zmiennej: inne procedury obsługi przesyłania mogły zdefiniować własne przekierowania.

Ale w tym przypadku zdecydowanie chcesz zastąpić zmienną. Nie ustawiałbyś tej wartości, chyba że chciałbyś zignorować ustawione wartości innego modułu. Myślę też, że musisz to zrobić ze względu na sposób drupal_goto()działania z parametrem zapytania. Może to być również powód, dla którego oryginalna odpowiedź powodowała fatalne błędy w mojej witrynie.

tmsimont
źródło
Ta odpowiedź pomogła mi uświadomić sobie, że w niektórych okolicznościach możesz chcieć całkowicie zastąpić $form_state['redirect']lub otrzymać WSOD z konkurującymi przekierowaniami.
tyler.frankenstein
-2

ustaw formularz #action

global $base_path;
$form['#action'] = $base_path . '/node/'.$form_state['node']->nid.'/mytab';
rem
źródło
-1 myślę, nazywając drupal_goto()w hook_node_insert()będzie przykręcić rzeczy (bo drupal_goto()rozmowy drupal_exit()zapobiegając nowy węzeł z zapisywane).
Andy,
true - w haczyku node_insert .. (zredagował odpowiedź)
rem
1
Nie powoduje to przekierowania, o które poprosił OP, ale przesyła formularz na inną ścieżkę.
Andy