[Series] Xây dựng RESTful API từ con số 0 với PHP Thuần & MVC - Phần 23: API Danh sách Đơn hàng cá nhân (My Orders)
Chào các bạn, mình đã quay trở lại!
Trong một hệ thống eCommerce, sau khi khách hàng bấm nút "Đặt hàng", tâm lý chung là họ muốn kiểm tra ngay xem đơn hàng đã được ghi nhận chưa. API mà chúng ta xây dựng hôm nay sẽ đóng vai trò cung cấp dữ liệu cho trang "Lịch sử mua hàng". Chúng ta sẽ sử dụng kỹ thuật LEFT JOIN để lấy kèm thông tin địa chỉ giao hàng, giúp dữ liệu trả về đầy đủ và hữu ích hơn cho Frontend.
1. Tư duy xử lý dữ liệu (Database Query)
Dữ liệu đơn hàng nằm ở bảng Orders, nhưng để người dùng biết họ đã đặt giao đến đâu, chúng ta cần kết nối với bảng Shipping_Addresses.
Câu lệnh SQL trọng tâm:
SELECT o.id, o.total_price, o.status, o.created_at, sa.full_name, sa.address, sa.phone
FROM Orders o
LEFT JOIN Shipping_Addresses sa ON o.shipping_address_id = sa.id
WHERE o.user_id = ?
ORDER BY o.created_at DESC
Lưu ý: Chúng ta dùng DESC để những đơn hàng mới đặt luôn hiện lên đầu danh sách.
2. Tầng Model: Truy vấn theo User (Order.php)
Chúng ta bổ sung thêm hàm getByUser vào Model Order để lọc chính xác đơn hàng của người đang đăng nhập.
File: app/Models/Order.php (Bổ sung)
<?php
namespace App\Models;
// ... (Các hàm create, updateStatus đã viết ở bài trước)
/**
* Lấy toàn bộ đơn hàng của một User, kèm thông tin địa chỉ
*/
public function getByUser($userId) {
$stmt = $this->db->prepare("
SELECT o.id, o.total_price, o.status, o.created_at,
sa.full_name, sa.address, sa.phone
FROM Orders o
LEFT JOIN Shipping_Addresses sa ON o.shipping_address_id = sa.id
WHERE o.user_id = ?
ORDER BY o.created_at DESC
");
$stmt->execute([$userId]);
return $stmt->fetchAll();
}
3. Tầng Controller: Bảo mật dữ liệu (OrderController.php)
Tại Controller, việc quan trọng nhất là trích xuất user_id từ JWT Token. Chúng ta tuyệt đối không tin tưởng vào ID gửi lên từ Client để tránh việc User A xem được đơn hàng của User B.
File:app/Controllers/OrderController.php (Bổ sung)
<?php
namespace App\Controllers;
use App\Core\Response;
use App\Models\Order;
use App\Middleware\AuthMiddleware;
class OrderController
{
// ...
/**
* API: Lấy danh sách đơn hàng của tôi
*/
public function myOrders() {
// 1. Kiểm tra Token và lấy thông tin User
$user = AuthMiddleware::check();
// 2. Gọi Model xử lý lấy dữ liệu
$orderModel = new Order();
$orders = $orderModel->getByUser($user->sub); // sub thường chứa User ID trong JWT
// 3. Trả về JSON cho Frontend
Response::json([
'status' => 'success',
'count' => count($orders),
'orders' => $orders
]);
}
}
4. Cấu hình Route (index.php)
Thêm một "ngã rẽ" mới cho danh sách đơn hàng cá nhân.
File: public/index.php
use App\Controllers\OrderController;
$orderController = new OrderController();
// GET /api/orders/my - Lấy danh sách đơn hàng của tôi
if ($uri === '/api/orders/my' && $method === 'GET') {
$orderController->myOrders();
}
5. Kiểm thử API (Test with Curl)
Hãy dùng Token của bạn để gọi thử API này nhé:
curl -X GET http://localhost:8000/api/orders/my \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Kết quả mong đợi:
{
"status": "success",
"count": 1,
"orders": [
{
"id": 15,
"total_price": "12990000.00",
"status": "shipping",
"created_at": "2026-03-25 14:21:00",
"full_name": "Nguyễn Văn Hoàng",
"address": "Phú Nhuận, TP.HCM",
"phone": "090xxxxxxx"
}
]
}
Tạm kết
Vậy là chúng ta đã hoàn thiện mảnh ghép tiếp theo trong quy trình bán hàng. Khách hàng giờ đây đã có thể yên tâm theo dõi "túi tiền" của mình qua danh sách đơn hàng. Hãy để lại bình luận phía dưới nhé! Đừng quên Upvote để tiếp thêm động lực cho "bố đời". Chúc các bạn code vui vẻ!
All rights reserved