Menu

array_key_exists() trong PHP: kiểm tra khóa có trong mảng

array_key_exists('key', $array) trả về true khi mảng có khóa đó, kể cả khi giá trị là null. isset($array['key']) nhanh hơn nhưng trả về false với giá trị null. Tìm hiểu sự khác biệt, key_exists(), khóa lồng nhau, kiểm tra nhiều khóa và vì sao đối tượng cần property_exists().

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

array_key_exists('key', $array) trả về true nếu mảng có khóa đó và false nếu không. Lưu ý thứ tự: khóa đứng trước, mảng đứng sau. Hàm trả về true ngay cả khi giá trị lưu ở khóa đó là null, và đây chính là điều duy nhất isset() không làm.

Để kiểm tra một giá trị thay vì một khóa, hãy dùng in_array().

array_key_exists vs isset

Cả hai đều kiểm tra một khóa. Chúng chỉ cho kết quả khác nhau khi giá trị là null: isset() coi giá trị null là "chưa được đặt", còn array_key_exists() báo đúng những gì thật sự có trong mảng.

0 và '' đều được cả hai coi là đã đặt; chỉ có null làm chúng khác nhau. Bạn cần hàm nào phụ thuộc vào ý nghĩa của null trong dữ liệu:

  • Dùng isset() khi null nghĩa là "không có giá trị". Đây là trường hợp phổ biến, isset() là một cấu trúc ngôn ngữ (nhanh hơn một chút), và nó nhận cả đường dẫn lồng nhau lẫn biến chưa định nghĩa mà không cảnh báo.
  • Dùng array_key_exists() khi null là một giá trị thật mà bạn phải phân biệt với khóa không tồn tại: một trường JSON được gửi là null, một cột cơ sở dữ liệu có giá trị NULL, một tùy chọn được cố ý đặt là null để xóa nó.

Trang isset trình bày các cách dùng khác của nó, bao gồm kiểm tra nhiều biến cùng lúc.

Phân biệt null với khóa không tồn tại trong payload JSON

Một trường hợp điển hình mà chỉ array_key_exists() cho câu trả lời đúng: một API cập nhật bản ghi từ JSON. Trường được gửi là null nghĩa là "xóa nó", còn trường không được gửi nghĩa là "đừng động vào". isset() coi hai trường hợp này là một.

Nếu dùng isset($patch[$field]), số điện thoại sẽ vẫn còn, vì null trông giống như một trường không được gửi.

key_exists() là cùng một hàm

key_exists() là bí danh của array_key_exists(), còn giữ lại từ các phiên bản PHP đầu tiên. Cùng đối số, cùng kết quả. Hãy ưu tiên tên đầy đủ, vì đó là tên người đọc code mong đợi.

Kiểu của khóa: "1" và 1 là cùng một khóa

Khóa của mảng là số nguyên hoặc chuỗi, và một chuỗi chỉ chứa số nguyên thập phân thông thường sẽ được lưu dưới dạng số nguyên. Vì vậy array_key_exists('1', $arr) tìm thấy khóa 1, và ngược lại. Một chuỗi như '01' vẫn là chuỗi và là một khóa khác.

Kiểm tra khóa lồng nhau và nhiều khóa

array_key_exists() chỉ xét một cấp. Với một đường dẫn lồng nhau mà null không quan trọng, isset($a['x']['y']) kiểm tra mọi cấp cùng lúc. Với đường dẫn mà null có ý nghĩa, một hàm hỗ trợ ngắn sẽ đi qua từng cấp. Để kiểm tra nhiều khóa có đủ hay không, hãy so sánh bằng array_diff_key().

array_flip($required) biến danh sách tên thành các khóa để array_diff_key() so sánh chúng với các khóa của đầu vào; phần còn lại là danh sách các trường bị thiếu, sẵn sàng cho thông báo lỗi.

Đối tượng cần property_exists

PHP phiên bản cũ chấp nhận đối tượng trong array_key_exists(). PHP 8 thì ném ra TypeError. Với đối tượng, property_exists() kiểm tra một thuộc tính đã khai báo hoặc thuộc tính động (kể cả khi được đặt là null), còn isset($obj->prop) hoạt động giống isset() trên mảng.

Hai dòng cuối cho thấy một cách khác: get_object_vars() biến các thuộc tính truy cập được của đối tượng thành một mảng, sau đó bạn dùng được các hàm xử lý mảng.

Câu hỏi thường gặp

Vì sao isset trả về false trong khi array_key_exists trả về true?

Vì khóa đó chứa null. isset($arr['k']) chỉ là true khi khóa tồn tại và giá trị khác null, còn array_key_exists('k', $arr) là true mỗi khi khóa có trong mảng. Với mọi giá trị khác, kể cả 0, '' và false, cả hai đều cho cùng một câu trả lời.

key_exists trong PHP là gì?

Là bí danh của array_key_exists(). key_exists('id', $row) và array_key_exists('id', $row) hoạt động giống hệt nhau. Phần lớn code dùng tên dài hơn.

Làm sao kiểm tra một khóa lồng nhau có tồn tại trong PHP?

Kiểm tra từng cấp: isset($data['user']['address']['city']) kiểm tra cả đường dẫn cùng lúc và không bao giờ cảnh báo khi thiếu một cấp. Nếu giá trị null vẫn phải được tính là có, hãy đi qua đường dẫn bằng array_key_exists() từng cấp một.

Có dùng array_key_exists với đối tượng được không?

Không. Từ PHP 8.0, truyền một đối tượng vào sẽ ném ra TypeError. Dùng property_exists($obj, 'name') cho các thuộc tính đã khai báo, hoặc isset($obj->name).

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu