REST API คืออะไร?
REST (Representational State Transfer) เป็นสถาปัตยกรรมการออกแบบ API ที่ใช้หลักการของ HTTP protocol โดยมีหลักการสำคัญคือ:
- Stateless – ไม่เก็บสถานะของ client
- Client-Server Architecture – แยกการทำงานระหว่าง client และ server
- Cacheable – สามารถ cache ข้อมูลได้
- Uniform Interface – ใช้รูปแบบการเรียกที่เป็นมาตรฐาน
- Layered System – ระบบสามารถมีหลายชั้น
HTTP Methods ที่ใช้ใน REST API
- GET – ดึงข้อมูล
- POST – สร้างข้อมูลใหม่
- PUT – อัพเดทข้อมูลทั้งหมด
- PATCH – อัพเดทข้อมูลบางส่วน
- DELETE – ลบข้อมูล
ตัวอย่างการพัฒนา REST API ด้วย PHP
การตั้งค่าเบื้องต้น
<?php
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET,POST,PUT,DELETE");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// เชื่อมต่อฐานข้อมูล
$conn = new mysqli("localhost", "username", "password", "db_name");
<?php
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET,POST,PUT,DELETE");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// เชื่อมต่อฐานข้อมูล
$conn = new mysqli("localhost", "username", "password", "db_name");
<?php header("Content-Type: application/json; charset=UTF-8"); header("Access-Control-Allow-Methods: GET,POST,PUT,DELETE"); header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); // เชื่อมต่อฐานข้อมูล $conn = new mysqli("localhost", "username", "password", "db_name");
การสร้าง API Endpoints
<?php
// GET /api/users - ดึงรายการผู้ใช้ทั้งหมด
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$sql = "SELECT * FROM users";
$result = $conn->query($sql);
$users = [];
while($row = $result->fetch_assoc()) {
$users[] = $row;
}
echo json_encode(['status' => 'success', 'data' => $users]);
}
// POST /api/users - สร้างผู้ใช้ใหม่
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = json_decode(file_get_contents("php://input"));
$sql = "INSERT INTO users (name, email) VALUES (?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $data->name, $data->email);
if ($stmt->execute()) {
echo json_encode(['status' => 'success', 'message' => 'User created']);
} else {
echo json_encode(['status' => 'error', 'message' => $conn->error]);
}
}
<?php
// GET /api/users - ดึงรายการผู้ใช้ทั้งหมด
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$sql = "SELECT * FROM users";
$result = $conn->query($sql);
$users = [];
while($row = $result->fetch_assoc()) {
$users[] = $row;
}
echo json_encode(['status' => 'success', 'data' => $users]);
}
// POST /api/users - สร้างผู้ใช้ใหม่
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = json_decode(file_get_contents("php://input"));
$sql = "INSERT INTO users (name, email) VALUES (?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $data->name, $data->email);
if ($stmt->execute()) {
echo json_encode(['status' => 'success', 'message' => 'User created']);
} else {
echo json_encode(['status' => 'error', 'message' => $conn->error]);
}
}
<?php // GET /api/users - ดึงรายการผู้ใช้ทั้งหมด if ($_SERVER['REQUEST_METHOD'] === 'GET') { $sql = "SELECT * FROM users"; $result = $conn->query($sql); $users = []; while($row = $result->fetch_assoc()) { $users[] = $row; } echo json_encode(['status' => 'success', 'data' => $users]); } // POST /api/users - สร้างผู้ใช้ใหม่ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $data = json_decode(file_get_contents("php://input")); $sql = "INSERT INTO users (name, email) VALUES (?, ?)"; $stmt = $conn->prepare($sql); $stmt->bind_param("ss", $data->name, $data->email); if ($stmt->execute()) { echo json_encode(['status' => 'success', 'message' => 'User created']); } else { echo json_encode(['status' => 'error', 'message' => $conn->error]); } }
ตัวอย่างการพัฒนา REST API ด้วย Node.js และ Express
การตั้งค่าเบื้องต้น
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
// เชื่อมต่อ MongoDB ด้วย Mongoose
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/api_db', { useNewUrlParser: true });
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
// เชื่อมต่อ MongoDB ด้วย Mongoose
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/api_db', { useNewUrlParser: true });
const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json()); // เชื่อมต่อ MongoDB ด้วย Mongoose const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/api_db', { useNewUrlParser: true });
การสร้าง Model
const userSchema = new mongoose.Schema({
name: String,
email: String,
createdAt: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
const userSchema = new mongoose.Schema({
name: String,
email: String,
createdAt: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
const userSchema = new mongoose.Schema({ name: String, email: String, createdAt: { type: Date, default: Date.now } }); const User = mongoose.model('User', userSchema);
การสร้าง API Routes
// GET /api/users - ดึงรายการผู้ใช้ทั้งหมด
app.get('/api/users', async (req, res) => {
try {
const users = await User.find();
res.json({ status: 'success', data: users });
} catch (err) {
res.status(500).json({ status: 'error', message: err.message });
}
});
// POST /api/users - สร้างผู้ใช้ใหม่
app.post('/api/users', async (req, res) => {
try {
const user = new User({
name: req.body.name,
email: req.body.email
});
const newUser = await user.save();
res.status(201).json({ status: 'success', data: newUser });
} catch (err) {
res.status(400).json({ status: 'error', message: err.message });
}
});
// PUT /api/users/:id - อัพเดทข้อมูลผู้ใช้
app.put('/api/users/:id', async (req, res) => {
try {
const user = await User.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true }
);
res.json({ status: 'success', data: user });
} catch (err) {
res.status(400).json({ status: 'error', message: err.message });
}
});
// DELETE /api/users/:id - ลบผู้ใช้
app.delete('/api/users/:id', async (req, res) => {
try {
await User.findByIdAndDelete(req.params.id);
res.json({ status: 'success', message: 'User deleted' });
} catch (err) {
res.status(500).json({ status: 'error', message: err.message });
}
});
// GET /api/users - ดึงรายการผู้ใช้ทั้งหมด
app.get('/api/users', async (req, res) => {
try {
const users = await User.find();
res.json({ status: 'success', data: users });
} catch (err) {
res.status(500).json({ status: 'error', message: err.message });
}
});
// POST /api/users - สร้างผู้ใช้ใหม่
app.post('/api/users', async (req, res) => {
try {
const user = new User({
name: req.body.name,
email: req.body.email
});
const newUser = await user.save();
res.status(201).json({ status: 'success', data: newUser });
} catch (err) {
res.status(400).json({ status: 'error', message: err.message });
}
});
// PUT /api/users/:id - อัพเดทข้อมูลผู้ใช้
app.put('/api/users/:id', async (req, res) => {
try {
const user = await User.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true }
);
res.json({ status: 'success', data: user });
} catch (err) {
res.status(400).json({ status: 'error', message: err.message });
}
});
// DELETE /api/users/:id - ลบผู้ใช้
app.delete('/api/users/:id', async (req, res) => {
try {
await User.findByIdAndDelete(req.params.id);
res.json({ status: 'success', message: 'User deleted' });
} catch (err) {
res.status(500).json({ status: 'error', message: err.message });
}
});
// GET /api/users - ดึงรายการผู้ใช้ทั้งหมด app.get('/api/users', async (req, res) => { try { const users = await User.find(); res.json({ status: 'success', data: users }); } catch (err) { res.status(500).json({ status: 'error', message: err.message }); } }); // POST /api/users - สร้างผู้ใช้ใหม่ app.post('/api/users', async (req, res) => { try { const user = new User({ name: req.body.name, email: req.body.email }); const newUser = await user.save(); res.status(201).json({ status: 'success', data: newUser }); } catch (err) { res.status(400).json({ status: 'error', message: err.message }); } }); // PUT /api/users/:id - อัพเดทข้อมูลผู้ใช้ app.put('/api/users/:id', async (req, res) => { try { const user = await User.findByIdAndUpdate( req.params.id, req.body, { new: true } ); res.json({ status: 'success', data: user }); } catch (err) { res.status(400).json({ status: 'error', message: err.message }); } }); // DELETE /api/users/:id - ลบผู้ใช้ app.delete('/api/users/:id', async (req, res) => { try { await User.findByIdAndDelete(req.params.id); res.json({ status: 'success', message: 'User deleted' }); } catch (err) { res.status(500).json({ status: 'error', message: err.message }); } });
แนวทางการพัฒนา REST API ที่ดี
- การจัดการ Response
// ตัวอย่างรูปแบบ Response ที่ดี
{
"status": "success",
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
"message": "User created successfully"
}
// ตัวอย่างรูปแบบ Response ที่ดี
{
"status": "success",
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
"message": "User created successfully"
}
// ตัวอย่างรูปแบบ Response ที่ดี { "status": "success", "data": { "id": 1, "name": "John Doe", "email": "john@example.com" }, "message": "User created successfully" }
2. การจัดการ Error
// ตัวอย่างรูปแบบ Error Response
{
"status": "error",
"code": 400,
"message": "Invalid email format",
"errors": [
{
"field": "email",
"message": "Email is not valid"
}
]
}
// ตัวอย่างรูปแบบ Error Response
{
"status": "error",
"code": 400,
"message": "Invalid email format",
"errors": [
{
"field": "email",
"message": "Email is not valid"
}
]
}
// ตัวอย่างรูปแบบ Error Response { "status": "error", "code": 400, "message": "Invalid email format", "errors": [ { "field": "email", "message": "Email is not valid" } ] }
- การตั้งชื่อ Endpoints
- ใช้คำนาม แทนคำกริยา:
/api/users
แทน/api/getUsers
- ใช้ตัวพิมพ์เล็กทั้งหมด
- ใช้ขีดกลางในการแบ่งคำ:
/api/user-profiles
- การจัดการ Version
/api/v1/users
/api/v2/users
/api/v1/users
/api/v2/users
/api/v1/users /api/v2/users
- การใช้ HTTP Status Codes ที่เหมาะสม
- 200 OK – สำเร็จ
- 201 Created – สร้างข้อมูลสำเร็จ
- 400 Bad Request – ข้อมูลไม่ถูกต้อง
- 401 Unauthorized – ไม่ได้ยืนยันตัวตน
- 403 Forbidden – ไม่มีสิทธิ์
- 404 Not Found – ไม่พบข้อมูล
- 500 Internal Server Error – เกิดข้อผิดพลาดที่เซิร์ฟเวอร์
การรักษาความปลอดภัย
- การใช้ JWT (JSON Web Tokens)
// Node.js example
const jwt = require('jsonwebtoken');
// สร้าง token
const token = jwt.sign({ userId: user.id }, 'secret_key', { expiresIn: '1h' });
// ตรวจสอบ token
const verifyToken = (req, res, next) => {
const token = req.headers.authorization;
if (!token) return res.status(401).json({ message: 'Token required' });
try {
const decoded = jwt.verify(token, 'secret_key');
req.user = decoded;
next();
} catch (err) {
res.status(401).json({ message: 'Invalid token' });
}
};
// Node.js example
const jwt = require('jsonwebtoken');
// สร้าง token
const token = jwt.sign({ userId: user.id }, 'secret_key', { expiresIn: '1h' });
// ตรวจสอบ token
const verifyToken = (req, res, next) => {
const token = req.headers.authorization;
if (!token) return res.status(401).json({ message: 'Token required' });
try {
const decoded = jwt.verify(token, 'secret_key');
req.user = decoded;
next();
} catch (err) {
res.status(401).json({ message: 'Invalid token' });
}
};
// Node.js example const jwt = require('jsonwebtoken'); // สร้าง token const token = jwt.sign({ userId: user.id }, 'secret_key', { expiresIn: '1h' }); // ตรวจสอบ token const verifyToken = (req, res, next) => { const token = req.headers.authorization; if (!token) return res.status(401).json({ message: 'Token required' }); try { const decoded = jwt.verify(token, 'secret_key'); req.user = decoded; next(); } catch (err) { res.status(401).json({ message: 'Invalid token' }); } };
- การป้องกัน SQL Injection
- ใช้ Prepared Statements
- ใช้ ORM
- Sanitize ข้อมูล input
- การจำกัด Rate Limiting
// Node.js example using express-rate-limit
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 นาที
max: 100 // จำกัด 100 requests ต่อ IP
});
app.use('/api/', limiter);
// Node.js example using express-rate-limit
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 นาที
max: 100 // จำกัด 100 requests ต่อ IP
});
app.use('/api/', limiter);
// Node.js example using express-rate-limit const rateLimit = require('express-rate-limit'); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 นาที max: 100 // จำกัด 100 requests ต่อ IP }); app.use('/api/', limiter);
การทดสอบ API
- ใช้เครื่องมือทดสอบ
- Postman
- curl
- Jest (สำหรับ Node.js)
- PHPUnit (สำหรับ PHP)
- ตัวอย่างการทดสอบด้วย Jest
describe('User API', () => {
test('should create a new user', async () => {
const res = await request(app)
.post('/api/users')
.send({
name: 'Test User',
email: 'test@example.com'
});
expect(res.statusCode).toBe(201);
expect(res.body.data).toHaveProperty('name', 'Test User');
});
});
describe('User API', () => {
test('should create a new user', async () => {
const res = await request(app)
.post('/api/users')
.send({
name: 'Test User',
email: 'test@example.com'
});
expect(res.statusCode).toBe(201);
expect(res.body.data).toHaveProperty('name', 'Test User');
});
});
describe('User API', () => { test('should create a new user', async () => { const res = await request(app) .post('/api/users') .send({ name: 'Test User', email: 'test@example.com' }); expect(res.statusCode).toBe(201); expect(res.body.data).toHaveProperty('name', 'Test User'); }); });