Chuyển hướng biểu mẫu không hoạt động nếu 'đích' nằm trong URL


20

Trong một trong các biểu mẫu của tôi, tôi đang cố gắng đặt $form_state['redirect']biểu mẫu để biểu mẫu sẽ đi đến đích đó sau khi người dùng nhấp vào một trong các nút hành động.

Nếu tôi kiểm tra $form_state['redirect']cả trước và sau khi tôi thêm chuyển hướng, thì đó là NULL trước và sau chứa mảng thích hợp. Đây là cách tôi thiết lập chuyển hướng:

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

Tôi muốn duy trì đích đến từ hình thức mà người dùng đang xem đến đường dẫn tiếp theo (đó là lý do tại sao tôi đang gọi drupal_get_destination(), trả về một mảng với 'destination' => 'some/path/here'bên trong.

Dường như, vì đã có một điểm đến trong đường dẫn của biểu mẫu hiện tại, biểu mẫu chuyển hướng đến đích đó bất kể tôi đặt gì trong trình xử lý biểu mẫu của riêng mình (xem mã ở trên). Tôi thậm chí đã thử sử dụng drupal_goto () và điều đó cũng không chuyển hướng người dùng.

Câu trả lời:


27

Khi một biểu mẫu được xử lý, giá trị của $form_state['redirect']được gửi đến drupal_goto()drupal_goto()luôn ưu tiên cho tham số $_GET['destination']của chính nó $path.

Để hoàn thiện, trong Drupal 6, bạn đã phần nào gặp may mà không đặt tiêu đề của riêng mình vào hook_exit():

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

Trong Drupal 7, hook_drupal_goto_alter()đã được thêm vào cho trường hợp sử dụng cụ thể này:

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

Một tùy chọn khác cho Drupal 7, gần với những gì bạn muốn làm, là đặt lại bộ đệm tĩnh cho drupal_get_destination() trình xử lý trình của bạn bằng cách sử dụng 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();
}

Vì bạn gọi drupal_get_destination()ngay sau khi thiết lập lại, Drupal hoàn toàn không biết về tham số đích cho phần còn lại của quá trình xây dựng trang, kể cả khi nó gọi drupal_goto().

Lưu ý: Tôi đã thay đổi mã để xác định $form_state['redirect']vì bạn không bao giờ muốn ghi đè lên biến: trình xử lý trình khác có thể đã xác định chuyển hướng của riêng họ. Drupal sẽ luôn sử dụng mục cuối cùng trong mảng, vì vậy nếu bạn muốn foo/barghi đè tham số đích (và mọi chuyển hướng khác được xác định cho đến thời điểm đó), thì nó cần phải là cuối cùng.


Hoàn hảo, và giải thích rất tốt. Tôi thực sự đã tìm thấy nhiều hơn một chút bằng cách xử lý dòng chảy của một hình thức được xử lý - drupal_goto () cuối cùng là lý do 'chuyển hướng' đơn giản của tôi không hoạt động. Tôi cũng cần ghi đè $ _GET ['đích'].
ge Muffguy

Thanx! Điều này thực sự rất rõ ràng.
zilverdistel

4

Cảm ơn vì điều này, nhưng vì một số lý do, nó không hoạt động khi tôi thử nó. Tôi đã gặp một lỗi nghiêm trọng - dữ liệu được gửi trong câu trả lời ví dụ ở trên không thỏa mãn các yêu cầu củadrupal_goto()

Có thể là do câu trả lời này khá cũ, nhưng tôi đã có thể khiến nó hoạt động với điều này thay vào đó:

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

}

Tôi biết điều này vi phạm lưu ý này:

bạn không bao giờ muốn ghi đè lên biến: các trình xử lý trình khác có thể đã xác định các chuyển hướng riêng của chúng.

Nhưng, trong trường hợp này, bạn chắc chắn muốn ghi đè lên biến. Bạn sẽ không đặt giá trị này trừ khi bạn muốn bỏ qua các giá trị được đặt của mô-đun khác. Ngoài ra, tôi nghĩ rằng bạn phải vì cách drupal_goto()làm việc với tham số truy vấn. Đây cũng có thể là lý do tại sao câu trả lời ban đầu đã gây ra lỗi nghiêm trọng trên trang web của tôi.


Câu trả lời này đã giúp tôi nhận ra rằng trong một số trường hợp, bạn có thể muốn ghi đè hoàn toàn $form_state['redirect']hoặc bạn có thể nhận được WSOD với các chuyển hướng cạnh tranh.
tyler.frankenstein

-2

thiết lập biểu mẫu #action

global $base_path;
$form['#action'] = $base_path . '/node/'.$form_state['node']->nid.'/mytab';

-1 Tôi nghĩ rằng việc gọi drupal_goto()vào hook_node_insert()sẽ làm hỏng mọi thứ (vì drupal_goto()các cuộc gọi drupal_exit()ngăn nút mới được lưu).
Andy

đúng - trong một hook_insert hook .. (đã chỉnh sửa câu trả lời)
rémy

1
Điều này không phát sinh chuyển hướng như OP yêu cầu, nhưng gửi biểu mẫu đến một đường dẫn khác.
Andy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.