feature: add error pages
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user