+1

json_decode Trong PHP: Vượt Qua "Cú Lừa" stdClass & Bẫy Mất Dữ Liệu

Câu chuyện xảy ra khi bạn gọi API của Facebook để lấy thông tin User. API trả về một chuỗi JSON rất đẹp:

{"id": 1001, "name": "Hiếu", "role": "admin"}

Bạn hí hửng gõ:

$json_string = '{"id": 1001, "name": "Hiếu", "role": "admin"}';
$user = json_decode($json_string);

echo $user['name']; // In ra tên user

BÙM! Màn hình văng ra lỗi đỏ chót: Fatal error: Uncaught Error: Cannot use object of type stdClass as array

Ủa? Rõ ràng nó là mảng mà sao lại không truy cập kiểu ['name'] được? Chào mừng bạn đến với cú lừa đầu tiên của json_decode.

1. Bí Mật Của Tham Số Thứ 2: stdClass vs Associative Array

Mặc định, khi bạn gọi json_decode($json_string), PHP sẽ chuyển đổi các object {} trong JSON thành một đối tượng ẩn danh của PHP có tên là stdClass.

Khi nó là Object, bạn BẮT BUỘC phải truy cập bằng dấu mũi tên ->:

$user = json_decode($json_string);
echo $user->name; // Chạy ngon lành!

Nhưng Vibe Coder KHÔNG THÍCH stdClass. Tại sao? Vì sức mạnh của PHP nằm ở bộ hàm xử lý Mảng (Array) khổng lồ như array_map, array_filter, array_column... Các hàm này sẽ "bó tay" nếu bạn ném vào một cục stdClass.

Giải pháp (Tham số thứ 2): Bật cờ true

Để ép PHP biến mọi thứ thành Mảng kết hợp (Associative Array), hãy luôn nhớ truyền true vào tham số thứ 2.

$user = json_decode($json_string, true); // <--- Bí quyết ở chữ true này
echo $user['name']; // Lúc này xài [''] hoàn toàn hợp lệ!

Chỉ một chữ true nhỏ nhoi, bạn đã giải phóng toàn bộ sức mạnh thao tác dữ liệu của PHP.

2. Sự Im Lặng Đáng Sợ: Hàm Decode Gặp Lỗi

Bạn nhận được một chuỗi JSON từ Frontend gửi lên, nhưng do Frontend code ẩu, chuỗi bị dư một dấu phẩy ở cuối:

{"name": "Hiếu", } (Đây là JSON không hợp lệ - Invalid JSON).

Bạn gọi $data = json_decode($json_string, true);.

App của bạn không báo lỗi dòng nào cả. Nhưng một lúc sau, hàm insert Database báo lỗi: Column 'name' cannot be null.

Đây là bẫy thứ 2: Khi json_decode gặp lỗi cú pháp, nó chọn cách IM LẶNG và trả về NULL. Nó không hề ném ra Exception để chặn luồng code lại!

Giải pháp (Tham số thứ 4 - Từ PHP 7.3+): JSON_THROW_ON_ERROR

Đừng bao giờ để code đi tiếp khi data đã sai. Hãy ép json_decode phải "la lên" khi gặp lỗi bằng cách chèn cờ này vào tham số thứ 4:

try {
    // Tham số 3 là độ sâu (depth) tối đa của JSON, mặc định 512 là dư xài.
    $data = json_decode($invalid_json, true, 512, JSON_THROW_ON_ERROR);
    
    // Nếu JSON sai, code sẽ KHÔNG BAO GIỜ chạy xuống tới dòng này
    DB::insert('users', $data); 
} catch (\JsonException $e) {
    // Code sẽ nhảy ngay vào đây
    return response()->json(['error' => 'Data gửi lên bị sai format JSON rồi bạn êi!'], 400);
}

3. Cú Lừa Số 3: Số Nguyên Khổng Lồ Bị Cắt Xén (BigInt)

Đây là bẫy tàn khốc nhất, thường gặp khi bạn làm việc với API của Twitter/X hoặc Discord (nơi dùng Snowflake ID - những con số dài ngoằng cỡ 19 chữ số).

Giả sử JSON chứa: {"tweet_id": 1050212345678901234} Khi bạn json_decode bình thường, bộ nhớ số nguyên của PHP (tùy cấu hình máy) có thể không chứa nổi con số khổng lồ này. Kết quả là nó bị làm tròn (Precision Loss) thành 1050212345678901200. Bốn số đuôi đã biến mất! Bạn lấy ID bị sai này đi xóa bài viết thì xóa nhầm bài của người khác.

Giải pháp: JSON_BIGINT_AS_STRING Ép PHP phải đối xử với những con số to này như một Chuỗi (String) để bảo toàn 100% dữ liệu. Ta kết hợp cờ này với cờ báo lỗi bằng toán tử bitwise |:

$flags = JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING;
$data = json_decode($twitter_json, true, 512, $flags);
// $data['tweet_id'] bây giờ sẽ là chuỗi "1050212345678901234", an toàn tuyệt đối!

Lời kết

Viết code chạy được thì dễ, nhưng viết code để lường trước mọi tình huống dữ liệu "độc hại" hay "cồng kềnh" mới là đỉnh cao của Vibe Coder. Bắt đầu từ hôm nay, đừng bao giờ xài json_decode($data) cộc lốc nữa nhé. Hãy trang bị cho nó tấm khiên Error Handling và BigInt để ăn ngon ngủ yên!

Chủ đề tiếp theo: "Chạy Ở Máy Em Rất Ngon Nhưng Lên Server Thì Tạch" - Khai Sáng Cùng Docker

Chúng ta đã bàn sâu về Code, từ Backend PHP, Node.js đến Frontend, từ JSON đến JWT. Code của bạn chạy cực kỳ mượt trên cái Macbook M2 của bạn. Bạn hào hứng nén file .zip, gửi lên Server Linux của công ty để chạy.

Và... Server văng lỗi: "PHP version mismatch", "Missing library libvips", "Port 3000 in use". Bạn mất nguyên một ngày cuối tuần chỉ để ngồi gõ lệnh cài đặt môi trường trên server sao cho giống hệt máy bạn.

Làm sao để đóng gói toàn bộ Code, Database, Redis, và cả hệ điều hành Node/PHP... vào trong một "cái hộp container", mang đi vứt ở máy tính nào cũng chạy được y chang nhau mà không trật một nhịp? Ở bài viết tới, chúng ta sẽ đàm đạo về thứ vũ khí vĩ đại nhất của DevOps và giới Backend hiện đại: Docker. Anh em nhớ follow nhé!


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.