# Tài liệu cấu hình và sử dụng System Error Pages

Tài liệu này hướng dẫn chi tiết cách hoạt động, các trường hợp sử dụng, cách kích hoạt (trigger) và kiểm thử các trang lỗi hệ thống trong dự án **thankcard-system**.

---

## 1. Danh sách các trang lỗi & Tình huống sử dụng

| Status Code | Tên lỗi | Tình huống sử dụng | Key Localization (`errors.php`) |
| :--- | :--- | :--- | :--- |
| **401** | Unauthorized | Người dùng chưa đăng nhập nhưng cố truy cập tài nguyên yêu cầu xác thực. | `errors.401_title` / `errors.401_message` |
| **403** | Forbidden | Người dùng đã đăng nhập nhưng không có quyền hạn thực hiện hành động này (ví dụ: User thường cố truy cập chức năng Admin). | `errors.403_title` / `errors.403_message` |
| **404** | Not Found | Đường dẫn (URL) không tồn tại, hoặc khi tìm dữ liệu bằng Model binding/Query không thấy mà muốn trả về lỗi. | `errors.404_title` / `errors.404_message` |
| **419** | Session Expired | Phiên làm việc hết hạn hoặc token CSRF không hợp lệ/hết hạn khi gửi Form (POST/PUT/DELETE). | `errors.419_title` / `errors.419_message` |
| **429** | Too Many Requests | Người dùng/IP gửi quá nhiều yêu cầu trong thời gian ngắn (vượt giới hạn Rate Limit của Middleware). | `errors.429_title` / `errors.429_message` |
| **500** | Internal Error | Lỗi xảy ra từ phía máy chủ hoặc do code PHP bị lỗi crash, kết nối cơ sở dữ liệu thất bại... | `errors.500_title` / `errors.500_message` |
| **503** | Service Unavailable | Hệ thống đang được bảo trì khi chạy lệnh `php artisan down`. | `errors.503_title` / `errors.503_message` |

---

## 2. Cách kích hoạt (Trigger) trong Laravel

Trong Laravel, bạn có thể trigger các trang lỗi này bằng nhiều cách khác nhau tùy thuộc vào ngữ cảnh.

### 2.1. Sử dụng hàm `abort()` (Khuyên dùng trong Controller/Service)
Hàm `abort()` sẽ ném ra một `HttpException` và Laravel sẽ tự động bắt lấy để render trang lỗi tương ứng nằm trong `resources/views/errors/{status}.blade.php`.

```php
// Ví dụ kiểm tra quyền trong Controller
if ($user->role !== 'admin') {
    abort(403, 'Bạn không có quyền quản trị viên.');
}

// Ví dụ không tìm thấy tài nguyên
$card = Card::find($id);
if (!$card) {
    abort(404, 'Không tìm thấy thẻ cảm ơn.');
}
```

### 2.2. Sử dụng lệnh bảo trì hệ thống (Maintenance Mode)
Kích hoạt lỗi **503** bằng cách đưa ứng dụng vào trạng thái bảo trì:
```bash
php artisan down
```
Để tắt chế độ bảo trì và đưa hệ thống hoạt động bình thường:
```bash
php artisan up
```

### 2.3. Sử dụng Middleware (Rate Limiting cho lỗi 429)
Laravel tích hợp sẵn middleware `throttle`. Bạn có thể áp dụng nó trong file Routes (`routes/web.php` hoặc `routes/api.php`):
```php
Route::middleware('throttle:60,1')->group(function () {
    Route::get('/send-card', [UserController::class, 'send']);
});
```
*(Nếu một IP gọi quá 60 lần/phút, Laravel sẽ tự động ném ra lỗi 429 và render trang 429)*

---

## 3. Ví dụ triển khai thực tế

### Trong Controller/Service:
```php
namespace App\Http\Controllers;

use App\Services\User\Contracts\UserServiceInterface;
use Illuminate\Http\Request;

class UserController extends Controller
{
    protected $userService;

    public function __construct(UserServiceInterface $userService)
    {
        $this->userService = $userService;
    }

    public function show($id)
    {
        $user = $this->userService->findUserById($id);
        
        if (!$user) {
            // Tự động render view errors/404.blade.php
            abort(404);
        }

        return view('user.profile', compact('user'));
    }
}
```

---

## 4. Checklist kiểm thử các trang lỗi

Để chắc chắn các trang lỗi hoạt động chính xác và hiển thị đẹp mắt, hãy tiến hành kiểm thử theo checklist sau:

- [ ] **Test 401 Unauthorized:**
  - Tạm thời gỡ bỏ middleware auth ở một route và ném `abort(401)`.
  - Kiểm tra xem có hiển thị nút **"Đi đến trang Đăng Nhập"** hay không.
- [ ] **Test 403 Forbidden:**
  - Đăng nhập tài khoản User thường, sau đó truy cập một route dành riêng cho Admin hoặc ném `abort(403)`.
  - Kiểm tra xem nút **"Quay lại Trang Chủ"** có hoạt động chính xác không.
- [ ] **Test 404 Not Found:**
  - Truy cập một đường dẫn ngẫu nhiên không khai báo trong route (ví dụ: `http://localhost:8888/path-does-not-exist`).
  - Kiểm tra giao diện và nút **"Quay lại Trang Chủ"**.
- [ ] **Test 419 Session Expired:**
  - Mở một trang có form POST, xóa trường `_token` ẩn (CSRF) trong thẻ `<form>` bằng Inspect Element của trình duyệt rồi bấm Submit.
  - Hoặc ném `abort(419)`.
  - Kiểm tra xem có hiển thị nút **"Tải lại trang"** hay không.
- [ ] **Test 429 Too Many Requests:**
  - Cấu hình tạm thời middleware `throttle:3,1` trên route chính và bấm F5 liên tục 4 lần.
  - Hoặc gọi `abort(429)`.
  - Kiểm tra thông báo lỗi.
- [ ] **Test 500 Internal Server Error:**
  - Thêm một dòng code bị lỗi cú pháp cố ý trong Controller (ví dụ: gọi hàm không tồn tại `$this->nonExistentMethod()`).
  - Hoặc gọi `abort(500)`.
  - Đảm bảo giao diện trang 500 hiển thị thân thiện, không làm lộ stack trace kỹ thuật của code PHP.
- [ ] **Test 503 Maintenance:**
  - Chạy lệnh `php artisan down` trong container Docker.
  - Tải lại trình duyệt để xem trang bảo trì 503 và nút **"Thử lại"**.
  - Chạy `php artisan up` để đưa website trở lại bình thường.
