การสร้าง REST API สำหรับโปรเจ็กต์ PHP ดั้งเดิม
เผยแพร่แล้ว: 2022-03-11การสร้างหรือการออกแบบ REST API ไม่ใช่เรื่องง่าย โดยเฉพาะอย่างยิ่งเมื่อคุณต้องทำสำหรับโปรเจ็กต์ PHP รุ่นเก่า มีไลบรารีของบุคคลที่สามจำนวนมากในปัจจุบันที่ทำให้ง่ายต่อการใช้งาน REST API แต่การผสานรวมเข้ากับฐานรหัสเดิมที่มีอยู่นั้นค่อนข้างน่ากลัว และคุณไม่ได้มีความหรูหราในการทำงานกับเฟรมเวิร์กที่ทันสมัย เช่น Laravel และ Symfony เสมอไป ด้วยโปรเจ็กต์ PHP แบบเก่า คุณมักจะพบว่าตัวเองอยู่ตรงกลางของเฟรมเวิร์กภายในที่เลิกใช้แล้ว ซึ่งทำงานบน PHP เวอร์ชันเก่า
ในบทความนี้ เราจะมาดูความท้าทายทั่วไปบางประการในการพยายามปรับใช้ REST API ตั้งแต่เริ่มต้น วิธีสองสามวิธีในการแก้ไขปัญหาเหล่านั้น และกลยุทธ์โดยรวมสำหรับการสร้างเซิร์ฟเวอร์ API ที่ใช้ PHP แบบกำหนดเองสำหรับโครงการรุ่นเก่า
แม้ว่าบทความนี้จะใช้ PHP 5.3 ขึ้นไป แต่แนวคิดหลักใช้ได้กับ PHP ทุกเวอร์ชันที่นอกเหนือจากเวอร์ชัน 5.0 และสามารถนำไปใช้กับโปรเจ็กต์ที่ไม่ใช่ PHP ได้ ในที่นี้ เราจะไม่ครอบคลุมถึงสิ่งที่ REST API โดยทั่วไป ดังนั้นหากคุณไม่คุ้นเคย โปรดอ่านเกี่ยวกับมันก่อน
เพื่อให้ง่ายต่อการปฏิบัติตาม ต่อไปนี้คือรายการคำศัพท์บางคำที่ใช้ในบทความนี้และความหมาย:
- เซิร์ฟเวอร์ API: แอปพลิเคชัน REST หลักที่ให้บริการ API ในกรณีนี้ เขียนด้วย PHP
- จุดสิ้นสุด API: "วิธีการ" แบ็กเอนด์ที่ไคลเอ็นต์สื่อสารด้วยเพื่อดำเนินการและให้ผลลัพธ์
- URL ปลายทางของ API: URL ที่ระบบแบ็กเอนด์สามารถเข้าถึงได้ทั่วโลก
- โทเค็น API: ตัวระบุเฉพาะที่ส่งผ่านส่วนหัว HTTP หรือคุกกี้ซึ่งระบุผู้ใช้ได้
- แอป: แอปพลิเคชันไคลเอ็นต์ซึ่งจะสื่อสารกับแอปพลิเคชัน REST ผ่านจุดปลาย API ในบทความนี้ เราจะถือว่ามันเป็นเว็บ (ทั้งเดสก์ท็อปหรือมือถือ) และเขียนด้วย JavaScript
ขั้นตอนเบื้องต้น
รูปแบบเส้นทาง
สิ่งแรกที่เราต้องตัดสินใจคือเส้นทาง URL ใดที่ปลายทาง API จะพร้อมใช้งาน มี 2 วิธียอดนิยม:
- สร้างโดเมนย่อยใหม่ เช่น api.example.com
- สร้างเส้นทาง เช่น example.com/api
เมื่อมองแวบเดียว ดูเหมือนว่าตัวแปรแรกจะเป็นที่นิยมและน่าดึงดูดใจมากกว่า อย่างไรก็ตาม ในความเป็นจริง หากคุณกำลังสร้าง API เฉพาะโปรเจ็กต์ การเลือกตัวแปรที่สองอาจเหมาะสมกว่า
เหตุผลที่สำคัญที่สุดประการหนึ่งเบื้องหลังการใช้แนวทางที่สองคือการอนุญาตให้ใช้คุกกี้เป็นวิธีการโอนข้อมูลรับรอง ลูกค้าที่ใช้เบราว์เซอร์จะส่งคุกกี้ที่เหมาะสมโดยอัตโนมัติภายในคำขอ XHR โดยไม่จำเป็นต้องมีส่วนหัวการอนุญาตเพิ่มเติม
เหตุผลสำคัญอีกประการหนึ่งคือคุณไม่จำเป็นต้องดำเนินการใดๆ เกี่ยวกับการกำหนดค่าโดเมนย่อยหรือปัญหาการจัดการที่พร็อกซีเซิร์ฟเวอร์บางตัวอาจถอดส่วนหัวที่กำหนดเอง นี่อาจเป็นการทดสอบที่น่าเบื่อในโครงการเดิม
การใช้คุกกี้ถือได้ว่าเป็นแนวทางปฏิบัติที่ "ไม่สงบ" เนื่องจากคำขอ REST ควรเป็นแบบไร้สัญชาติ ในกรณีนี้ เราสามารถประนีประนอมและส่งค่าโทเค็นในคุกกี้ แทนที่จะส่งต่อผ่านส่วนหัวที่กำหนดเอง อย่างมีประสิทธิภาพ เราใช้คุกกี้เป็นเพียงวิธีการส่งค่าโทเค็นแทน session_id โดยตรง วิธีการนี้ถือได้ว่าเป็นคนไร้สัญชาติ แต่เราสามารถปล่อยให้เป็นไปตามความต้องการของคุณ
URL ปลายทางของ API ยังสามารถกำหนดเวอร์ชันได้ นอกจากนี้ พวกเขาสามารถรวมรูปแบบการตอบสนองที่คาดไว้เป็นส่วนขยายในชื่อพาธ แม้ว่าสิ่งเหล่านี้จะไม่สำคัญ โดยเฉพาะอย่างยิ่งในช่วงเริ่มต้นของการพัฒนา API แต่ในระยะยาว รายละเอียดเหล่านี้สามารถให้ผลตอบแทนได้อย่างแน่นอน โดยเฉพาะอย่างยิ่งเมื่อคุณต้องการใช้คุณสมบัติใหม่ การตรวจสอบเวอร์ชันที่ไคลเอ็นต์คาดหวังและการจัดหารูปแบบที่จำเป็นสำหรับความเข้ากันได้แบบย้อนหลังอาจเป็นทางออกที่ดีที่สุด
โครงสร้าง URL ปลายทางของ API อาจมีลักษณะดังนี้:
example.com/api/${version_code}/${actual_request_path}.${format}
และตัวอย่างจริง:
example.com/api/v1.0/records.json
การกำหนดเส้นทาง
หลังจากเลือก URL ฐานสำหรับปลายทาง API สิ่งต่อไปที่เราต้องทำคือคิดถึงระบบการกำหนดเส้นทางของเรา มันสามารถรวมเข้ากับเฟรมเวิร์กที่มีอยู่ได้ แต่ถ้านั่นยุ่งยากเกินไป วิธีแก้ปัญหาที่เป็นไปได้คือการสร้างโฟลเดอร์ชื่อ “api” ในรูทของเอกสาร ด้วยวิธีนี้ API สามารถมีตรรกะที่แยกจากกันโดยสิ้นเชิง คุณสามารถขยายแนวทางนี้ได้โดยการวางตรรกะ API ลงในไฟล์ของตัวเอง เช่น
คุณสามารถมองว่า “www/api/Apis/Users.php” เป็น “ตัวควบคุม” แยกต่างหากสำหรับจุดปลาย API เฉพาะ การนำการนำไปใช้งานซ้ำจากฐานโค้ดที่มีอยู่มาใช้ซ้ำจะดีมาก เช่น การนำแบบจำลองที่ใช้แล้วมาใช้ซ้ำในโปรเจ็กต์เพื่อสื่อสารกับฐานข้อมูล
สุดท้าย ตรวจสอบให้แน่ใจว่าได้ระบุคำขอขาเข้าทั้งหมดจาก “/api/*” ไปที่ “/api/index.php” ซึ่งสามารถทำได้โดยเปลี่ยนการกำหนดค่าเว็บเซิร์ฟเวอร์ของคุณ
คลาส API
เวอร์ชันและรูปแบบ
คุณควรระบุให้ชัดเจนว่าเวอร์ชันและรูปแบบใดที่ปลายทาง API ของคุณยอมรับและค่าเริ่มต้นคืออะไร ซึ่งจะทำให้คุณสามารถสร้างคุณลักษณะใหม่ได้ในอนาคตโดยที่ยังคงฟังก์ชันเดิมไว้ โดยพื้นฐานแล้ว เวอร์ชัน API สามารถเป็นสตริงได้ แต่คุณสามารถใช้ค่าตัวเลขเพื่อความเข้าใจและเปรียบเทียบได้ดียิ่งขึ้น เป็นการดีที่จะมีตัวเลขสำรองสำหรับรุ่นรองเพราะจะแสดงให้เห็นชัดเจนว่ามีเพียงบางสิ่งเท่านั้นที่แตกต่างกัน:
- v1.0 จะหมายถึงรุ่นแรก
- v1.1 เวอร์ชันแรกพร้อมการเปลี่ยนแปลงเล็กน้อย
- v2.0 จะเป็นเวอร์ชันใหม่ทั้งหมด
รูปแบบสามารถเป็นอะไรก็ได้ที่ลูกค้าของคุณต้องการ ซึ่งรวมถึงแต่ไม่จำกัดเพียง JSON, XML และแม้แต่ CSV โดยการระบุผ่าน URL เป็นนามสกุลไฟล์ URL ปลายทางของ API ช่วยให้สามารถอ่านได้ และกลายเป็นเรื่องง่ายสำหรับผู้บริโภค API ที่จะรู้ว่ารูปแบบใดที่พวกเขาคาดหวังได้:
- “/api/v1.0/records.json” จะส่งคืนอาร์เรย์ JSON ของเรคคอร์ด
- “/api/v1.0/records.xml” จะส่งคืนไฟล์ XML ของบันทึก
เป็นที่น่าสังเกตว่าคุณจะต้องส่งส่วนหัวของประเภทเนื้อหาที่เหมาะสมในการตอบกลับสำหรับแต่ละรูปแบบเหล่านี้
เมื่อได้รับคำขอเข้ามา สิ่งแรกที่คุณควรทำคือตรวจสอบว่าเซิร์ฟเวอร์ API รองรับเวอร์ชันและรูปแบบที่ร้องขอหรือไม่ ในวิธีการหลักของคุณ ซึ่งจัดการคำขอที่เข้ามา ให้แยกวิเคราะห์ $_SERVER['PATH_INFO'] หรือ $_SERVER['REQUEST_URI'] เพื่อตรวจสอบว่ารูปแบบและเวอร์ชันที่ร้องขอได้รับการสนับสนุนหรือไม่ จากนั้น ดำเนินการต่อหรือตอบกลับ 4xx ตอบกลับ (เช่น 406 “ไม่ยอมรับ”) ส่วนที่สำคัญที่สุดในที่นี้คือส่งคืนสิ่งที่ลูกค้าคาดหวังเสมอ อีกทางเลือกหนึ่งคือการตรวจสอบส่วนหัวคำขอ "ยอมรับ" แทนส่วนขยายเส้นทาง URL
เส้นทางที่อนุญาต
คุณสามารถส่งต่อทุกอย่างอย่างโปร่งใสไปยังตัวควบคุม API ของคุณได้ แต่ควรใช้ชุดเส้นทางที่อนุญาตในรายการที่อนุญาตพิเศษ สิ่งนี้จะลดความยืดหยุ่นลงเล็กน้อย แต่จะให้ข้อมูลเชิงลึกที่ชัดเจนว่า URL ปลายทางของ API มีลักษณะอย่างไรในครั้งต่อไปที่คุณกลับมาที่โค้ด
private $public_routes = array( 'system' => array( 'regex' => 'system', ), 'records' => array( 'regex' => 'records(?:/?([0-9]+)?)', ), );
คุณยังสามารถย้ายไฟล์เหล่านี้ไปยังไฟล์แยกกันเพื่อทำให้ทุกอย่างสะอาดขึ้น การกำหนดค่าด้านบนจะใช้เพื่อเปิดใช้งานคำขอไปยัง URL เหล่านี้:
/api/v1.0/system.json /api/v1.0/records.json /api/v1.0/records/7.json
การจัดการ PUT Data
PHP จัดการข้อมูล POST ที่เข้ามาโดยอัตโนมัติและวางไว้ใต้ $_POST superglobal อย่างไรก็ตาม นั่นไม่ใช่กรณีของคำขอ PUT ข้อมูลทั้งหมดถูก "ฝัง" ลงใน php://input อย่าลืมแยกวิเคราะห์เป็นโครงสร้างหรืออาร์เรย์แยกต่างหากก่อนที่จะเรียกใช้เมธอด API จริง parse_str แบบธรรมดาอาจเพียงพอ แต่ถ้าไคลเอนต์ส่งคำขอแบบหลายส่วน อาจจำเป็นต้องแยกวิเคราะห์เพิ่มเติมเพื่อจัดการกับขอบเขตของแบบฟอร์ม กรณีการใช้งานทั่วไปของคำขอหลายส่วนรวมถึงการอัปโหลดไฟล์ การตรวจจับและจัดการคำขอแบบหลายส่วนสามารถทำได้ดังนี้:
self::$input = file_get_contents('php://input'); // For PUT/DELETE there is input data instead of request variables if (!empty(self::$input)) { preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches); if (isset($matches[1]) && strpos(self::$input, $matches[1]) !== false) { $this->parse_raw_request(self::$input, self::$input_data); } else { parse_str(self::$input, self::$input_data); } }
ที่นี่ parse_raw_request สามารถนำไปใช้เป็น:
/** * Helper method to parse raw requests */ private function parse_raw_request($input, &$a_data) { // grab multipart boundary from content type header preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches); $boundary = $matches[1]; // split content by boundary and get rid of last -- element $a_blocks = preg_split("/-+$boundary/", $input); array_pop($a_blocks); // loop data blocks foreach ($a_blocks as $id => $block) { if (empty($block)) { continue; } // parse uploaded files if (strpos($block, 'application/octet-stream') !== false) { // match "name", then everything after "stream" (optional) except for prepending newlines preg_match("/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s", $block, $matches); // parse all other fields } else { // match "name" and optional value in between newline sequences preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $block, $matches); } $a_data[$matches[1]] = $matches[2]; } }
ด้วยวิธีนี้ เราสามารถมีเพย์โหลดคำขอที่จำเป็นที่ Api::$input เป็นอินพุตดิบ และ Api::$input_data เป็นอาร์เรย์ที่เชื่อมโยง

แกล้ง PUT/DELETE
บางครั้ง คุณอาจเห็นตัวเองอยู่ในสถานการณ์ที่เซิร์ฟเวอร์ไม่สนับสนุนสิ่งใดนอกจากวิธี GET/POST HTTP มาตรฐาน วิธีแก้ปัญหาทั่วไปสำหรับปัญหานี้คือการ "ปลอม" PUT/DELETE หรือวิธีการร้องขอแบบกำหนดเองอื่นๆ เพื่อที่คุณจะใช้พารามิเตอร์ "magic" เช่น "_method" ได้ หากคุณเห็นในอาร์เรย์ $_REQUEST ของคุณ ให้ถือว่าคำขอนั้นเป็นประเภทที่ระบุ กรอบงานสมัยใหม่เช่น Laravel มีฟังก์ชันดังกล่าวอยู่ภายใน มีความเข้ากันได้ดีในกรณีที่เซิร์ฟเวอร์หรือไคลเอนต์ของคุณมีข้อจำกัด (เช่น บุคคลกำลังใช้เครือข่าย Wi-Fi ของงานหลังพร็อกซีขององค์กรที่ไม่อนุญาตให้ส่งคำขอ PUT)
การส่งต่อไปยัง API เฉพาะ
หากคุณไม่มีความหรูหราในการนำตัวโหลดอัตโนมัติของโปรเจ็กต์ที่มีอยู่กลับมาใช้ใหม่ คุณสามารถสร้างของคุณเองได้โดยใช้ฟังก์ชัน spl_autoload_register กำหนดไว้ในหน้า “api/index.php” และเรียกคลาส API ของคุณที่อยู่ใน “api/Api.php” คลาส API ทำหน้าที่เป็นมิดเดิลแวร์และเรียกใช้เมธอดจริง ตัวอย่างเช่น การร้องขอไปยัง “/api/v1.0/records/7.json” ควรจบลงด้วยการเรียกใช้เมธอด GET ของ “Apis/Records.php” ด้วยพารามิเตอร์ 7 การทำเช่นนี้จะช่วยแยกข้อกังวลและให้วิธีที่จะรักษา ตัวล้างตรรกะ แน่นอน ถ้าเป็นไปได้ที่จะรวมสิ่งนี้ให้ลึกลงไปในเฟรมเวิร์กที่คุณกำลังใช้และนำคอนโทรลเลอร์เฉพาะหรือเส้นทางกลับมาใช้ใหม่ คุณควรพิจารณาถึงความเป็นไปได้นั้นด้วย
ตัวอย่าง “api/index.php” พร้อมตัวโหลดอัตโนมัติดั้งเดิม:
<?php // Let's define very primitive autoloader spl_autoload_register(function($classname){ $classname = str_replace('Api_', 'Apis/', $classname); if (file_exists(__DIR__.'/'.$classname.'.php')) { require __DIR__.'/'.$classname.'.php'; } }); // Our main method to handle request Api::serve();
สิ่งนี้จะโหลดคลาส API ของเราและเริ่มให้บริการโดยไม่ขึ้นกับโปรเจ็กต์หลัก
คำขอตัวเลือก
เมื่อไคลเอนต์ใช้ส่วนหัวที่กำหนดเองเพื่อส่งต่อโทเค็นเฉพาะ เบราว์เซอร์จะต้องตรวจสอบทุกครั้งที่เซิร์ฟเวอร์สนับสนุนส่วนหัวนั้นก่อน นั่นคือที่มาของคำขอ OPTIONS โดยมีจุดประสงค์เพื่อให้แน่ใจว่าทุกอย่างเรียบร้อยและปลอดภัยสำหรับทั้งไคลเอนต์และเซิร์ฟเวอร์ API ดังนั้นคำขอ OPTIONS อาจเริ่มทำงานทุกครั้งที่ลูกค้าพยายามทำอะไร อย่างไรก็ตาม เมื่อไคลเอนต์ใช้คุกกี้สำหรับข้อมูลประจำตัว เบราว์เซอร์จะบันทึกไม่ต้องส่งคำขอ OPTIONS เพิ่มเติมนี้
หากไคลเอนต์ร้องขอ POST /users/8.json ด้วยคุกกี้ คำขอนั้นก็จะมีมาตรฐานค่อนข้างมาก:
- แอปดำเนินการส่งคำขอ POST ไปยัง /users/8.json
- เบราว์เซอร์ดำเนินการตามคำขอและรับการตอบกลับ
แต่ด้วยการอนุญาตแบบกำหนดเองหรือส่วนหัวของโทเค็น:
- แอปดำเนินการส่งคำขอ POST ไปยัง /users/8.json
- เบราว์เซอร์หยุดประมวลผลคำขอและเริ่มคำขอ OPTIONS แทน
- คำขอ OPTIONS ถูกส่งไปยัง /users/8.json
- เบราว์เซอร์ได้รับการตอบกลับพร้อมรายการวิธีการและส่วนหัวที่มีอยู่ทั้งหมด ตามที่กำหนดโดย API
- เบราว์เซอร์จะดำเนินการต่อด้วยคำขอ POST เดิมต่อเมื่อมีส่วนหัวที่กำหนดเองอยู่ในรายการส่วนหัวที่พร้อมใช้งาน
อย่างไรก็ตาม โปรดทราบว่าแม้ในขณะที่ใช้คุกกี้ เมื่อใช้ PUT/DELETE คุณอาจยังคงได้รับคำขอ OPTIONS เพิ่มเติมนั้น ดังนั้นจงเตรียมพร้อมที่จะตอบสนองต่อมัน
บันทึก API
โครงสร้างพื้นฐาน
ตัวอย่าง Records API ของเราค่อนข้างตรงไปตรงมา มันจะประกอบด้วยวิธีการร้องขอทั้งหมดและส่งคืนผลลัพธ์กลับไปยังคลาส API หลักเดียวกัน ตัวอย่างเช่น:
<?php class Api_Records { public function __construct() { // In here you could initialize some shared logic between this API and rest of the project } /** * Get individual record or records list */ public function get($id = null) { if ($id) { return $this->getRecord(intval($id)); } else { return $this->getRecords(); } } /** * Update record */ public function put($record_id = null) { // In real world there would be call to model with validation and probably token checking // Use Api::$input_data to update return Api::responseOk('OK', array()); } // ...
ดังนั้นการกำหนดวิธี HTTP แต่ละวิธีจะช่วยให้เราสร้าง API ในรูปแบบ REST ได้ง่ายขึ้น
การจัดรูปแบบเอาต์พุต
การตอบสนองอย่างไร้เดียงสากับทุกอย่างที่ได้รับจากฐานข้อมูลกลับไปยังไคลเอนต์อาจส่งผลกระทบร้ายแรง เพื่อหลีกเลี่ยงการเปิดเผยข้อมูลโดยไม่ได้ตั้งใจ ให้สร้างวิธีการจัดรูปแบบเฉพาะซึ่งจะส่งคืนเฉพาะคีย์ที่อนุญาตพิเศษ
ประโยชน์อีกประการของคีย์ที่อนุญาตพิเศษคือ คุณสามารถเขียนเอกสารโดยอิงจากสิ่งเหล่านี้ และทำการตรวจสอบประเภททั้งหมดเพื่อให้แน่ใจว่า user_id จะเป็นจำนวนเต็มเสมอ แฟล็ก is_banned จะเป็นบูลีนจริงหรือเท็จเสมอ และวันที่เวลาจะมีมาตรฐานเดียว รูปแบบการตอบสนอง
ผลลัพธ์ที่ได้
ส่วนหัว
วิธีการแยกสำหรับเอาต์พุตส่วนหัวจะช่วยให้แน่ใจว่าทุกอย่างที่ส่งไปยังเบราว์เซอร์นั้นถูกต้อง วิธีนี้สามารถใช้ประโยชน์จากการทำให้ API สามารถเข้าถึงได้ผ่านโดเมนเดียวกันในขณะที่ยังคงความเป็นไปได้ที่จะได้รับส่วนหัวการอนุญาตที่กำหนดเอง ตัวเลือกระหว่างโดเมนเดียวกันหรือโดเมนบุคคลที่สามอาจเกิดขึ้นได้ด้วยความช่วยเหลือของส่วนหัวเซิร์ฟเวอร์ HTTP_ORIGIN และ HTTP_REFERER หากแอปตรวจพบว่าไคลเอ็นต์ใช้การอนุญาต x (หรือส่วนหัวที่กำหนดเองอื่นๆ) แอปควรอนุญาตการเข้าถึงจากต้นทางทั้งหมด ให้อนุญาตส่วนหัวที่กำหนดเอง ดังนั้นจึงอาจมีลักษณะดังนี้:
header('Access-Control-Allow-Origin: *'); header('Access-Control-Expose-Headers: x-authorization'); header('Access-Control-Allow-Headers: origin, content-type, accept, x-authorization'); header('X-Authorization: '.YOUR_TOKEN_HERE);
อย่างไรก็ตาม หากไคลเอนต์ใช้ข้อมูลประจำตัวแบบคุกกี้ ส่วนหัวอาจแตกต่างกันเล็กน้อย โดยอนุญาตเฉพาะส่วนหัวที่เกี่ยวข้องกับโฮสต์และคุกกี้ที่ร้องขอสำหรับข้อมูลประจำตัว:
header('Access-Control-Allow-Origin: '.$origin); header('Access-Control-Expose-Headers: set-cookie, cookie'); header('Access-Control-Allow-Headers: origin, content-type, accept, set-cookie, cookie'); // Allow cookie credentials because we're on the same domain header('Access-Control-Allow-Credentials: true'); if (strtolower($_SERVER['REQUEST_METHOD']) != 'options') { setcookie(TOKEN_COOKIE_NAME, YOUR_TOKEN_HERE, time()+86400*30, '/', '.'.$_SERVER['HTTP_HOST']); }
โปรดทราบว่าคำขอ OPTIONS ไม่รองรับคุกกี้ ดังนั้นแอปจะไม่ส่งคำขอไปด้วย และสุดท้ายนี้ทำให้วิธีการ HTTP ทั้งหมดที่เราต้องการมีการควบคุมการเข้าถึงหมดอายุ:
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE'); header('Access-Control-Max-Age: 86400');
ตัว
เนื้อหาควรมีการตอบสนองในรูปแบบที่ลูกค้าของคุณร้องขอโดยมีสถานะ HTTP 2xx เมื่อสำเร็จ สถานะ 4xx เมื่อล้มเหลวเนื่องจากไคลเอนต์และสถานะ 5xx เมื่อล้มเหลวเนื่องจากเซิร์ฟเวอร์ โครงสร้างของการตอบสนองอาจแตกต่างกันไป แม้ว่าการระบุฟิลด์ "สถานะ" และ "การตอบสนอง" อาจเป็นประโยชน์เช่นกัน ตัวอย่างเช่น หากไคลเอนต์พยายามลงทะเบียนผู้ใช้ใหม่และชื่อผู้ใช้นั้นถูกใช้ไปแล้ว คุณสามารถส่งการตอบกลับด้วยสถานะ HTTP 200 แต่ JSON ในเนื้อหาที่มีลักษณะดังนี้:
{“status”: “ERROR”, “response”: ”username already taken”}
… แทนที่จะเป็นข้อผิดพลาด HTTP 4xx โดยตรง
บทสรุป
ไม่มีสองโครงการที่เหมือนกันทุกประการ กลยุทธ์ที่สรุปไว้ในบทความนี้อาจจะใช่หรือไม่เหมาะกับกรณีของคุณ แต่แนวความคิดหลักควรมีความคล้ายคลึงกัน เป็นที่น่าสังเกตว่าไม่ใช่ว่าทุกหน้าจะมีเฟรมเวิร์กที่เป็นเทรนด์ล่าสุดหรือเป็นปัจจุบันอยู่เบื้องหลัง และบางครั้งความโกรธที่ว่า "เหตุใดชุด REST Symfony ของฉันจึงไม่ทำงานที่นี่" อาจกลายเป็นแรงจูงใจในการสร้างสิ่งที่มีประโยชน์ สิ่งที่ทำงาน ผลลัพธ์ที่ได้อาจไม่แวววาวเท่าที่ควร เนื่องจากจะเป็นการใช้งานแบบเฉพาะและเฉพาะโครงการเสมอ แต่ท้ายที่สุดแล้ว โซลูชันจะเป็นสิ่งที่ใช้งานได้จริง และในสถานการณ์เช่นนี้ควรเป็นเป้าหมายของนักพัฒนา API ทุกคน
ตัวอย่างการใช้งานแนวคิดที่กล่าวถึงในที่นี้ได้รับการอัปโหลดไปยังที่เก็บ GitHub เพื่อความสะดวก คุณอาจไม่ต้องการใช้โค้ดตัวอย่างเหล่านี้โดยตรงในการผลิตเหมือนที่เป็นอยู่ แต่นี่อาจเป็นจุดเริ่มต้นสำหรับโปรเจ็กต์การรวม PHP API แบบเดิมของคุณได้อย่างง่ายดาย
ต้องใช้เซิร์ฟเวอร์ REST API สำหรับโครงการเดิมบางโครงการเมื่อเร็ว ๆ นี้หรือไม่ แบ่งปันประสบการณ์ของคุณกับเราในส่วนความคิดเห็นด้านล่าง