El redireccionamiento de formularios no funciona si 'destino' está en la URL

20

En uno de mis formularios, estoy tratando de establecer un $form_state['redirect']formulario para que el formulario vaya a ese destino después de que el usuario haga clic en uno de los botones de acción.

Si inspecciono $form_state['redirect']antes y después de agregar la redirección, es NULL antes y después contiene la matriz adecuada. Así es como estoy configurando la redirección:

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

Quiero preservar el destino del formulario que el usuario está viendo a la siguiente ruta (es por eso que estoy llamando drupal_get_destination(), que devuelve una matriz con el 'destination' => 'some/path/here'interior.

Parece que, debido a que ya hay un destino en la ruta del formulario actual, el formulario se redirige a ese destino sin importar lo que coloque en mi propio controlador de envío de formulario (consulte el código anterior). Incluso intenté usar drupal_goto () y eso tampoco redirigió al usuario.

geerlingguy
fuente

Respuestas:

27

Cuando se procesa un formulario, el valor de $form_state['redirect']se envía a drupal_goto(), y drupal_goto()siempre favorece $_GET['destination']a su propio $pathparámetro.

En aras de la exhaustividad, en Drupal 6, no tuvo suerte sin configurar sus propios encabezados en hook_exit():

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

En Drupal 7, hook_drupal_goto_alter()se agregó para este caso de uso específico:

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

Otra opción para Drupal 7, que está más cerca de lo que desea hacer, es restablecer el caché estático drupal_get_destination() en su controlador de envío usando 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();
}

Como llama drupal_get_destination()inmediatamente después del reinicio, Drupal desconoce felizmente el parámetro de destino para el resto de la construcción de la página, incluso cuando llama drupal_goto().

Nota: Cambié el código para definirlo $form_state['redirect']porque nunca desea sobrescribir la variable: otros controladores de envío pueden haber definido sus propios redireccionamientos. Drupal siempre usará el último elemento de la matriz, por lo que si desea foo/baranular el parámetro de destino (y cualquier otra redirección definida hasta ese punto), debe ser el último.


fuente
Perfecto, y muy buena explicación. De hecho, encontré un poco más trabajando a través del flujo de un formulario procesado: drupal_goto () es, en última instancia, la razón por la que mi simple 'redirección' no estaba funcionando. También necesitaba sobrescribir $ _GET ['destino'].
geerlingguy
Gracias! Esto es realmente muy clarificador.
zilverdistel
4

Gracias por esto, pero por alguna razón esto no funcionó cuando lo probé. Recibí un error fatal: los datos enviados en la respuesta de ejemplo anterior no satisfacen los requisitos dedrupal_goto()

Puede ser porque esta respuesta es bastante antigua, pero pude hacer que funcione con esto:

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

}

Sé que esto viola esta nota:

nunca desea sobrescribir la variable: otros controladores de envío pueden haber definido sus propios redireccionamientos.

Pero, en este caso, definitivamente desea sobrescribir la variable. No establecería este valor a menos que quisiera ignorar los valores establecidos de otro módulo. Además, creo que debe hacerlo debido a la forma en que drupal_goto()funciona con el parámetro de consulta. Esta también puede ser la razón por la cual la respuesta original arrojó errores fatales en mi sitio.

tmsimont
fuente
Esta respuesta me ayudó a darme cuenta de que, en algunas circunstancias, es posible que desee anular por completo el $form_state['redirect'], o puede obtener un WSOD con redireccionamientos competitivos.
tyler.frankenstein
-2

establecer formulario # acción

global $base_path;
$form['#action'] = $base_path . '/node/'.$form_state['node']->nid.'/mytab';
rémy
fuente
-1 pienso llamar drupal_goto()en hook_node_insert()lo enredar las cosas (porque drupal_goto()las llamadas drupal_exit()evitando que el nuevo nodo se guarden).
Andy
verdadero - en un gancho node_insert .. (editó la respuesta)
rémy
1
Esto no emite una redirección como OP solicitó, pero envía el formulario a una ruta diferente.
Andy