การเปลี่ยนเส้นทางแบบฟอร์มไม่ทำงานหาก 'ปลายทาง' อยู่ใน URL


20

ในหนึ่งในแบบฟอร์มของฉันฉันกำลังพยายามตั้งค่า$form_state['redirect']เพื่อให้แบบฟอร์มไปยังปลายทางนั้นหลังจากที่ผู้ใช้คลิกปุ่มการกระทำปุ่มใดปุ่มหนึ่ง

ถ้าฉันตรวจสอบ$form_state['redirect']ทั้งก่อนและหลังฉันเพิ่มการเปลี่ยนเส้นทางมันเป็นโมฆะก่อนและหลังมีอาร์เรย์ที่เหมาะสม นี่คือวิธีที่ฉันตั้งค่าการเปลี่ยนเส้นทาง:

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

ฉันต้องการสงวนปลายทางจากแบบฟอร์มที่ผู้ใช้กำลังดูไปยังเส้นทางถัดไป (นั่นคือเหตุผลที่ฉันกำลังโทรหาdrupal_get_destination()ซึ่งจะส่งกลับอาร์เรย์'destination' => 'some/path/here'ภายใน

ดูเหมือนว่าเนื่องจากมีปลายทางอยู่ในเส้นทางของฟอร์มปัจจุบันแล้วการเปลี่ยนเส้นทางไปยังปลายทางนั้นไม่ว่าสิ่งที่ฉันใส่ไว้ในแบบฟอร์มของฉันจะส่ง handler (ดูรหัสด้านบน) ฉันได้ลองใช้ drupal_goto () และนั่นก็ไม่ได้เปลี่ยนเส้นทางผู้ใช้

คำตอบ:


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 ['ปลายทาง'] ด้วย
geerlingguy

Thanx! นี่เป็นการชี้แจงที่ชัดเจนมาก
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

-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()ป้องกันโหนดใหม่จากการถูกบันทึกไว้)
Andy

จริง - ใน node_insert hook .. (แก้ไขคำตอบ)
rémy

1
นี่ไม่ใช่ปัญหาการเปลี่ยนเส้นทางตามที่ OP ขอ แต่ส่งแบบฟอร์มไปยังเส้นทางอื่น
Andy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.