การจัดการแบบฟอร์ม PHP และการเข้าถึงข้อมูลที่ตามมาจากอินพุตของผู้ใช้ถือเป็นหัวใจสำคัญของการเรียนรู้ PHP Symfony เพิ่มสถาปัตยกรรม Model-View-Controller (MVC) ที่มีส่วนประกอบที่นำมาใช้ซ้ำได้ โครงสร้างที่จัดระบบอย่างดี และแนวทางปฏิบัติที่ดีที่สุดให้กับกระบวนการพัฒนา ทำให้เป็นสภาพแวดล้อมทั่วไปสำหรับการจัดการอินพุตของผู้ใช้ Ajax ซึ่งเป็น เทคโนโลยีที่ช่วยให้มีเนื้อหาแบบไดนามิกบนหน้าเว็บ ช่วยให้ผู้ใช้สามารถดำเนินการต่างๆ บนหน้าได้โดยไม่ต้องเปลี่ยนหน้าหรือโหลดซ้ำ โดยประมวลผลข้อมูลในเบื้องหลัง ส่งคำขอไปยังเซิร์ฟเวอร์ และอัปเดตมุมมองหน้าตามการตอบสนอง รู้จักกันในชื่อ Javascript แบบอะซิงโครนัสฟังก์ชั่น Ajax มักใช้แทนรูปแบบ PHP เพื่อส่งข้อมูลอินพุตของผู้ใช้ไปยังเซิร์ฟเวอร์
คำถาม: การเพิ่มรายการลงในตะกร้าสินค้า
สมมติว่าเราต้องการเพิ่มรายการลงในตะกร้าสินค้า ผลมาจากการป้อนข้อมูลของผู้ใช้ เรามีชุดของรายการที่มี IDและปริมาณ คู่ของ (id, ปริมาณ) เป็นข้อมูลที่เราส่งแบบอะซิงโครนัสไปยังเซิร์ฟเวอร์ เทคโนโลยีที่เราเลือกใช้เป็นไลบรารี Javascript ที่นิยมใช้กันทั่วไปที่เรียกว่า axios ซึ่งมาพร้อมกับอินเทอร์เฟซสำหรับส่งคำขอโพสต์ไปยัง URL ที่กำหนดโดยมีข้อมูลอยู่ในเนื้อหาคำขอ เหตุผลที่อยู่เบื้องหลังตัวเลือกนั้นคือการรวมเข้ากับสภาพแวดล้อมของ VueJS หรือ ReactJSได้ง่าย
การเรียกฟังก์ชั่น
axios.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