Vấn đề
Đã muộn, và bạn đang hoàn tất việc tích hợp một API. Dịch vụ bên ngoài gửi về một phản hồi JSON hợp lệ, bạn gọi json_decode(), và sau đó cố gắng lấy một giá trị. Đột nhiên, script của bạn bị lỗi.
$response = file_get_contents('https://api.example.com/user/1');
$data = json_decode($response);
echo $data['username']; // Dòng này sẽ kích hoạt Fatal Error
Thay vì nhận được tên người dùng, bạn nhận được một thông báo lỗi ngắn gọn: Fatal error: Cannot use object of type stdClass as array. Mã nguồn của bạn dừng hoạt động ngay lập tức.
Tại sao lỗi này xảy ra
Theo mặc định, json_decode($json) trả về một đối tượng (object) thuộc kiểu stdClass. PHP sẽ không cho phép bạn sử dụng dấu ngoặc vuông ($data['key']) trên các đối tượng trừ khi chúng thực thi giao diện ArrayAccess. Vì stdClass chỉ là một khung chứa chung, trống rỗng, nó chỉ hiểu toán tử mũi tên (->).
Hãy tưởng tượng việc này giống như bạn cố gắng dùng chìa khóa cho một cánh cửa chỉ có tay nắm. Cú pháp không khớp với cấu trúc.
Cách sửa lỗi trong 1 giây: Sử dụng cờ Boolean
Giải pháp nhanh nhất là truyền true vào tham số thứ hai của json_decode(). Điều này yêu cầu PHP trả về một mảng liên kết (associative array) thay vì một đối tượng. Hầu hết các lập trình viên thích cách này vì mảng dễ thao tác hơn trong các vòng lặp.
// Thay đổi từ:
$data = json_decode($response);
// Thành:
$data = json_decode($response, true);
// Bây giờ mã sẽ hoạt động hoàn hảo:
echo $data['username'];
Lựa chọn thay thế: Giữ nguyên cú pháp Đối tượng
Đôi khi bạn muốn giữ dữ liệu dưới dạng đối tượng, đặc biệt nếu các phần khác của ứng dụng yêu cầu định dạng đó. Trong trường hợp này, chỉ cần thay dấu ngoặc vuông bằng toán tử mũi tên. Nó trông gọn gàng hơn và nhanh hơn một chút trong một số phiên bản PHP.
$data = json_decode($response);
// Truy cập dưới dạng thuộc tính của đối tượng
echo $data->username;
Nếu khóa JSON có dấu gạch ngang, ví dụ như user-id thì sao? Bạn không thể viết $data->user-id vì PHP sẽ hiểu rằng bạn đang cố gắng trừ một hằng số. Hãy sử dụng dấu ngoặc nhọn thay thế: $data->{'user-id'}.
Xử lý dữ liệu lồng nhau phức tạp
Lỗi này gây khó chịu nhất với các chuỗi JSON lồng nhau. Hãy tưởng tượng một cấu trúc như {"meta": {"status": 200}}. Nếu bạn quên cờ true, $data['meta']['status'] sẽ bị lỗi ngay từ dấu ngoặc đầu tiên.
Để xem chính xác PHP đang làm việc với gì, hãy chạy var_dump($data). Nếu bạn thấy class stdClass, hãy dùng mũi tên. Nếu bạn thấy array, hãy dùng ngoặc vuông. Đây là cách nhanh nhất để xác minh cấu trúc dữ liệu của bạn trước khi viết thêm mã.
Xác minh và An toàn
Đừng giả định rằng API luôn trả về dữ liệu hợp lệ. Một sai lầm phổ biến là cố gắng truy cập mảng trên một giá trị null do JSON bị lỗi định dạng. Hãy thêm một bước kiểm tra đơn giản để mã của bạn sẵn sàng cho môi trường production:
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception("Nhận được JSON không hợp lệ: " . json_last_error_msg());
}
if (isset($data['username'])) {
echo "Người dùng: " . $data['username'];
}
Mẹo chuyên nghiệp: Kiểm tra JSON thô
Khi tôi đang gỡ lỗi các phản hồi API lạ, tôi thường sao chép chuỗi thô vào một công cụ định dạng để trực quan hóa các cấp độ. Tôi thường sử dụng JSON Formatter & Validator trên ToolCraft. Nó chạy hoàn toàn trong trình duyệt của bạn. Điều này giúp dữ liệu production nhạy cảm hoặc các khóa API không bao giờ bị gửi đến máy chủ của bên thứ ba.
Tóm tắt cách sửa lỗi:
- **Đối với Mảng:** Sử dụng `json_decode($json, true);` và `$data['key']`.
- **Đối với Đối tượng:** Sử dụng `json_decode($json);` và `$data->key`.
- **Gỡ lỗi:** Kiểm tra `json_last_error()` nếu kết quả là `null`.

