Devfavor

Back

Laravel API Versioning - ดีไซน์ API ให้รองรับอนาคตBlur image

หากคุณเป็น developer ที่เขียน Laravel อยู่แล้ว การจะสร้าง API ขึ้นมาใช้งานคงไม่ใช่เรื่องยากและถ้าผู้ใช้งานเป็น developer ในทีมเดียวกันด้วยแล้วก็คงจะไม่เกิดปัญหาอะไร แต่ถ้า API ที่เราเขียน จำเป็นต้องให้บริการแก่ client หลายคนหรือหลายฝ่าย เช่น web frontend หรือ mobile application อาจมีโอกาสที่ client ทั้ง 2 นี้ต้องการข้อมูลที่แตกต่างกัน

หากเราอัปเดต Version ของ API ผิดพลาด ผลก็คืออาจทำให้ client ที่ใช้งานอยู่บางส่วนพังได้ทันทีโดยไม่รู้ตัว และคงจะเป็นเรื่องยากยิ่งกว่าเดิมแน่ ๆ หากระบบเรามีความซับซ้อนมากยิ่งขึ้น โอกาสที่การแก้ไขของเราจะทำให้ client พังก็ยิ่งมีมากขึ้นไปอีก นั่นทำให้การวางแผนเรื่อง API Versioning จึงเป็นเรื่องที่สำคัญและไม่ควรมองข้าม

💡 API Versioning คืออะไร#

API Versioning คือ การกำหนดรุ่น หรือ Version ให้กับ API แต่ละเส้นของเรา เพื่อให้ผู้ใช้งานสามารถแยกการใช้งานและกำหนดคุณลักษณะของ client ที่เรียกใช้แยกออกจากกัน เช่น web frontend หรือ mobile application เป็นต้น เพื่อให้ client แต่ละตัวสามารถทำงานได้ต่อเนื่องแม้ว่าทาง backend จะมีการอัปเดตเวอร์ชันนั่นเอง

📑 รูปแบบของ API Versioning#

การกำหนดเวอร์ชันให้กับ API สามารถทำได้หลายรูปแบบ เช่น

  • URI Versioning - เป็นการกำหนดเวอร์ชันของ API ผ่าน path ของ endpoint เช่น

/api/v1/users และ /api/v2/users

  • Header Versioning - เป็นการกำหนดเวอร์ชันของ API ผ่าน request header เช่น

X-API-Version: 2 และ Accept: application/vnd.example.v2+json

  • Query Parameter - เป็นการกำหนดเวอร์ชันของ API ผ่าน query parameters ของ endpoint เช่น

/api/users?version=1 และ /api/users?version=2

จะเห็นว่าแต่ละวิธีที่เลือกใช้ก็จะมีข้อดีและข้อเสียแตกต่างกัน ขึ้นอยู่กับว่าผู้พัฒนาต้องการผลลัพธ์แบบใด

🛠️ การออกแบบ API Versioning บน Laravel#

สำหรับในบทความนี้ แอดมินจะขอแนะนำวิธีการบริหารจัดการ API Versioning ในรูปแบบของ URI Versioning ซึ่งเป็นรูปแบบที่ผู้อ่านน่าจะพบเห็นได้ทั่วไป และตัว Laravel เองก็มีฟีเจอร์สำหรับแยก prefix และ group ของ API อยู่แล้วจึงทำให้สามารถบริหารจัดการได้ง่าย

โดยหัวข้อที่เกี่ยวกับการพัฒนาแบ่งออกเป็นส่วน ๆ ดังนี้

การใช้ Route Group และ Namespace#

ในขั้นแรกของการจัดการ API Versioning เราต้องทำการแยก route ของ API แต่ละเวอร์ชันออกจากกันเสียก่อน และให้ API แต่ละเวอร์ชันเรียกผ่าน Controller ที่ Namespace ตรงกับเวอร์ชันของ API ตัวอย่างเช่น

Route::prefix('v1')->group(function () {
    Route::get('/users', [App\Http\Controllers\V1\UserController::class, 'index']);
});

Route::prefix('v2')->group(function () {
    Route::get('/users', [App\Http\Controllers\V2\UserController::class, 'index']);
});
php

จากตัวอย่างจะเห็นว่า เรามี endpoint 2 เส้นคือเส้น v1 และ v2 ซึ่งถูกบริหารจัดการด้วย Controller ที่แตกต่างกัน

การใช้ Service Layer เพื่อลดความซ้ำซ้อนของโค้ดใน Controller#

หากเราแยก Controller ออกเป็น 2 เวอร์ชันแล้ว อาจมีโค้ดบางส่วนที่เหมือนเดิมซึ่งทำให้ยากต่อการบำรุงรักษาในอนาคต ในจุดนี้เราจะใช้ Service Layer เข้ามาช่วยลดความซ้ำซ้อนของโค้ดบางส่วนลง เช่น

class UserService {
    public function getUsers() {
        return User::all();
    }
}

// Controller V1
class UserControllerV1 extends Controller {
    public function index(UserService $service) {
        // Business logic for V1
        return response()->json($service->getUsers());
    }
}

// Controller V2
class UserControllerV2 extends Controller {
    public function index(UserService $service) {
        // Business logic for V2
        return response()->json($service->getUsers());
    }
}
php

จากตัวอย่างจะเห็นว่า แม้เราจะแยก Controller ออกเป็น 2 ไฟล์แล้วก็ตาม แต่การใช้ Service Layer เข้ามาช่วยจะทำให้โค้ดภายใน Controller ทั้ง 2 ไฟล์นี้ แทบจะไม่มีความซ้ำซ้อนกันอยู่เลย สิ่งที่แตกต่างกันมีเพียงโครงสร้างที่สำคัญเท่านั้นเอง

✔️ Best Practices และแนวทางที่ควรทำ#

แม้ว่าการแยก API Versioning ออกเป็นหลายเวอร์ชัน จะเป็นสิ่งที่ดีและควรทำ แต่หากไม่บริหารจัดการให้ดีก็อาจทำให้เกิดปัญหาที่คาดไม่ถึงขึ้นมาในภายหลังได้ สำหรับ Best Practices ที่ดีของการจัดการ API Versioning ที่แอดมินแนะนำว่าควรทำควบคู่กันไปมีดังนี้

  • เปลี่ยนเวอร์ชัน เมื่อมี breaking changes เท่านั้น

แม้ว่าการเปลี่ยนเวอร์ชันใน Laravel จะสามารถทำได้โดยง่าย แต่หากเราต้องเปลี่ยนเวอร์ชันทุกครั้งที่มีการแก้ไขเล็ก ๆ น้อย ๆ ก็อาจทำให้โค้ดของเราบวมขึ้นมาได้ และจะกลายเป็นว่าเวอร์ชันที่เพิ่มขึ้นมานั้นทำให้ยากต่อการบำรุงรักษาเสียเอง

ซึ่งในจุดนี้แอดมินแนะนำว่าให้เปลี่ยนเวอร์ชันเมื่อโครงสร้างของ API เปลี่ยน เช่น request parameters หรือ JSON response เท่านั้นก็เพียงพอ (หรือการ breaking changes อื่น ๆ ตามที่ทีมตกลงร่วมกัน)

  • เขียนเอกสารกำกับให้ชัดเจน

กรณีที่ API มีหลายเส้นและหลายเวอร์ชัน อาจทำให้ client หรือผู้ใช้งานเกิดความสับสนถึงโครงสร้างของ request และ response ที่อาจเปลี่ยนแปลงไปได้ เราจึงควรมีเอกสารกลางไว้กำกับคุณสมบัติของ API แต่ละเวอร์ชันเพื่อให้การสื่อสารระหว่างผู้พัฒนา API และผู้ใช้งานมีความชัดเจนมากยิ่งขึ้น

  • วางแผน Deprecation

บางครั้ง API เวอร์ชันเก่าที่โครงสร้างไม่รองรับแล้วและจำเป็นต้องหยุดให้บริการลงด้วยเหตุผลต่าง ๆ เช่น ความปลอดภัยหรือ Performance ของ software ในกรณีนี้ผู้พัฒนาควรวางแผน Deprecation และแจ้งผู้ใช้งานก่อนที่จะหยุดให้บริการ เพื่อให้ผู้ใช้งานสามารถปรับปรุง website หรือ application ให้รองรับกับ API เวอร์ชันปัจจุบันได้

  • วางแผน Test API แต่ละเวอร์ชันแยกกัน

แม้การทำงานของ API แต่ละเวอร์ชันจะคล้ายกัน แต่เมื่อมีการพัฒนาก็ย่อมมีความแตกต่างกันอย่างแน่นอน (ยิ่งรวมกับว่าเราแยก API เมื่อ breaking changes) ทำให้การทดสอบ API แต่ละเวอร์ชันควรทำแยกกัน เพื่อให้มั่นใจได้ว่า API แต่ละเวอร์ชันยังคงสามารถทำงานได้อย่างถูกต้องแม้จะมีการเพิ่มเติมหรือแก้ไขใด ๆ

👩‍💻 บทสรุป#

แม้ว่าเรื่อง API Versioning จะดูเป็นเรื่องเล็กน้อยแต่ก็เป็นสิ่งสำคัญที่จะช่วยให้ระบบสามารถพัฒนาและเปลี่ยนแปลงได้โดยไม่กระทบผู้ใช้เดิม และเมื่อวางแผนอย่างเป็นระบบตั้งแต่ต้น ก็จะช่วยลดปัญหาในอนาคต และสร้างความมั่นใจให้ทั้งทีมพัฒนาและผู้ใช้งาน API อีกด้วย

Code, coffee, and calm — the holy trinity of a good day. ☕

Laravel API Versioning - ดีไซน์ API ให้รองรับอนาคต
Author Coffee Stack
Published at August 25, 2025