O redirecionamento de formulário não funcionará se "destino" estiver no URL

20

Em um dos meus formulários, estou tentando definir um $form_state['redirect']para que o formulário vá para esse destino depois que o usuário clicar em um dos botões de ação.

Se eu inspecionar $form_state['redirect']antes e depois de adicionar o redirecionamento, é NULL antes e depois contém a matriz adequada. Veja como estou configurando o redirecionamento:

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

Quero preservar o destino do formulário que o usuário está visualizando para o próximo caminho (é por isso que estou ligando drupal_get_destination(), que retorna uma matriz com o 'destination' => 'some/path/here'interior.

Parece que, como já existe um destino no caminho do formulário atual, o formulário é redirecionado para esse destino, independentemente do que eu coloquei no meu próprio manipulador de envio de formulários (veja o código acima). Eu até tentei usar drupal_goto () e isso também não redirecionou o usuário.

geerlingguy
fonte

Respostas:

27

Quando um formulário é processado, o valor de $form_state['redirect']é enviado para drupal_goto()e drupal_goto()sempre favorece $_GET['destination']seu próprio $pathparâmetro.

Por uma questão de completude, no Drupal 6, você estava um pouco sem sorte sem definir seus próprios cabeçalhos em hook_exit():

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

No Drupal 7, hook_drupal_goto_alter()foi adicionado para este caso de uso específico:

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

Outra opção para o Drupal 7, mais próxima do que você deseja fazer, é redefinir o cache estático drupal_get_destination() no manipulador de envio 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 você liga drupal_get_destination()imediatamente após a redefinição, o Drupal desconfia alegremente do parâmetro de destino para o restante da criação da página, inclusive quando ele chama drupal_goto().

Nota: Alterei o código para definição $form_state['redirect']porque você nunca deseja substituir a variável: outros manipuladores de envio podem ter definido seus próprios redirecionamentos. O Drupal sempre usará o último item da matriz, portanto, se você deseja foo/barsubstituir o parâmetro de destino (e todos os outros redirecionamentos definidos até esse ponto), ele precisa ser o último.


fonte
Explicação perfeita e muito boa. Na verdade, descobri um pouco mais trabalhando no fluxo de um formulário processado - drupal_goto () é o motivo pelo qual meu simples 'redirecionamento' não estava funcionando. Eu também precisava sobrescrever $ _GET ['destination'].
geerlingguy
Thanx! Isso é realmente muito esclarecedor.
Zilverdistel
4

Obrigado por isso, mas por algum motivo isso não funcionou quando eu tentei. Eu recebi um erro fatal - os dados enviados na resposta de exemplo acima não atendem aos requisitos dedrupal_goto()

Pode ser porque essa resposta é bastante antiga, mas eu consegui fazê-la funcionar com isso:

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

}

Eu sei que isso viola esta nota:

você nunca deseja sobrescrever a variável: outros manipuladores de envio podem ter definido seus próprios redirecionamentos.

Mas, nesse caso, você definitivamente deseja substituir a variável. Você não definiria esse valor a menos que desejasse desconsiderar os valores definidos de outros módulos. Além disso, acho que você deve fazê-lo por causa da maneira como drupal_goto()funciona com o parâmetro de consulta. Também pode ser por isso que a resposta original estava lançando erros fatais no meu site.

tmsimont
fonte
Esta resposta me ajudou a perceber que, em algumas circunstâncias, você pode substituir completamente o $form_state['redirect']ou pode obter um WSOD com redirecionamentos concorrentes.
tyler.frankenstein
-2

definir formulário #action

global $base_path;
$form['#action'] = $base_path . '/node/'.$form_state['node']->nid.'/mytab';
rémy
fonte
-1 Eu acho que chamar drupal_goto()em hook_node_insert()vão estragar tudo (porque drupal_goto()chamadas drupal_exit()impedindo o novo nó de ser salvo).
22414 Andy
verdadeiro - em um gancho node_insert .. (editado a resposta)
rémy
11
Isso não emite um redirecionamento conforme solicitado pelo OP, mas envia o formulário para um caminho diferente.
Andy