ศูนย์รวมความรู้วิศวกรรมซอฟต์แวร์

แบ่งปันประสบการณ์การออกแบบสถาปัตยกรรมระบบ, การเขียนโค้ดด้วย Laravel และการจัดการ Server ระดับ Production เพื่อยกระดับทักษะของนักพัฒนาทุกคน

คู่มือสถาปัตยกรรมระบบ: Laravel Layered Architecture

สำหรับทีมพัฒนาขนาด 2-5 คน (Production Grade)


เอกสารฉบับนี้คือคู่มืออ้างอิงภายในทีมสำหรับสถาปัตยกรรมแอปพลิเคชัน Laravel โปรเจกต์นี้ใช้หลัก Layered Architecture บน Laravel โดยแบ่งความรับผิดชอบออกเป็นชั้นที่ชัดเจน เป้าหมายหลักเพื่อให้โค้ดอ่านง่าย ทดสอบได้ (Testable) และสามารถขยายสเกลได้ในระยะยาว

กฎพื้นฐานที่สำคัญที่สุด: ข้อมูลจะต้องไหลจาก Presentation → Application → Domain เสมอ ห้าม Layer ชั้นล่างเรียกใช้งาน Layer ชั้นบนเด็ดขาด

📂 โครงสร้างโฟลเดอร์ (Directory Structure) 
app/
├── Actions/          # Business Logic — งาน 1 ขั้นตอนหลัก [cite: 11]
├── Queries/          # Read-only — ดึงข้อมูลซับซ้อน / Report [cite: 12]
├── DTOs/             # Data Transfer Objects [cite: 13]
├── Enums/            # ค่าคงที่ (Type-safe) [cite: 14]
├── Http/             # [cite: 15]
│   ├── Controllers/  # รับ Request, เรียก Action/Query, ส่ง Response [cite: 16]
│   ├── Requests/     # Form Validation [cite: 17]
│   └── Resources/    # API Response Format [cite: 18]
├── Livewire/         # UI Components (Fullstack) [cite: 19]
├── Models/           # Eloquent Models [cite: 20]
└── Services/         # Business Logic — งานหลายขั้นตอน / 3rd Party [cite: 21]

รายละเอียดของแต่ละ Layer
1. Presentation Layer
ทำหน้าที่เป็นประตูรับ Request จากผู้ใช้ ประกอบด้วย 3 ส่วนหลัก:
  • Controllers: ทำหน้าที่รับ HTTP Request แล้วส่งต่อให้ Action หรือ Query ทำงาน จากนั้นจึง Return Resource หรือ View ห้ามมี Business Logic อยู่ใน Controller เด็ดขาด 
  • Requests: จัดการ Form Validation ทั้งหมดไว้ที่นี่ โดยใช้ authorize() สำหรับ Policy และ rules() สำหรับกำหนดเงื่อนไขตรวจสอบข้อมูล 
  • Resources: กำหนดรูปแบบ JSON Response สำหรับ API โดยแยกออกจาก Model เพื่อป้องกันการเปิดเผย (Expose) ฟิลด์ข้อมูลที่ไม่จำเป็น 
  • Livewire Components: ใช้สำหรับสร้าง UI ที่ต้องการความมีชีวิตชีวา (Reactivity) สามารถเรียกใช้งาน Action หรือ Query ได้โดยตรง แต่ต้องไม่มี Business Logic ภายใน Component 
2. Application Layer
Business Logic ทั้งหมดของระบบจะรวมอยู่ที่นี่ โดยแบ่งการทำงานออกเป็น 2 ประเภท:

เกณฑ์           | Action                            | Service                                        |  
--------------------------------------------------------------------------------------------
จำนวนขั้นตอน | 1 ขั้นตอนหลัก                   | หลายขั้นตอน / ทำงานกับหลาย Model   |
--------------------------------------------------------------------------------------------
การใช้งาน      | มี execute() method เดียว | Inject เข้า Action หรือ Controller       |
--------------------------------------------------------------------------------------------
Third-party  | ไม่ควรมี                          | เหมาะสำหรับเรียก API ภายนอก            |
--------------------------------------------------------------------------------------------
ตัวอย่าง       | CreateOrderAction          | PaymentService, NotificationService |
--------------------------------------------------------------------------------------------
  • Actions: ใช้สำหรับงานที่มีจุดประสงค์เดียวและชัดเจน ต้องตั้งชื่อในรูปแบบ Verb + Noun + Action เสมอ 
  • Services: ใช้เมื่องานนั้นมีหลายขั้นตอน ต้องเชื่อมโยงหลาย Action เข้าด้วยกัน หรือต้องสื่อสารกับ Third-party API (เช่น Payment Gateway, Email, SMS) 
3. Query Layer
ใช้สำหรับการดึงข้อมูลที่มีความซับซ้อน เช่น การทำรายงาน (Report), Dashboard, หรือการ Query ที่ต้อง Join หลาย Table 
  • กฎเหล็ก: Query ต้องทำงานแบบ Read-only เท่านั้น ห้ามมีการแก้ไขเปลี่ยนแปลงข้อมูลเด็ดขาด 
4. Domain Layer
ถือเป็นหัวใจของระบบ ประกอบด้วยโครงสร้างข้อมูลและค่าคงที่ที่ Business ใช้งาน เป็นชั้นแบบ Pure PHP ที่ไม่มี Side Effects 
  • Models (Eloquent): ใช้กำหนด Relationships, Casts, และ Scopes ห้ามมี Business Logic หรือ Validation อยู่ใน Model 
  • DTOs (Data Transfer Objects): ใช้สำหรับส่งข้อมูลข้ามระหว่าง Layer อย่างปลอดภัย เป็น Typed Object ที่เข้ามาแทนที่ Array ธรรมดา ช่วยให้ IDE ทำ Autocomplete ได้ และป้องกันการพิมพ์ชื่อตัวแปรผิด (Typo) 
  • Enums: ใช้แทน Magic String หรือ Magic Number เพื่อให้ระบบมีความปลอดภัยทางชนิดข้อมูล (Type-safe) และทำให้โค้ดอ่านง่ายขึ้น 
กระแสข้อมูล (Request Flow)
ทุก Request ที่เข้ามาจะต้องไหลตามเส้นทางนี้เสมอ ห้ามข้ามขั้นตอน:
Flow การเขียน / เปลี่ยนแปลงข้อมูล (Write Flow) 
  1. HTTP Request เข้าสู่ Router
  2. Router ส่งคำสั่งไปยัง Controller
  3. FormRequest ทำการตรวจสอบข้อมูล (Validation) อัตโนมัติ
  4. Controller สร้าง DTO จาก Request ที่ผ่านการตรวจสอบแล้ว
  5. Controller เรียกใช้งาน Action หรือ Service พร้อมส่ง DTO เข้าไป
  6. Action/Service ทำงานร่วมกับ Model เพื่อบันทึกข้อมูล
  7. Controller รับผลลัพธ์กลับมา แล้ว Return เป็น Resource ออกไป
Flow การอ่านข้อมูล / ออกรายงาน (Read / Report Flow) 
  1. HTTP Request เข้าสู่ Router
  2. Controller เรียกใช้งาน Query โดยตรง
  3. Query ทำการดึงข้อมูลจาก Database
  4. Controller Return ข้อมูลกลับไปเป็น Resource หรือ Collection
Do's & Don'ts (ข้อควรปฏิบัติและข้อห้าม)
สิ่งที่ควรทำ (Do's) 
  • ตั้งชื่อ Action ในรูปแบบ Verb + Noun + Action (เช่น CreateOrderAction) 
  • ใช้ DTO แทน array เสมอเมื่อต้องส่งข้อมูลข้าม Layer 
  • ใช้ Enum แทน Magic String ทุกครั้ง 
  • เขียน Query แยกออกจาก Action ทันที เมื่อเป็นงานดึงข้อมูลเพื่อทำ Report 
  • ใช้วิธี Inject Service เข้ามาใน Controller ผ่าน Constructor 
สิ่งที่ไม่ควรทำ (Don'ts)
  • ห้ามเขียน Business Logic ใน Controller หรือ Model 
  • หลีกเลี่ยงการเรียก Eloquent โดยตรงใน Controller (ควรเรียกผ่าน Action หรือ Query) 
  • ห้ามใช้ Service กับงานง่ายๆ ที่มีแค่ขั้นตอนเดียว (ให้ใช้ Action แทน) 
  • ห้ามแก้ไขเปลี่ยนแปลงข้อมูล (Write) ภายในโฟลเดอร์ Query 
  • ห้ามส่ง Request Object เข้าไปใน Action หรือ Service โดยตรง (ต้องแปลงเป็น DTO ก่อน) 
 สรุปการใช้งานด่วน (Quick Reference — ใช้อะไรเมื่อไหร่?) 

สถานการณ์                                                        | ควรใช้...
------------------------------------------------------------------------------------------------------------------------------
สร้าง / แก้ไข / ลบข้อมูล (ทำงานกับ 1 Model)            | Action
------------------------------------------------------------------------------------------------------------------------------
งานที่ผูกกับหลาย Model หรือมีกระบวนการหลายขั้นตอน | Service
------------------------------------------------------------------------------------------------------------------------------
เรียกใช้งาน Payment, Email, หรือ SMS API              | Service
------------------------------------------------------------------------------------------------------------------------------
ดึงข้อมูลสำหรับทำ Report หรือ Dashboard              | Query
------------------------------------------------------------------------------------------------------------------------------
ดึงข้อมูลแบบธรรมดาทั่วไป (เช่น find, paginate)         | Controller สามารถเรียก Model ได้โดยตรงผ่าน Query ง่ายๆ
------------------------------------------------------------------------------------------------------------------------------
ส่งชุดข้อมูลข้ามระหว่าง Layer                               | DTO
------------------------------------------------------------------------------------------------------------------------------
กำหนดค่าสถานะ (เช่น status, role, type)                 | Enum
------------------------------------------------------------------------------------------------------------------------------


laravel