Wer zwei oder mehr Arrays miteinander vergleichen möchte, findet in array_diff() ein praktisches Werkzeug. Die Funktion ermittelt alle Werte, die im ersten Array vorkommen, aber in keinem der Vergleichs-Arrays enthalten sind. Das Ergebnis ist ein neues Array mit genau diesen Unterschieden. Besonders nützlich ist das beim Abgleich von Datensätzen, beim Filtern von Listen oder beim Erkennen von Änderungen zwischen zwei Zuständen.
Syntax und Grundlagen
Die Funktion erwartet mindestens zwei Arrays und gibt die Elemente zurück, die nur im ersten Array stehen:
array_diff(array $array, array ...$arrays): array
Der Rückgabewert enthält alle Werte aus $array, die in keinem der weiteren Arrays vorkommen. Die Schlüssel aus dem ersten Array bleiben dabei erhalten. Wenn alle Werte auch in den Vergleichs-Arrays enthalten sind, gibt die Funktion ein leeres Array zurück.
Wichtig: array_diff() vergleicht ausschließlich die Werte, nicht die Schlüssel. Für einen Vergleich, der auch die Schlüssel berücksichtigt, gibt es array_diff_assoc() und array_diff_key().
Beispiel: Zwei Arrays vergleichen
Im einfachsten Fall vergleicht man zwei Arrays miteinander und erhält die Elemente zurück, die nur im ersten enthalten sind:
<?php
$farben1 = ["grün", "rot", "blau"];
$farben2 = ["rot", "gelb", "blau"];
$unterschied = array_diff($farben1, $farben2);
print_r($unterschied);
?>
Ausgabe:
Array
(
[0] => grün
)
Das Element "grün" kommt nur in $farben1 vor und ist daher im Ergebnis enthalten. Die Elemente "rot" und "blau" existieren in beiden Arrays und werden herausgefiltert. Beachte, dass der ursprüngliche Schlüssel [0] erhalten bleibt.
Mehrere Arrays gleichzeitig vergleichen
array_diff() akzeptiert nicht nur zwei, sondern beliebig viele Arrays. Das Ergebnis enthält dann nur die Werte, die ausschließlich im ersten Array vorkommen und in keinem der anderen:
<?php
$alle = ["PHP", "Python", "Java", "Ruby", "Go"];
$team_a = ["Python", "Java"];
$team_b = ["Go", "Ruby"];
$nur_erste = array_diff($alle, $team_a, $team_b);
print_r($nur_erste);
?>
Ausgabe:
Array
(
[0] => PHP
)
Nur "PHP" ist weder in $team_a noch in $team_b enthalten und bleibt daher übrig. Dieses Muster eignet sich gut, um aus einer Gesamtliste alle bereits zugeordneten Einträge herauszufiltern.
Die diff-Familie im Vergleich
PHP bietet mehrere Varianten der diff-Funktion, die sich darin unterscheiden, was genau verglichen wird. Die folgende Übersicht zeigt die drei wichtigsten:
| Funktion | Vergleicht | Beschreibung |
array_diff() | nur Werte | Gibt Werte zurück, die im ersten Array stehen, aber in keinem Vergleichs-Array |
array_diff_assoc() | Werte + Schlüssel | Wie array_diff(), prüft aber zusätzlich, ob der Schlüssel übereinstimmt |
array_diff_key() | nur Schlüssel | Vergleicht ausschließlich die Schlüssel, ignoriert die Werte komplett |
Ein konkretes Beispiel verdeutlicht den Unterschied:
<?php
$a = ["name" => "Max", "alter" => "30"];
$b = ["name" => "Max", "alter" => "25"];
/* Nur Werte vergleichen */
print_r(array_diff($a, $b));
/* Array ( [alter] => 30 ) */
/* Werte + Schlüssel vergleichen */
print_r(array_diff_assoc($a, $b));
/* Array ( [alter] => 30 ) */
/* Nur Schlüssel vergleichen */
print_r(array_diff_key($a, $b));
/* Array () - leer, da Schlüssel identisch */
?>
Bei array_diff() und array_diff_assoc() ist das Ergebnis hier gleich, weil sich der Wert "30" vs. "25" am selben Schlüssel "alter" unterscheidet. array_diff_key() gibt ein leeres Array zurück, weil beide Arrays dieselben Schlüssel haben.
Typvergleich bei array_diff()
array_diff() vergleicht Werte intern als Strings. Das bedeutet: Der Integer 1 und der String "1" gelten als gleich. Bei gemischten Datentypen kann das zu überraschenden Ergebnissen führen:
<?php
$zahlen = [1, 2, 3, 4];
$strings = ["1", "3"];
$diff = array_diff($zahlen, $strings);
print_r($diff);
?>
Ausgabe:
Array
(
[1] => 2
[3] => 4
)
Obwohl $zahlen Integers und $strings Strings enthält, erkennt array_diff() die Übereinstimmung. Wer einen typstrengen Vergleich benötigt, kann array_diff_assoc() in Kombination mit einer eigenen Callback-Funktion über array_udiff() verwenden.
Das Gegenstück: array_intersect()
Während array_diff() die Unterschiede ermittelt, gibt array_intersect() die gemeinsamen Werte zurück. Beide Funktionen ergänzen sich und decken zusammen die meisten Vergleichs-Szenarien ab:
<?php
$liste_a = ["PHP", "Python", "Java", "Ruby"];
$liste_b = ["Python", "Go", "Java", "Rust"];
/* Nur in $liste_a */
$nur_a = array_diff($liste_a, $liste_b);
print_r($nur_a);
/* Array ( [0] => PHP [3] => Ruby ) */
/* In beiden Listen */
$gemeinsam = array_intersect($liste_a, $liste_b);
print_r($gemeinsam);
/* Array ( [1] => Python [2] => Java ) */
?>
Auch array_intersect() gibt es in Varianten: array_intersect_assoc() vergleicht Werte und Schlüssel, array_intersect_key() vergleicht nur die Schlüssel.
Praxisbeispiel: Konfigurationsänderungen erkennen
Ein typischer Anwendungsfall für array_diff() ist der Vergleich von zwei Zuständen. Stellen wir uns vor, eine Anwendung speichert Benutzerrechte in einem Array. Nach einer Änderung sollen die neu hinzugekommenen und die entfernten Rechte ermittelt werden:
<?php
$rechte_alt = ["lesen", "schreiben", "kommentieren"];
$rechte_neu = ["lesen", "kommentieren", "admin"];
/* Welche Rechte wurden entfernt? */
$entfernt = array_diff($rechte_alt, $rechte_neu);
print_r($entfernt);
/* Array ( [1] => schreiben ) */
/* Welche Rechte sind neu hinzugekommen? */
$hinzu = array_diff($rechte_neu, $rechte_alt);
print_r($hinzu);
/* Array ( [2] => admin ) */
/* Was ist gleich geblieben? */
$gleich = array_intersect($rechte_alt, $rechte_neu);
print_r($gleich);
/* Array ( [0] => lesen [2] => kommentieren ) */
?>
Durch den doppelten Aufruf von array_diff() (einmal in jede Richtung) und array_intersect() bekommt man ein vollständiges Bild aller Änderungen. Dieses Muster funktioniert genauso gut für den Vergleich von Produktlisten, Tags, Kategorien oder jeder anderen Art von Datensätzen.
Mehrdimensionale Arrays vergleichen
array_diff() arbeitet nur auf der ersten Ebene eines Arrays. Bei mehrdimensionalen Arrays versucht PHP, die Sub-Arrays in Strings umzuwandeln, was zu einer Fehlermeldung führt. Für verschachtelte Strukturen braucht man eine rekursive eigene Funktion:
<?php
function array_diff_recursive($arr1, $arr2) {
$diff = [];
foreach ($arr1 as $key => $value) {
if (is_array($value)) {
if (!isset($arr2[$key]) || !is_array($arr2[$key])) {
$diff[$key] = $value;
} else {
$sub = array_diff_recursive($value, $arr2[$key]);
if (!empty($sub)) {
$diff[$key] = $sub;
}
}
} elseif (!isset($arr2[$key]) || $arr2[$key] !== $value) {
$diff[$key] = $value;
}
}
return $diff;
}
$config_alt = [
"db" => ["host" => "localhost", "port" => "3306"],
"cache" => ["aktiv" => "ja", "ttl" => "3600"]
];
$config_neu = [
"db" => ["host" => "localhost", "port" => "5432"],
"cache" => ["aktiv" => "ja", "ttl" => "3600"]
];
$aenderungen = array_diff_recursive($config_alt, $config_neu);
print_r($aenderungen);
?>
Ausgabe:
Array
(
[db] => Array
(
[port] => 3306
)
)
Die Funktion durchläuft beide Arrays mit einer foreach-Schleife und vergleicht jede Ebene rekursiv. Im Ergebnis erscheint nur der geänderte Wert: Der Datenbank-Port hat sich von 3306 auf 5432 geändert. Mit print_r() lässt sich das Ergebnis übersichtlich ausgeben.
Verwandte Tutorials
Die Arbeit mit Arrays in PHP umfasst viele Funktionen, die sich gegenseitig ergänzen. Hier findest du weiterführende Tutorials zu verwandten Themen:
Häufige Fragen zu array_diff()
Die folgenden Fragen und Antworten klären typische Unsicherheiten beim Einsatz von array_diff() und den verwandten Funktionen.
Ist array_diff() case-sensitive?
Ja, array_diff() unterscheidet zwischen Groß- und Kleinschreibung. "PHP" und "php" gelten als unterschiedliche Werte. Für einen Vergleich ohne Berücksichtigung der Schreibweise kann man array_udiff() mit strcasecmp als Callback verwenden:
<?php
$a = ["PHP", "Python", "JAVA"];
$b = ["php", "java"];
$diff = array_udiff($a, $b, 'strcasecmp');
print_r($diff);
/* Array ( [1] => Python ) */
?>
Bleiben die Schlüssel erhalten?
Ja. array_diff() behält die Schlüssel aus dem ersten Array bei. Das kann zu Lücken in den numerischen Indizes führen. Wer ein fortlaufend nummeriertes Array benötigt, kann das Ergebnis mit array_values() neu indizieren:
<?php
$a = ["rot", "blau", "grün", "gelb"];
$b = ["blau", "gelb"];
$diff = array_diff($a, $b);
print_r($diff);
/* Array ( [0] => rot [2] => grün ) */
$clean = array_values($diff);
print_r($clean);
/* Array ( [0] => rot [1] => grün ) */
?>
Kann array_diff() Duplikate entfernen?
array_diff() ist nicht dafür gedacht, Duplikate zu entfernen. Dafür gibt es array_unique(). Mit array_diff() lassen sich aber gezielt bestimmte Werte aus einem Array herausfiltern, indem man die unerwünschten Werte als zweites Array übergibt.
Was passiert bei leeren Arrays?
Wenn das erste Array leer ist, gibt array_diff() ein leeres Array zurück. Wenn die Vergleichs-Arrays leer sind, enthält das Ergebnis alle Elemente des ersten Arrays, da keiner der Werte in einem leeren Vergleichs-Array gefunden werden kann.
Funktioniert array_diff() mit assoziativen Arrays?
Ja. Bei assoziativen Arrays werden ebenfalls nur die Werte verglichen, nicht die Schlüssel. Wenn zwei assoziative Arrays denselben Wert unter verschiedenen Schlüsseln haben, erkennt array_diff() die Übereinstimmung trotzdem. Für einen Vergleich, der Schlüssel-Wert-Paare gemeinsam betrachtet, ist array_diff_assoc() die richtige Wahl.