Menggabungkan dua daftar produk, mencari isi keranjang yang tidak ada di stok, atau menyusun konfigurasi dari nilai bawaan — semuanya adalah operasi gabung dan banding antar array. PHP menyediakan dua jalur penggabungan yang perilakunya sangat berbeda: fungsi array_merge dan operator union (+), ditambah keluarga fungsi difference dan intersect untuk membandingkan isi. Chapter ini membedah perilaku setiap operasi tersebut, khususnya perlakuan mereka terhadap kunci numerik dan kunci string yang sering menjadi sumber kejutan.
Menggabungkan Array dengan array_merge #
array_merge menerima dua array atau lebih lalu mengembalikan array baru. Perlakuannya berbeda bergantung pada jenis kunci: kunci numerik di-reindex berurutan dari nol, sedangkan untuk kunci string yang sama, nilai dari array belakang menimpa nilai dari array depan.
<?php
$a = [10, 20, 30];
$b = [40, 50];
$gabungan = array_merge($a, $b);
print_r($gabungan);Output yang Dihasilkan:
Array
(
[0] => 10
[1] => 20
[2] => 30
[3] => 40
[4] => 50
)Semua elemen dari kedua array hadir, dan kunci numerik disusun ulang menjadi 0 sampai 4 — PHP memperlakukan array berindeks numerik sebagai daftar yang urutannya dibawa oleh posisi, bukan oleh angka kuncinya. Sekarang bandingkan dengan kunci string:
<?php
$a = ['nama' => 'Budi', 'kota' => 'Bandung'];
$b = ['nama' => 'Siti', 'usia' => 25];
$gabungan = array_merge($a, $b);
print_r($gabungan);Output yang Dihasilkan:
Array
(
[nama] => Siti
[kota] => Bandung
[usia] => 25
)Kunci nama bentrok, dan nilai dari array kedua (Siti) menang mengikuti urutan parameter — aturan later wins. Kunci usia yang baru ikut ditambahkan di akhir hasil, sementara kota tetap pada posisinya. Pola ini yang membuat array_merge cocok untuk menyusun data secara berlapis, misalnya menimpa sebagian field data lama dengan data baru.
Operator Union: Array Kiri Selalu Menang #
Operator + menghasilkan union dua array dengan aturan kebalikan total dari array_merge: kunci yang sudah ada di array kiri tetap dipertahankan, dan operator ini tidak pernah menyusun ulang kunci apa pun.
<?php
$a = [10, 20, 30];
$b = [40, 50];
$union = $a + $b;
print_r($union);Output yang Dihasilkan:
Array
(
[0] => 10
[1] => 20
[2] => 30
)Elemen 40 dan 50 lenyap. Alasannya: $b[0] dan $b[1] bentrok dengan kunci 0 dan 1 yang sudah terisi di $a, dan array kiri selalu menang. Operator + bekerja atas dasar kunci — ia tidak peduli urutan posisi seperti array_merge.
Pola paling berguna dari operator union adalah mengisi nilai bawaan (defaults) untuk konfigurasi. Nilai dari pengguna diletakkan di kiri agar menang, sementara kunci yang tidak diisi pengguna dilengkapi dari kanan:
<?php
$default = ['limit' => 10, 'offset' => 0, 'sort' => 'asc'];
$user = ['limit' => 25, 'sort' => 'desc'];
$konfigurasi = $user + $default;
print_r($konfigurasi);Output yang Dihasilkan:
Array
(
[limit] => 25
[sort] => desc
[offset] => 0
)Pengguna menginginkan limit 25 dan sort desc, keduanya menang atas nilai bawaan. Kunci offset tidak diisi pengguna sehingga diambil dari $default. Selain ringkas, pola ini juga aman untuk konfigurasi: operator + tidak pernah menyusun ulang kunci numerik sebagaimana array_merge, sehingga campuran kunci angka dan string tetap utuh.
Perbandingan Singkat array_merge dan Operator Union #
| Aspek | array_merge($a, $b) | $a + $b |
|---|---|---|
| Kunci numerik bentrok | digabung semua, di-reindex dari 0 | nilai $b dibuang |
| Kunci string bentrok | nilai $b (belakang) menang | nilai $a (kiri) menang |
| Kunci hasil | kunci numerik disusun ulang | kunci asli apa adanya |
| Kebiasaan pemakaian | menyusun daftar dan menimpa field | mengisi nilai bawaan |
Merge Bersarang dengan array_merge_recursive dan array_replace #
array_merge bersifat dangkal: kunci db yang bernilai array akan ditimpa utuh, bukan digabungkan. Ketika Anda benar-benar perlu menggabungkan array bersarang, ada dua pilihan dengan hasil berbeda. array_merge_recursive menuruni tiap tingkat dan menggabungkannya; bila nilai yang bentrok sama-sama berupa array, keduanya digabung; bila bentroknya berupa nilai skalar, nilainya dikumpulkan menjadi array:
<?php
$a = ['db' => ['host' => 'localhost', 'port' => 3306], 'debug' => true];
$b = ['db' => ['port' => 3307, 'user' => 'budi']];
$hasil = array_merge_recursive($a, $b);
print_r($hasil);Output yang Dihasilkan:
Array
(
[db] => Array
(
[host] => localhost
[port] => Array
(
[0] => 3306
[1] => 3307
)
[user] => budi
)
[debug] => 1
)Di dalam kunci db, host dan user bergabung damai, tetapi bentrokan port menghasilkan array [3306, 3307] — bukan satu nilai. Perilaku ini jarang yang diinginkan untuk konfigurasi, dan itulah alasan fungsi array_replace biasanya lebih tepat. array_replace menimpa nilai per kunci di semua tingkat yang Anda sebutkan secara eksplisit, mempertahankan urutan kunci array pertama, dan tidak pernah mengubah nilai menjadi array:
<?php
$konfig = ['host' => 'localhost', 'port' => 3306, 'debug' => false];
$override = ['port' => 5432, 'debug' => true];
$hasil = array_replace($konfig, $override);
print_r($hasil);Output yang Dihasilkan:
Array
(
[host] => localhost
[port] => 5432
[debug] => 1
)Nilai port dan debug diganti nilai dari $override, sedangkan host selamat karena tidak disebut. Untuk konfigurasi bersarang Anda tetap harus menuruni tiap tingkat secara manual atau memakai pustaka khusus — array_replace tidak menuruni array bersarang secara otomatis.
Mencari Selisih dengan array_diff dan Kerabatnya #
array_diff mengembalikan elemen array pertama yang nilainya tidak ditemukan di array lain mana pun. Kunci dari array pertama dipertahankan di hasil:
<?php
$lama = ['php', 'mysql', 'html'];
$baru = ['php', 'css'];
print_r(array_diff($lama, $baru));
print_r(array_intersect($lama, $baru));Output yang Dihasilkan:
Array
(
[1] => mysql
[2] => html
)
Array
(
[0] => php
)Hasil array_diff adalah mysql dan html dengan kunci aslinya 1 dan 2 — hanya php yang juga ada di $baru. Sebaliknya, array_intersect mengembalikan elemen array pertama yang nilainya juga hadir di semua array pembanding, sehingga hanya php yang lolos. Perhatikan bahwa array_intersect mempertahankan nilai dari array pertama, bukan dari array pembanding.
Bila perbandingannya harus berdasarkan kunci, gunakan pasangan array_diff_key dan array_intersect_key:
<?php
$a = ['a' => 1, 'b' => 2, 'c' => 3];
$b = ['b' => 20, 'd' => 40];
print_r(array_diff_key($a, $b));
print_r(array_intersect_key($a, $b));Output yang Dihasilkan:
Array
(
[a] => 1
[c] => 3
)
Array
(
[b] => 2
)array_diff_key menyisakan a dan c karena kunci b dimiliki $b; nilainya (20 berlawanan dengan 2) tidak diperhatikan sama sekali. array_intersect_key menahan elemen yang kuncinya hadir di kedua array — hanya b — dan tetap memakai nilai dari array pertama.
<?php
$satu = ['Apel', 'Jeruk', 'Mangga'];
$dua = ['apel', 'Pisang'];
$selisih = array_udiff(
$satu,
$dua,
fn (string $x, string $y): int => strcasecmp($x, $y)
);
print_r($selisih);Output yang Dihasilkan:
Array
(
[1] => Jeruk
[2] => Mangga
)Callback strcasecmp membandingkan dua string tanpa memedulikan kapitalisasi, sehingga Apel dianggap sama dengan apel dan tersingkir dari hasil. Callback seperti ini adalah fungsi yang dikirim sebagai argumen — pola yang akan dibahas tuntas nanti di Chapter Anonymous Functions
pada Section Fungsi.
Ringkasan #
array_merge menggabungkan dengan aturan later wins dan reindex numerik; operator + mempertahankan array kiri tanpa menyentuh kunci; array_merge_recursive dan array_replace menangani kasus bersarang dengan karakter berbeda; array_diff/array_intersect beserta varian _key dan array_udiff membandingkan isi antar array. Semua operasi ini mengembalikan array baru dan tidak pernah mengubah array asli — sebuah fakta yang membawa kita ke pertanyaan menarik: bagaimana sebenarnya PHP menyalin array? Chapter berikutnya membedah perilaku salin (copy) dan reference pada array.