array_map($callback, $array) gọi $callback trên mọi phần tử của $array và trả về một mảng mới chứa kết quả. Callback đứng trước, mảng đứng sau, và mảng gốc giữ nguyên.
fn($p) => $p * 1.2 là một arrow function: hàm chỉ có một biểu thức và trả về kết quả của biểu thức đó. Bất kỳ callable nào cũng dùng được ở vị trí này.
Dùng hàm có sẵn làm callback
Truyền tên một hàm có sẵn dưới dạng chuỗi. Đây là cách ngắn nhất để dọn dẹp cả một mảng: trim mọi giá trị, chuyển chuỗi thành số nguyên hoặc đổi chữ hoa chữ thường.
array_map('intval', ...) là cách thường dùng để biến các chuỗi từ biểu mẫu hay từ explode() thành số nguyên thật. Bạn cũng có thể viết intval(...), cú pháp first-class callable từ PHP 8.1, mà trình soạn thảo có thể tự gợi ý và kiểm tra.
Dùng closure với biến bên ngoài
Arrow function tự động nhìn thấy các biến xung quanh nó. Một function kiểu cũ cần use để đưa chúng vào. Cả hai đều được giải thích ở trang hàm ẩn danh.
array_map kèm khóa
Với một mảng duy nhất, array_map giữ nguyên khóa, kể cả khóa chuỗi. Nhưng callback chỉ nhận được giá trị. Để nhận cả khóa, hãy truyền array_keys($array) làm mảng thứ hai: khi đó callback được gọi với một phần tử từ mỗi mảng.
Hãy để ý kết quả thứ hai: ngay khi bạn truyền nhiều hơn một mảng, các khóa bị thay bằng 0, 1, 2. Đó là lý do dòng cuối dùng array_combine() để dựng lại chúng.
Map nhiều mảng cùng lúc
Mỗi mảng thêm vào trở thành một đối số thêm cho callback, được ghép theo vị trí. Nếu các mảng có độ dài khác nhau, mảng ngắn hơn được bù bằng null.
Truyền null làm callback sẽ bỏ qua bước gọi hàm và ghép các mảng thành từng cặp:
array_map vs array_walk vs foreach
array_map tạo một mảng mới. array_walk thay đổi chính mảng bạn truyền vào thông qua tham chiếu, và đưa khóa cho callback làm đối số thứ hai. Một foreach làm được cả hai việc, lại còn có thể bỏ qua phần tử hoặc dừng sớm bằng break.
Dùng array_map khi mỗi phần tử biến thành đúng một phần tử mới. Nếu bạn còn cần bỏ bớt một số phần tử, hãy kết hợp với array_filter, hoặc viết một vòng lặp foreach.
Lỗi thường gặp: thứ tự đối số
array_map nhận callback trước và mảng sau. Hàm anh em của nó là array_filter lại nhận theo thứ tự ngược lại, nên rất dễ nhầm:
array_map($callback, $array); // callback first
array_filter($array, $callback); // array first
Đảo thứ tự hai đối số khiến PHP 8 ném ra TypeError, vì một mảng bình thường không phải callback hợp lệ:
PHP dừng với thông báo:
PHP Fatal error: Uncaught TypeError: array_map(): Argument #1 ($callback) must be a valid callback or null, array callback must have exactly two members in /home/index.php:4
Đổi lại thứ tự hai đối số là khối code chạy được.
Câu hỏi thường gặp
Hàm array_map trong PHP làm gì?
Hàm này gọi một hàm trên mọi phần tử của mảng và trả về một mảng mới chứa kết quả: array_map(fn($n) => $n * 2, [1, 2, 3]) trả về [2, 4, 6]. Mảng gốc không bị thay đổi.
array_map có giữ nguyên khóa không?
Với một mảng thì có: khóa chuỗi và khóa số nguyên được giữ nguyên. Với hai mảng trở lên, kết quả luôn nhận khóa mới 0, 1, 2....
Làm sao lấy khóa bên trong callback của array_map?
Truyền các khóa làm mảng thứ hai: array_map(fn($k, $v) => "$k=$v", array_keys($arr), $arr). Kết quả là một list, nên hãy bọc nó trong array_combine(array_keys($arr), ...) nếu bạn cần lấy lại khóa ban đầu.
array_map có nhanh hơn foreach không?
Không đáng kể. Cả hai đều duyệt mảng một lần, và một foreach bình thường thường nhanh hơn một chút vì không phải gọi hàm cho từng phần tử. Hãy chọn array_map khi nó dễ đọc hơn: một phép biến đổi tạo ra mảng mới.
array_map và array_walk khác nhau thế nào?
array_map trả về một mảng mới và không đụng tới đầu vào. array_walk trả về true và được dùng để thay đổi trực tiếp mảng thông qua một tham số tham chiếu: array_walk($arr, function (&$v, $k) { $v = trim($v); });.