- สร้าง REST API ด้วย Laravel 13: ตั้งแต่เริ่มต้นจนพร้อมใช้งาน
- 1. สิ่งที่ต้องเตรียม
- 2. สร้าง Laravel Project
- 3. เปิดใช้งาน API Routes
- 4. ตั้งค่า Database
- 5. สร้าง Model และ Migration
- 6. กำหนด Product Model
- 7. สร้าง Form Request สำหรับ Validation
- 8. สร้าง API Resource
- 9. สร้าง API Controller
- 10. กำหนด API Routes
- 11. ทดสอบ Create Product
- 12. ทดสอบ Get Products
- 13. ทดสอบ Get Product By ID
- 14. ทดสอบ Update Product
- 15. ทดสอบ Delete Product
- 16. Validation Error
- 17. เพิ่ม Search และ Filter
- 18. Versioning API
- 19. ป้องกัน API ด้วย Laravel Sanctum
- 20. HTTP Status Code ที่ควรรู้
- 21. โครงสร้างโปรเจกต์ที่เกี่ยวข้อง
- 22. Data Flow ของ Laravel API
- 23. แนวทางที่ควรใช้ใน Production
- 24. ตัวอย่าง Feature Test
- 25. สรุปคำสั่งสำคัญ
- สรุป
- เอกสารอ้างอิง
#สร้าง REST API ด้วย Laravel 13: ตั้งแต่เริ่มต้นจนพร้อมใช้งาน
Laravel เป็น PHP Framework ที่เหมาะทั้งสำหรับการพัฒนา Web Application แบบ Full Stack และการทำหน้าที่เป็น API Backend ให้กับ Frontend เช่น React, Vue, Next.js, Mobile Application หรือระบบ Microservices
บทความนี้สาธิตการสร้าง REST API สำหรับจัดการสินค้า (Product API) ด้วย Laravel 13 โดยครอบคลุมตั้งแต่การสร้างโปรเจกต์ ไปจนถึง CRUD, Validation, API Resource และแนวทางเพิ่ม Authentication ด้วย Laravel Sanctum
API ที่เราจะสร้างมี Endpoint หลักดังนี้
| Method | Endpoint | หน้าที่ |
|---|---|---|
GET |
/api/products |
แสดงรายการสินค้า |
POST |
/api/products |
เพิ่มสินค้า |
GET |
/api/products/{product} |
ดูรายละเอียดสินค้า |
PUT/PATCH |
/api/products/{product} |
แก้ไขสินค้า |
DELETE |
/api/products/{product} |
ลบสินค้า |
#1. สิ่งที่ต้องเตรียม
เครื่องควรมีเครื่องมือพื้นฐานดังนี้
- PHP
- Composer
- Laravel Installer
- Database เช่น SQLite, MySQL หรือ PostgreSQL
- API Client เช่น Postman, Bruno, Insomnia หรือ
curl
ตรวจสอบ PHP และ Composer
php -v
composer --version
ติดตั้ง Laravel Installer หากยังไม่มี
composer global require laravel/installer
#2. สร้าง Laravel Project
สร้างโปรเจกต์ใหม่
laravel new laravel-api
เข้าไปในโฟลเดอร์โปรเจกต์
cd laravel-api
ทดลองรัน Development Server
php artisan serve
จากนั้นเปิด
http://127.0.0.1:8000
Laravel รุ่นใหม่สามารถใช้คำสั่ง
composer run dev
เพื่อรัน Development Services ตามที่โปรเจกต์กำหนดไว้ได้เช่นกัน
#3. เปิดใช้งาน API Routes
Laravel สามารถติดตั้งส่วนที่จำเป็นสำหรับ API ด้วยคำสั่ง
php artisan install:api
คำสั่งนี้จะเตรียม API routing และ Laravel Sanctum สำหรับการทำ Authentication แบบ API
หลังติดตั้งแล้วจะมีไฟล์
routes/api.php
Route ที่อยู่ในไฟล์นี้จะมี prefix /api โดยอัตโนมัติ
ตัวอย่าง
<?php
use Illuminate\Support\Facades\Route;
Route::get('/hello', function () {
return response()->json([
'message' => 'Hello Laravel API',
]);
});
เรียกใช้งานได้ที่
GET /api/hello
ทดสอบด้วย
curl http://127.0.0.1:8000/api/hello
ผลลัพธ์
{
"message": "Hello Laravel API"
}
#4. ตั้งค่า Database
Laravel สามารถใช้ SQLite สำหรับการทดลองได้อย่างสะดวก หรือเปลี่ยนไปใช้ MySQL/PostgreSQL ใน .env
ตัวอย่าง MySQL
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_api
DB_USERNAME=root
DB_PASSWORD=
จากนั้นสร้างฐานข้อมูล laravel_api ให้เรียบร้อย
#5. สร้าง Model และ Migration
เราจะสร้าง Model ชื่อ Product
php artisan make:model Product -m
คำสั่งนี้สร้าง
app/Models/Product.php
database/migrations/xxxx_xx_xx_xxxxxx_create_products_table.php
แก้ไข Migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('sku')->unique();
$table->text('description')->nullable();
$table->decimal('price', 10, 2);
$table->unsignedInteger('stock')->default(0);
$table->boolean('is_active')->default(true);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('products');
}
};
รัน Migration
php artisan migrate
#6. กำหนด Product Model
เปิดไฟล์
app/Models/Product.php
กำหนดฟิลด์ที่อนุญาตให้ Mass Assignment
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = [
'name',
'sku',
'description',
'price',
'stock',
'is_active',
];
protected function casts(): array
{
return [
'price' => 'decimal:2',
'stock' => 'integer',
'is_active' => 'boolean',
];
}
}
$fillable ช่วยควบคุมว่าฟิลด์ใดสามารถส่งเข้า Product::create() หรือ $product->update() ได้
#7. สร้าง Form Request สำหรับ Validation
ในงานจริงควรแยก Validation ออกจาก Controller เพื่อให้โค้ดดูแลง่าย
สร้าง Request สำหรับการเพิ่มสินค้า
php artisan make:request StoreProductRequest
สร้าง Request สำหรับการแก้ไขสินค้า
php artisan make:request UpdateProductRequest
#StoreProductRequest
แก้ไข
app/Http/Requests/StoreProductRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreProductRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'sku' => ['required', 'string', 'max:100', 'unique:products,sku'],
'description' => ['nullable', 'string'],
'price' => ['required', 'numeric', 'min:0'],
'stock' => ['required', 'integer', 'min:0'],
'is_active' => ['sometimes', 'boolean'],
];
}
}
#UpdateProductRequest
แก้ไข
app/Http/Requests/UpdateProductRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class UpdateProductRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => ['sometimes', 'required', 'string', 'max:255'],
'sku' => [
'sometimes',
'required',
'string',
'max:100',
Rule::unique('products', 'sku')
->ignore($this->route('product')),
],
'description' => ['nullable', 'string'],
'price' => ['sometimes', 'required', 'numeric', 'min:0'],
'stock' => ['sometimes', 'required', 'integer', 'min:0'],
'is_active' => ['sometimes', 'boolean'],
];
}
}
เมื่อ Validation ของ API ไม่ผ่าน Laravel จะส่ง JSON response พร้อม HTTP status 422 Unprocessable Entity
#8. สร้าง API Resource
ไม่ควรคืน Eloquent Model ตรง ๆ ในทุกกรณี เพราะโครงสร้างฐานข้อมูลอาจเปลี่ยนได้ การใช้ API Resource ช่วยสร้างชั้นสำหรับกำหนดรูปแบบ JSON Response
สร้าง Resource
php artisan make:resource ProductResource
แก้ไข
app/Http/Resources/ProductResource.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ProductResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'sku' => $this->sku,
'description' => $this->description,
'price' => (float) $this->price,
'stock' => $this->stock,
'is_active' => $this->is_active,
'created_at' => $this->created_at?->toISOString(),
'updated_at' => $this->updated_at?->toISOString(),
];
}
}
#9. สร้าง API Controller
สร้าง Controller
php artisan make:controller Api/ProductController --api
แก้ไข
app/Http/Controllers/Api/ProductController.php
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreProductRequest;
use App\Http\Requests\UpdateProductRequest;
use App\Http\Resources\ProductResource;
use App\Models\Product;
use Illuminate\Http\Response;
class ProductController extends Controller
{
public function index()
{
$products = Product::query()
->latest()
->paginate(10);
return ProductResource::collection($products);
}
public function store(StoreProductRequest $request)
{
$product = Product::create($request->validated());
return (new ProductResource($product))
->response()
->setStatusCode(Response::HTTP_CREATED);
}
public function show(Product $product)
{
return new ProductResource($product);
}
public function update(
UpdateProductRequest $request,
Product $product
) {
$product->update($request->validated());
return new ProductResource($product->refresh());
}
public function destroy(Product $product)
{
$product->delete();
return response()->noContent();
}
}
จุดสำคัญคือ Laravel ใช้ Route Model Binding ดังนั้น parameter
Product $product
จะถูกค้นหาจาก {product} ใน URL ให้อัตโนมัติ
หากไม่พบข้อมูล Laravel จะตอบกลับ 404 Not Found
#10. กำหนด API Routes
เปิด
routes/api.php
เพิ่ม
<?php
use App\Http\Controllers\Api\ProductController;
use Illuminate\Support\Facades\Route;
Route::apiResource('products', ProductController::class);
เพียงบรรทัดเดียว Laravel จะสร้าง RESTful routes ที่จำเป็น
ตรวจสอบ Route
php artisan route:list --path=api
โครงสร้างจะใกล้เคียงกับ
GET|HEAD api/products
POST api/products
GET|HEAD api/products/{product}
PUT|PATCH api/products/{product}
DELETE api/products/{product}
#11. ทดสอบ Create Product
ส่ง Request
curl -X POST http://127.0.0.1:8000/api/products \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "Mechanical Keyboard",
"sku": "KB-001",
"description": "75% mechanical keyboard",
"price": 2490,
"stock": 20,
"is_active": true
}'
ตัวอย่าง Response
{
"data": {
"id": 1,
"name": "Mechanical Keyboard",
"sku": "KB-001",
"description": "75% mechanical keyboard",
"price": 2490,
"stock": 20,
"is_active": true,
"created_at": "2026-09-15T01:00:00.000000Z",
"updated_at": "2026-09-15T01:00:00.000000Z"
}
}
HTTP Status ที่เหมาะสมคือ
201 Created
#12. ทดสอบ Get Products
curl \
-H "Accept: application/json" \
http://127.0.0.1:8000/api/products
เนื่องจาก Controller ใช้
paginate(10)
Response จะมีทั้งข้อมูลสินค้าและข้อมูล Pagination
#13. ทดสอบ Get Product By ID
curl \
-H "Accept: application/json" \
http://127.0.0.1:8000/api/products/1
#14. ทดสอบ Update Product
curl -X PATCH http://127.0.0.1:8000/api/products/1 \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"price": 2290,
"stock": 15
}'
การใช้ PATCH เหมาะกับการแก้ไขบางฟิลด์ โดยไม่จำเป็นต้องส่งข้อมูลทั้งหมด
#15. ทดสอบ Delete Product
curl -X DELETE \
-H "Accept: application/json" \
http://127.0.0.1:8000/api/products/1
เมื่อสำเร็จ API ควรตอบ
204 No Content
#16. Validation Error
ลองส่งข้อมูลที่ไม่ครบ
curl -X POST http://127.0.0.1:8000/api/products \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "",
"price": -100
}'
Laravel จะคืน Validation Error ในรูปแบบ JSON พร้อม status 422
ตัวอย่างแนวคิดของ Response
{
"message": "The name field is required. (and more errors)",
"errors": {
"name": [
"The name field is required."
],
"sku": [
"The sku field is required."
],
"price": [
"The price field must be at least 0."
],
"stock": [
"The stock field is required."
]
}
}
#17. เพิ่ม Search และ Filter
เราสามารถขยาย index() ให้ค้นหาสินค้าได้
public function index()
{
$products = Product::query()
->when(request('search'), function ($query, $search) {
$query->where(function ($query) use ($search) {
$query
->where('name', 'like', "%{$search}%")
->orWhere('sku', 'like', "%{$search}%");
});
})
->when(
request()->has('active'),
fn ($query) => $query->where(
'is_active',
request()->boolean('active')
)
)
->latest()
->paginate(10)
->withQueryString();
return ProductResource::collection($products);
}
เรียกใช้งาน
GET /api/products?search=keyboard
หรือ
GET /api/products?active=1
#18. Versioning API
เมื่อระบบเริ่มมี Client หลายรุ่น ควรพิจารณา API Versioning
ตัวอย่าง
Route::prefix('v1')->group(function () {
Route::apiResource('products', ProductController::class);
});
Endpoint จะกลายเป็น
/api/v1/products
ข้อดีคือสามารถพัฒนา /api/v2/... ในอนาคตโดยลดผลกระทบต่อ Client เดิม
#19. ป้องกัน API ด้วย Laravel Sanctum
หาก API ต้องการ Authentication สามารถใช้ Laravel Sanctum ได้
หลังจาก
php artisan install:api
เราสามารถป้องกัน Routes ด้วย middleware
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('products', ProductController::class);
});
Request ที่ใช้ Personal Access Token จะส่ง Header ลักษณะ
Authorization: Bearer YOUR_API_TOKEN
แนวคิดนี้เหมาะสำหรับ Mobile App, Internal API หรือ API ที่ใช้ Token Authentication
สำหรับ SPA ที่อยู่ใน first-party domain ควรศึกษา Sanctum SPA Authentication เพิ่มเติม เพราะรูปแบบการยืนยันตัวตนแตกต่างจาก Personal Access Token
#20. HTTP Status Code ที่ควรรู้
| Status | ความหมาย | ตัวอย่าง |
|---|---|---|
200 OK |
Request สำเร็จ | อ่าน/แก้ไขข้อมูล |
201 Created |
สร้าง Resource สำเร็จ | POST |
204 No Content |
สำเร็จแต่ไม่มี Response Body | DELETE |
401 Unauthorized |
ยังไม่ได้ Authentication | Token ไม่ถูกต้อง/ไม่มี Token |
403 Forbidden |
ไม่มีสิทธิ์ | ผ่าน Authentication แต่ไม่มี Permission |
404 Not Found |
ไม่พบ Resource | Product ID ไม่มี |
422 Unprocessable Entity |
Validation ไม่ผ่าน | Input ไม่ถูกต้อง |
429 Too Many Requests |
Request มากเกิน Rate Limit | API ถูกเรียกถี่เกินไป |
500 Internal Server Error |
Server Error | Exception ที่ไม่ได้จัดการ |
#21. โครงสร้างโปรเจกต์ที่เกี่ยวข้อง
หลังทำ Tutorial นี้ ส่วนสำคัญจะมีประมาณนี้
app/
├── Http/
│ ├── Controllers/
│ │ └── Api/
│ │ └── ProductController.php
│ ├── Requests/
│ │ ├── StoreProductRequest.php
│ │ └── UpdateProductRequest.php
│ └── Resources/
│ └── ProductResource.php
└── Models/
└── Product.php
database/
└── migrations/
└── xxxx_xx_xx_xxxxxx_create_products_table.php
routes/
└── api.php
โครงสร้างนี้แยกหน้าที่ชัดเจน
- Route — กำหนด URL และ HTTP Method
- Controller — จัดการ Application Flow
- Form Request — ตรวจสอบ Input
- Model — ติดต่อและจัดการข้อมูล
- API Resource — กำหนด JSON Output
- Sanctum / Middleware — Authentication และ Authorization
#22. Data Flow ของ Laravel API
ภาพรวมการทำงานสามารถอธิบายได้ดังนี้
Client
|
| HTTP Request
v
Route
|
v
Middleware
|
v
Form Request Validation
|
v
Controller
|
v
Eloquent Model
|
v
Database
|
v
API Resource
|
v
JSON Response
การแยก Layer แบบนี้ทำให้ระบบสามารถขยายและทดสอบได้ง่ายกว่าเขียน Business Logic ทั้งหมดไว้ใน Route หรือ Controller
#23. แนวทางที่ควรใช้ใน Production
เมื่อ API เริ่มใช้งานจริง ควรพิจารณาประเด็นต่อไปนี้
#ใช้ Form Request
หลีกเลี่ยง Validation ขนาดใหญ่ใน Controller เพราะจะทำให้ Controller ซับซ้อน
#ใช้ API Resource
อย่าผูก JSON Response กับ Database Schema โดยตรง
#ใช้ Pagination
Endpoint ที่คืน Collection ไม่ควรโหลดข้อมูลทั้งหมดแบบไม่จำกัด
Product::paginate(20);
#ใช้ Authentication และ Authorization
Authentication ตอบว่า ผู้ใช้คือใคร
Authorization ตอบว่า ผู้ใช้ทำอะไรได้บ้าง
Laravel สามารถใช้ Policy, Gate และ Sanctum เพื่อควบคุมสิทธิ์ได้
#ใช้ Rate Limiting
ช่วยลด Abuse, Bot และ Request ที่ผิดปกติ
#เขียน Automated Tests
API ควรมี Feature Tests ครอบคลุม Happy Path และ Error Cases
#ทำ API Documentation
สำหรับทีมพัฒนาและ Client ควรมีเอกสาร API เช่น OpenAPI/Swagger
#ใช้ HTTPS
Production API ควรให้บริการผ่าน HTTPS เสมอ
#Logging และ Monitoring
ควรเก็บ Logs และ Metrics เพื่อวิเคราะห์ปัญหาเมื่อระบบจริงเกิด Error
#24. ตัวอย่าง Feature Test
สร้าง Test
php artisan make:test ProductApiTest
ตัวอย่าง
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ProductApiTest extends TestCase
{
use RefreshDatabase;
public function test_can_create_product(): void
{
$response = $this->postJson('/api/products', [
'name' => 'Mechanical Keyboard',
'sku' => 'KB-001',
'price' => 2490,
'stock' => 10,
'is_active' => true,
]);
$response
->assertCreated()
->assertJsonPath('data.name', 'Mechanical Keyboard');
$this->assertDatabaseHas('products', [
'sku' => 'KB-001',
]);
}
public function test_product_requires_valid_data(): void
{
$response = $this->postJson('/api/products', []);
$response
->assertUnprocessable()
->assertJsonValidationErrors([
'name',
'sku',
'price',
'stock',
]);
}
}
รัน Test
php artisan test
หรือเลือกเฉพาะไฟล์
php artisan test tests/Feature/ProductApiTest.php
#25. สรุปคำสั่งสำคัญ
# สร้างโปรเจกต์
laravel new laravel-api
cd laravel-api
# เปิดใช้งาน API + Sanctum
php artisan install:api
# สร้าง Model และ Migration
php artisan make:model Product -m
# สร้าง Form Requests
php artisan make:request StoreProductRequest
php artisan make:request UpdateProductRequest
# สร้าง API Resource
php artisan make:resource ProductResource
# สร้าง API Controller
php artisan make:controller Api/ProductController --api
# สร้างฐานข้อมูลตาม Migration
php artisan migrate
# ดู API Routes
php artisan route:list --path=api
# รัน Development Server
php artisan serve
# รัน Automated Tests
php artisan test
#สรุป
การสร้าง REST API ด้วย Laravel สามารถพัฒนาได้อย่างเป็นระบบโดยใช้เครื่องมือที่ Framework เตรียมไว้ ได้แก่
Route
↓
Middleware
↓
Form Request
↓
Controller
↓
Eloquent Model
↓
Database
↓
API Resource
↓
JSON Response
สำหรับ API ขนาดเล็ก เราสามารถเริ่มจาก Route::apiResource() และ Controller แบบ CRUD ได้ทันที แต่เมื่อระบบใหญ่ขึ้นควรค่อย ๆ เพิ่ม Service Layer, Policies, Authentication, Caching, Queue, API Versioning, Automated Testing และ Observability ตามความเหมาะสม
Laravel จึงเหมาะทั้งกับการสร้าง API สำหรับ Web/Mobile Application และการพัฒนา Backend Service ที่ต้องการโครงสร้างชัดเจนและขยายต่อได้ง่าย
#เอกสารอ้างอิง
- Laravel Documentation: https://laravel.com/docs
- Laravel Installation: https://laravel.com/docs/13.x/installation
- Laravel Routing: https://laravel.com/docs/13.x/routing
- Laravel Controllers: https://laravel.com/docs/13.x/controllers
- Laravel Validation: https://laravel.com/docs/13.x/validation
- Laravel Eloquent: https://laravel.com/docs/13.x/eloquent
- Laravel API Resources: https://laravel.com/docs/13.x/eloquent-resources
- Laravel Sanctum: https://laravel.com/docs/13.x/sanctum