PHPs array_udiff_assoc()-Funktion erklärt
Wie array_udiff_assoc() in PHP funktioniert: Array-Differenz per Schlüssel und eigenem Callback. Syntax, Beispiele, Objekte und Stolperfallen.
array_udiff_assoc() vergleicht zwei oder mehr Arrays und gibt die Einträge aus dem ersten Array zurück, die in keinem der anderen vorkommen. Das Besondere daran ist wie verglichen wird: Schlüssel werden mit der eingebauten strengen Prüfung verglichen, während Werte durch eine von Ihnen bereitgestellte Callback-Funktion verglichen werden. Diese Seite erklärt die Signatur, zeigt funktionierende Beispiele (Strings, mehrere Arrays und Objekte) und beleuchtet die Stolperfallen, über die man leicht stolpert.
Syntax
array_udiff_assoc(
array $array,
array ...$arrays,
callable $value_compare_func
): array$array— das Array, aus dem verglichen werden soll. Nur seine Einträge können im Ergebnis erscheinen....$arrays— ein oder mehrere Arrays, gegen die verglichen wird. Es können beliebig viele übergeben werden.$value_compare_func— ein Callback, der zwei Werte vergleicht. Er muss eine ganze Zahl zurückgeben, die kleiner als, gleich oder größer als 0 ist, wenn das erste Argument als kleiner, gleich bzw. größer als das zweite gilt — derselbe Vertrag wie beiusort()und dem Raumschiff-Operator (<=>).
Die Funktion gibt ein neues Array der verbleibenden Schlüssel/Wert-Paare aus $array zurück. Der Callback ist immer das letzte Argument.
Wie der Vergleich funktioniert
Ein Eintrag aus dem ersten Array wird beibehalten, sofern kein anderes Array sowohl denselben Schlüssel (intern als Strings verglichen) als auch einen Wert hat, den der Callback als gleich meldet (gibt 0 zurück). Mit anderen Worten:
- Schlüssel → strenger, eingebauter Vergleich (das
associm Namen). - Werte → Ihr Callback (das
u, für user-defined, also benutzerdefiniert).
Dies ist der wesentliche Unterschied zu array_diff_assoc(), das Werte mit (string)-Casting vergleicht, und zu array_udiff(), das Schlüssel vollständig ignoriert.
Einfaches Beispiel
<?php
function compareArrays($a, $b) {
if ($a === $b) {
return 0;
}
return ($a > $b) ? 1 : -1;
}
$array1 = array("a" => "red", "b" => "green", "c" => "blue");
$array2 = array("a" => "red", "b" => "blue", "c" => "green");
$result = array_udiff_assoc($array1, $array2, "compareArrays");
print_r($result);
?>Schlüssel für Schlüssel durchgegangen:
a→"red"vs."red": Schlüssel stimmen überein, Callback gibt0zurück (gleich) → entfernt.b→"green"vs."blue": Schlüssel stimmen überein, Werte unterscheiden sich → behalten.c→"blue"vs."green": Schlüssel stimmen überein, Werte unterscheiden sich → behalten.
Die Ausgabe lautet also:
Array
(
[b] => green
[c] => blue
)Vergleich gegen mehrere Arrays
Es können mehr als ein Array zum Vergleich übergeben werden. Ein Eintrag überlebt nur dann, wenn er in jedem anderen Array fehlt. Hier vergleicht der Callback Strings zuerst nach Länge, dann alphabetisch:
<?php
function compareValues($a, $b) {
return strlen($a) <=> strlen($b) ?: strcmp($a, $b);
}
$current = ["item1" => "apple", "item2" => "banana", "item3" => "kiwi"];
$baseline = ["item1" => "apple", "item2" => "cherry", "item3" => "kiwi"];
$result = array_udiff_assoc($current, $baseline, "compareValues");
print_r($result);
// Array
// (
// [item2] => banana
// )Nur item2 unterscheidet sich: "banana" (6 Buchstaben) und "cherry" (6 Buchstaben) haben die gleiche Länge, weshalb der Callback auf strcmp() zurückfällt, das sie als verschieden ausweist. item1 und item3 sind in beiden Arrays identisch und werden verworfen.
Objekte vergleichen
Die eigentliche Stärke von array_udiff_assoc() zeigt sich, wenn Werte Objekte oder Arrays sind — Dinge, die man nicht mit einem einfachen String-Cast vergleichen kann. Der Callback entscheidet, was „gleich" bedeutet. Hier werden zwei Warenkörbe ausschließlich nach dem Preis verglichen, ohne den Produktnamen zu berücksichtigen:
<?php
class Product {
public function __construct(public string $name, public float $price) {}
}
function byPrice(Product $a, Product $b): int {
return $a->price <=> $b->price;
}
$cart = [
"p1" => new Product("Pen", 1.50),
"p2" => new Product("Notebook", 3.00),
];
$reference = [
"p1" => new Product("Pen", 1.50),
"p2" => new Product("Notebook", 4.25),
];
$diff = array_udiff_assoc($cart, $reference, "byPrice");
foreach ($diff as $key => $product) {
echo "$key => {$product->name} ({$product->price})\n";
}
// p2 => Notebook (3)p1 hat in beiden Warenkörben denselben Preis und wird entfernt; der Preis von p2 hat sich geändert und er bleibt erhalten.
Stolperfallen
- Der Callback ist das letzte Argument, nicht das zweite. Ein häufiger Fehler ist der Aufruf
array_udiff_assoc($a, $callback, $b). Die Reihenfolge ist immer: erstes Array, dann die Arrays zum Vergleich, dann der Callback. - Der Callback vergleicht Werte, nicht Schlüssel. Schlüssel werden intern mit strengem Vergleich behandelt; der Schlüsselabgleich kann hier nicht beeinflusst werden. Wenn auch ein benutzerdefinierter Schlüssel-Vergleich benötigt wird, greift man auf
array_udiff_uassoc()zurück. - Eine ganze Zahl zurückgeben, kein boolean. Die Rückgabe von
true/falseaus dem Callback funktioniert zufällig (sie werden zu1/0gecastet), ist aber fehleranfällig — besser das Ergebnis von<=>oder explizit-1/0/1zurückgeben. - Das Ergebnis behält die ursprünglichen Schlüssel aus dem ersten Array; es wird nicht neu indiziert.
Wann verwenden
array_udiff_assoc() empfiehlt sich, wenn sowohl der Schlüssel als auch ein benutzerdefinierter Wertvergleich eine Rolle spielen — etwa beim Vergleich zweier Datensätze mit Schlüsseln aus Objekten, beim Groß-/Kleinschreibungsunabhängigen Vergleich von Datensätzen unter Beibehaltung ihrer Bezeichner oder beim Ermitteln von Änderungen zwischen einem vorherigen und dem aktuellen Zustand. Wenn Schlüssel keine Rolle spielen, empfiehlt sich array_udiff(); bei einfachen skalaren Werten reicht das leichtgewichtigere array_diff_assoc() meist aus.
Fazit
array_udiff_assoc() ist ein präzises Werkzeug zum Auffinden von Unterschieden zwischen Arrays, wenn sowohl Schlüssel als auch benutzerdefinierte Wertlogik wichtig sind. Durch die Kombination aus striktem Schlüsselabgleich und einem selbst gesteuerten Vergleichs-Callback lassen sich komplexe Datenstrukturen — Objekte, verschachtelte Arrays, normalisierte Strings — vergleichen, ohne verschachtelte Schleifen oder manuelle Prüfungen schreiben zu müssen.