คู่มือ

Handling Ajax post requests with Symfony

การจัดการแบบฟอร์ม PHP และการเข้าถึงข้อมูลที่ตามมาจากอินพุตของผู้ใช้ถือเป็นหัวใจสำคัญของการเรียนรู้ PHP Symfony เพิ่มสถาปัตยกรรม Model-View-Controller (MVC) ที่มีส่วนประกอบที่นำมาใช้ซ้ำได้ โครงสร้างที่จัดระบบอย่างดี และแนวทางปฏิบัติที่ดีที่สุดให้กับกระบวนการพัฒนา ทำให้เป็นสภาพแวดล้อมทั่วไปสำหรับการจัดการอินพุตของผู้ใช้ Ajax ซึ่งเป็น เทคโนโลยีที่ช่วยให้มีเนื้อหาแบบไดนามิกบนหน้าเว็บ ช่วยให้ผู้ใช้สามารถดำเนินการต่างๆ บนหน้าได้โดยไม่ต้องเปลี่ยนหน้าหรือโหลดซ้ำ โดยประมวลผลข้อมูลในเบื้องหลัง ส่งคำขอไปยังเซิร์ฟเวอร์ และอัปเดตมุมมองหน้าตามการตอบสนอง รู้จักกันในชื่อ Javascript แบบอะซิงโครนัสฟังก์ชั่น Ajax มักใช้แทนรูปแบบ PHP เพื่อส่งข้อมูลอินพุตของผู้ใช้ไปยังเซิร์ฟเวอร์

คำถาม: การเพิ่มรายการลงในตะกร้าสินค้า

สมมติว่าเราต้องการเพิ่มรายการลงในตะกร้าสินค้า ผลมาจากการป้อนข้อมูลของผู้ใช้ เรามีชุดของรายการที่มี IDและปริมาณ คู่ของ (id, ปริมาณ) เป็นข้อมูลที่เราส่งแบบอะซิงโครนัสไปยังเซิร์ฟเวอร์ เทคโนโลยีที่เราเลือกใช้เป็นไลบรารี Javascript ที่นิยมใช้กันทั่วไปที่เรียกว่า axios ซึ่งมาพร้อมกับอินเทอร์เฟซสำหรับส่งคำขอโพสต์ไปยัง URL ที่กำหนดโดยมีข้อมูลอยู่ในเนื้อหาคำขอ เหตุผลที่อยู่เบื้องหลังตัวเลือกนั้นคือการรวมเข้ากับสภาพแวดล้อมของ VueJS หรือ ReactJSได้ง่าย

การเรียกฟังก์ชั่น

axios.post(url, payload)

ส่งคำขอ HTTP POST แบบอะซิงโครนัสไปยังเส้นทางของตัวแปร url พร้อมข้อมูลที่เก็บไว้ในตัวแปร payload

ตัวควบคุม Symfony ที่จัดการเส้นทางนั้นเรียกว่า addItems

use Symfony\Component\HttpFoundation\Request;
public function addItems (Request $request) {

    // process data here, for example:
    $quantity = $request->request->get('quantity');

}

โดยปกติ เมื่อประมวลผลข้อมูลฟอร์ม PHP ค่าของฟิลด์ฟอร์มจะสามารถเข้าถึงได้ผ่านตัวแปร $_POST ซึ่งแมปกับคำขอ เมื่อเราโพสต์ฟอร์ม HTML ข้อมูลจะสามารถเข้าถึงได้ตามที่คาดไว้ แต่ตอนนี้เมื่อเราสร้างคำขอ Ajax ด้วย axios คำขอจะว่างเปล่า ข้อมูลของเราหายไปหรือไม่ ? ทำไม ? เปรียบเทียบการส่งแบบฟอร์ม HTML และ axios ajax

สาเหตุ: ความแตกต่างของประเภทเนื้อหา

การโพสต์รูปแบบ HTML จะส่ง payload เป็นสตริงที่เข้ารหัส url โดยค่าเริ่มต้น หนึ่งในส่วน headers คำขอระบุประเภทเนื้อหา

Content-Type: application/x-www-form-urlencoded

Axios.post จัดอันดับ payload ลงในสตริง JSON โดยค่าเริ่มต้นซึ่งจะแสดงในส่วนหัวของชนิดเนื้อหา

Content-Type: application/json;

เนื่องจากรูปแบบ JSON อนุญาตให้จัดเก็บข้อมูลในเชิงลึกตามต้องการ จึงไม่สามารถแม็ปกับโครงสร้าง PHP ของ Parameter bag ของ $request- ได้อย่างปลอดภัย> ขอ. ดังนั้นเราต้องปรับรหัสของเราให้ทำงานกับคำขอ axios.post

โค้ดที่แก้ปัญหา

โซลูชัน # 1

ส่งส่วนของข้อมูลเป็นสตริง JSON และแก้ไขโค้ด PHP การเข้าถึงเนื้อหาคำร้องขอแบบ raw ในคอนโทรลเลอร์เกิดขึ้นผ่าน getContent () ข้อมูลดิบ JSON นี้จะต้องถูกถอดรหัสเป็นวัตถุ PHP ซึ่งค่าฟิลด์เป็นคุณสมบัติที่สามารถเข้าถึงได้

$postData = json_decode($request->getContent());
$quantity = $postData->quantity;

โซลูชัน # 2

ส่งส่วนของข้อมูลเป็นสตริงที่เข้ารหัส url โดยแก้ไขโค้ด Javascript เราสร้างวัตถุ URLSearchParams สำหรับเพย์โหลดเนื่องจาก axios ไม่ได้แปลงเป็นสตริง JSON โดยอัตโนมัติ โดยปกติของเบราว์เซอร์เราอาจใช้ส่วนต่อประสาน FormData แทน URLSearchParams

const params = new URLSearchParams();
params.append('id',1234567890);
params.append('quantity',4);

จากนั้นโพสต์ข้อมูล ตัวอย่างเช่น:

const submitData = () => {
  try {
    return axios.post(url,params);
  } catch (error) {
    console.log(error);
  }
}
response = submitData()
  .then(({data}) => {
    console.log(data);
  });

จากนั้นข้อมูลโพสต์จะสามารถเข้าถึงได้ในตัวควบคุมตัวอย่างเช่น:

$quantity = $request->request->get('quantity');

โซลูชั่นอื่น ๆ

เมื่อใดก็ตามที่ความคิดแรกรู้สึกยากหรือใช้เวลานานเกินไปในการดำเนินการเรามีแนวโน้มที่จะหาทางเลือกอื่น ดังนั้นการส่งคำขอ HTTP GET แทนทำอย่างไร? การบรรจุพารามิเตอร์บางอย่างใน URL ควรจะโอเคใช่ไหม ใช้งานง่ายแล้วทำไมไม่ใช้ axios.get ล่ะ? นี่คือเหตุผลที่ไม่ไม่ใช้

สิ่งที่ง่ายหรือรวดเร็วในการปรับใช้นั้น ไม่เกี่ยวข้องกันเมื่อเราเลือกระหว่างการโพสต์ HTTP และรับคำขอ แต่เราควรถามว่าเราสามารถทำซ้ำโดยไม่มีผลกระทบหรือไม่คุณสมบัติที่เรียกว่า idempotence ตัวอย่างเช่น การเพิ่มรายการลงในตะกร้าสินค้าควรมีผลที่ตามมาซึ่งแสดงเป็นการอัปเดตข้อมูลบนเซิร์ฟเวอร์ การกระทำซ้ำแต่ละครั้งควรเพิ่มรายการลงในรถเข็น แล้วถ้าเราใช้เครื่องมือนี้กับเพื่อรับคำขอล่ะ? ครั้งแรกอาจใช้งานได้ดี แต่ครั้งที่สอง – เราอาจได้รับข้อความ “เพิ่มรายการสำเร็จ” ตอบกลับ โดยเบราว์เซอร์ที่ไม่มีการร้องขอถึงเซิร์ฟเวอร์ นอกจากจะเป็นผลลัพธ์ที่ไม่พึงประสงค์อย่างชัดเจนแล้วยังอธิบายว่าทำไมคำขอรับไม่สามารถแทนที่คำขอโพสต์ได้ หากเราต้องการโซลูชันทางเลือกจริง ๆ เราสามารถใช้ Javascript library อื่นเป็นไคลเอนต์ HTTP ตัวอย่างเช่น jQuery มาพร้อมกับการสนับสนุนอย่างเต็มที่สำหรับ Ajax

ติดต่อเรา

มาหาทางออกที่ใช่สำหรับธุรกิจของคุณ

เราร่วมงานกับทีมผลิตภัณฑ์และผู้ก่อตั้ง เพื่อออกแบบ สร้าง และส่งมอบซอฟต์แวร์ที่ใช้งานได้ยั่งยืน

คุยกับทีมของเรา