La redirection de formulaire ne fonctionne pas si la «destination» est dans l'URL

20

Dans l'un de mes formulaires, j'essaie de définir un $form_state['redirect']afin que le formulaire accède à cette destination après que l'utilisateur a cliqué sur l'un des boutons d'action.

Si j'inspecte $form_state['redirect']avant et après avoir ajouté la redirection, elle est NULL avant et après contient le tableau approprié. Voici comment je configure la redirection:

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

Je veux conserver la destination du formulaire que l'utilisateur visualise au chemin suivant (c'est pourquoi j'appelle drupal_get_destination(), ce qui retourne un tableau avec l' 'destination' => 'some/path/here'intérieur.

Il semble que, comme il existe déjà une destination dans le chemin du formulaire actuel, le formulaire redirige vers cette destination, peu importe ce que je mets dans mon propre gestionnaire de soumission de formulaire (voir le code ci-dessus). J'ai même essayé d'utiliser drupal_goto () et cela n'a pas redirigé l'utilisateur non plus.

geerlingguy
la source

Réponses:

27

Lorsqu'un formulaire est traité, la valeur de $form_state['redirect']est envoyée à drupal_goto()et drupal_goto()privilégie toujours $_GET['destination']son propre $pathparamètre.

Par souci d'exhaustivité, dans Drupal 6, vous n'avez pas eu de chance sans définir vos propres en-têtes dans hook_exit():

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

Dans Drupal 7, a hook_drupal_goto_alter()été ajouté pour ce cas d'utilisation spécifique:

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

Une autre option pour Drupal 7, qui est plus proche de ce que vous voulez faire, est de réinitialiser le cache statique drupal_get_destination() dans votre gestionnaire de soumission en utilisant 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();
}

Puisque vous appelez drupal_get_destination()immédiatement après la réinitialisation, Drupal ignore parfaitement le paramètre de destination pour le reste de la création de page, y compris lorsqu'il appelle drupal_goto().

Remarque: J'ai changé le code de définition $form_state['redirect']parce que vous ne voulez jamais écraser la variable: d'autres gestionnaires de soumission ont peut-être défini leurs propres redirections. Drupal utilisera toujours le dernier élément du tableau, donc si vous souhaitez foo/barremplacer le paramètre de destination (et toutes les autres redirections définies jusqu'à ce point), il doit être le dernier.


la source
Parfait et très bonne explication. En fait, j'ai trouvé un peu plus en travaillant à travers le flux d'un formulaire traité - drupal_goto () est finalement la raison pour laquelle ma simple `` redirection '' ne fonctionnait pas. J'avais aussi besoin d'écraser $ _GET ['destination'].
geerlingguy
Merci! C'est en effet très clarifiant.
zilverdistel
4

Merci pour cela, mais pour une raison quelconque, cela n'a pas fonctionné lorsque je l'ai essayé. J'ai eu une erreur fatale - les données envoyées dans l'exemple de réponse ci-dessus ne répondent pas aux exigences dedrupal_goto()

C'est peut-être parce que cette réponse est plutôt ancienne, mais j'ai pu le faire fonctionner avec ceci à la place:

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

}

Je sais que cela viole cette note:

vous ne voulez jamais écraser la variable: d'autres gestionnaires de soumission peuvent avoir défini leurs propres redirections.

Mais, dans ce cas, vous voulez vraiment écraser la variable. Vous ne définiriez pas cette valeur à moins que vous ne vouliez ignorer les valeurs définies d'autres modules. En outre, je pense que vous devez le faire en raison de la façon dont drupal_goto()fonctionne le paramètre de requête. C'est peut-être aussi la raison pour laquelle la réponse originale lançait des erreurs fatales sur mon site.

tmsimont
la source
Cette réponse m'a aidé à réaliser que dans certaines circonstances, vous pouvez vouloir remplacer complètement le $form_state['redirect'], ou vous pouvez obtenir un WSOD avec des redirections concurrentes.
tyler.frankenstein
-2

définir le formulaire #action

global $base_path;
$form['#action'] = $base_path . '/node/'.$form_state['node']->nid.'/mytab';
rémy
la source
-1 Je pense appeler drupal_goto()à hook_node_insert()visserez les choses (parce que les drupal_goto()appels drupal_exit()empêchant le nouveau noeud d'être sauvé).
Andy
true - dans un hook node_insert .. (édité la réponse)
rémy
1
Cela n'émet pas de redirection comme l'OP l'a demandé, mais soumet le formulaire à un chemin différent.
Andy