如果网址中有“目标”,则表单重定向不起作用


20

在我的一种表单中,我试图设置一个,$form_state['redirect']以便用户单击操作按钮之一后,表单将转到该目标。

如果$form_state['redirect']在添加重定向之前和之后都进行检查,则在包含正确的数组之前和之后均为NULL。这是我设置重定向的方法:

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

我想保留从用户查看的形式到下一个路径的目的地(这就是为什么我要调用drupal_get_destination(),它返回一个带有'destination' => 'some/path/here'inside 的数组的原因。

看来,由于当前表单的路径中已经有一个目标,因此无论我在自己的表单提交处理程序中放置了什么内容,该表单都会重定向到该目标(请参见上面的代码)。我什至尝试使用drupal_goto(),也没有重定向用户。

Answers:


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的另一个更接近您要执行的操作的选项是,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 2011年

谢谢!这确实非常清楚。
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 2015年

-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()阻止新的节点被保存)。
安迪

真-在一个node_insert钩..(编辑的回答)
雷米

1
这不会按照OP的要求发出重定向,而是将表单提交到其他路径。
安迪
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.