array_merge($a, $b) trả về một mảng mới gồm các phần tử của $a rồi đến các phần tử của $b. Khóa số được đánh số lại từ 0; khi cả hai mảng có cùng một khóa chuỗi, giá trị từ mảng đứng sau sẽ thắng. Bạn có thể truyền bao nhiêu mảng tùy thích.
array_merge() không thay đổi các đối số của nó. Hàm trả về mảng đã gộp, nên hãy gán kết quả: $all = array_merge($all, $more);.
Khóa số được đánh số lại
array_merge() coi khóa số nguyên là vị trí chứ không phải tên. Mọi phần tử có khóa số nguyên đều được nối vào cuối và nhận khóa mới bắt đầu từ 0, kể cả khi các mảng dùng cùng những con số hoặc có chỗ bị khuyết. Đó là điều bạn muốn với list, nhưng sẽ gây bất ngờ khi các con số là ID.
Khóa chuỗi trông giống số nguyên ('101') được lưu dưới dạng số nguyên, nên cũng bị đánh số lại. Khóa như 'id101' thì giữ nguyên.
array_merge vs toán tử +
Toán tử + (hợp mảng) cũng gộp các mảng, nhưng theo quy tắc ngược lại: với khóa nào đã có trong mảng bên trái, giá trị bên trái thắng và giá trị bên phải bị bỏ. Toán tử này không bao giờ đánh số lại. Vì thế + là cách tự nhiên để điền giá trị mặc định, còn array_merge() là cách tự nhiên để ghi đè chúng.
array_merge($a, $b) | $a + $b | |
|---|---|---|
| Cùng khóa chuỗi | giá trị từ $b | giá trị từ $a |
| Khóa số nguyên | đánh số lại, giữ mọi giá trị | giữ nguyên, $b thua khi trùng khóa |
| Cách dùng thường gặp | nối list, ghi đè cài đặt | điền giá trị mặc định, giữ ID |
Ví dụ cuối trong khối code là cái bẫy kinh điển của +: ['a', 'b'] + ['x', 'y', 'z'] cho ra a, b, z, vì các khóa 0 và 1 đã có ở bên trái.
Cú pháp spread: [...b]
Toán tử spread mở các mảng ra bên trong một literal mảng. Nó hoạt động giống array_merge(): khóa số nguyên được đánh số lại và, từ PHP 8.1, khóa chuỗi được cho phép và khóa đứng sau thắng. Cú pháp này dễ đọc khi bạn trộn mảng với các giá trị đơn lẻ.
Để nối một mảng vào một mảng có sẵn ngay tại chỗ, xem array_push() với spread operator.
Gộp một mảng chứa các mảng
Khi các mảng cần gộp nằm sẵn trong một list, hãy spread list đó vào array_merge(). Đây cũng là cách nhanh để gộp trong vòng lặp: gom các phần lại, rồi gộp một lần.
Viết $all = array_merge($all, $batch); bên trong vòng lặp vẫn chạy được, nhưng nó sao chép toàn bộ mảng ngày càng lớn ở mỗi lần lặp, và sẽ chậm khi có hàng nghìn phần tử.
array_merge_recursive và array_replace
array_merge_recursive() gộp cả các mảng lồng nhau, nhưng với một khóa chuỗi trùng chứa giá trị thường, nó không ghi đè: nó gom cả hai giá trị vào một mảng mới. Với cấu hình, đó hiếm khi là điều bạn muốn. Trong trường hợp này array_replace_recursive() thường là công cụ đúng: nó ghi đè giá trị ở mọi cấp và giữ nguyên khóa.
Đọc ba dòng JSON từ trên xuống: array_merge() thay toàn bộ mảng db và làm mất host, array_merge_recursive() biến port và debug thành list hai phần tử, còn array_replace_recursive() cho ra đúng cấu hình bạn muốn.
Lỗi thường gặp: gộp mảng không loại bỏ gì cả
array_merge() giữ các giá trị trùng nhau nằm ở các khóa khác nhau. Gộp hai list tag sẽ khiến mỗi tag chung xuất hiện hai lần. Hãy cho kết quả đi qua array_unique() rồi array_values() để đánh số lại.
Trang array_unique trình bày cách loại bỏ phần tử trùng khỏi các hàng dữ liệu và mảng lồng nhau.
Câu hỏi thường gặp
array_merge và + trong PHP khác nhau thế nào?
Với khóa chuỗi trùng nhau, array_merge($a, $b) giữ giá trị từ $b, còn $a + $b giữ giá trị từ $a. Với khóa số, array_merge() nối mọi thứ vào cuối và đánh số lại, còn + giữ nguyên khóa số và bỏ mọi phần tử của $b có khóa đã tồn tại trong $a.
Làm sao gộp mảng mà vẫn giữ khóa số?
Dùng $a + $b nếu mảng bên trái phải thắng, hoặc array_replace($a, $b) nếu mảng bên phải phải thắng. array_merge() luôn đánh số lại khóa số bắt đầu từ 0.
Làm sao gộp một mảng chứa các mảng trong PHP?
Spread mảng bên ngoài vào array_merge(): $all = array_merge(...$lists);. Với danh sách rỗng, kết quả là []. Hãy gom các mảng trong vòng lặp trước rồi gộp một lần ở cuối; gọi array_merge() bên trong vòng lặp sẽ sao chép lại kết quả ngày càng lớn ở mỗi lần lặp.
Có dùng được spread operator với khóa chuỗi trong PHP không?
Được, từ PHP 8.1. Khi đó [...$a, ...$b] hoạt động giống array_merge($a, $b): khóa số được đánh số lại và khóa chuỗi đứng sau ghi đè khóa đứng trước.