La Funzione array_udiff_assoc() di PHP Spiegata
Come funziona array_udiff_assoc() in PHP: confronta array per chiave e callback personalizzato. Sintassi, esempi e casi particolari.
array_udiff_assoc() confronta due o più array e restituisce le voci del primo array che non compaiono in nessuno degli altri. La sua particolarità sta nel modo in cui effettua il confronto: le chiavi vengono confrontate con un controllo interno rigoroso, mentre i valori vengono confrontati tramite una funzione di callback fornita dall'utente. Questa pagina spiega la firma della funzione, illustra esempi pratici (stringhe, più array e object) e descrive i casi particolari che possono trarre in inganno.
Sintassi
array_udiff_assoc(
array $array,
array ...$arrays,
callable $value_compare_func
): array$array— l'array da cui partire per il confronto. Solo le sue voci possono comparire nel risultato....$arrays— uno o più array con cui confrontare. È possibile passarne quanti se ne desidera.$value_compare_func— un callback che confronta due valori. Deve restituire un intero minore di, uguale a, o maggiore di 0 quando il primo argomento è rispettivamente minore di, uguale a, o maggiore del secondo — lo stesso contratto utilizzato dausort()e dall'operatore spaceship (<=>).
Restituisce un nuovo array contenente le coppie chiave/valore superstiti di $array. Il callback è sempre l'ultimo argomento.
Come funziona il confronto
Una voce del primo array viene mantenuta a meno che un altro array non abbia sia la stessa chiave (confrontata internamente come string) sia un valore che il callback giudica uguale (restituisce 0). In altre parole:
- Chiavi → confronto rigoroso e interno (il termine
assocnel nome). - Valori → il tuo callback (la
u, da user-defined, definito dall'utente).
Questa è la differenza fondamentale rispetto a array_diff_assoc(), che confronta i valori mediante casting a (string), e rispetto a array_udiff(), che ignora completamente le chiavi.
Esempio base
<?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);
?>Analizzando chiave per chiave:
a→"red"vs"red": le chiavi corrispondono, il callback restituisce0(uguale) → rimosso.b→"green"vs"blue": le chiavi corrispondono, i valori differiscono → mantenuto.c→"blue"vs"green": le chiavi corrispondono, i valori differiscono → mantenuto.
Quindi l'output è:
Array
(
[b] => green
[c] => blue
)Confronto con più array
È possibile passare più di un array con cui confrontare. Una voce sopravvive solo se è assente da tutti gli altri array. In questo esempio il callback confronta le stringhe prima per lunghezza, poi alfabeticamente:
<?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
// )Solo item2 è diverso: "banana" (6 lettere) e "cherry" (6 lettere) hanno la stessa lunghezza, quindi il callback ricorre a strcmp(), che le segnala come diverse. item1 e item3 sono identici in entrambi gli array e vengono scartati.
Confronto di object
La vera forza di array_udiff_assoc() emerge quando i valori sono object o array — elementi che non si possono confrontare con un semplice cast a string. Il callback stabilisce cosa significa "uguale". In questo esempio due carrelli vengono confrontati solo per prezzo, ignorando il nome del prodotto:
<?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 ha lo stesso prezzo in entrambi i carrelli e viene rimosso; il prezzo di p2 è cambiato, quindi sopravvive.
Casi particolari
- Il callback è l'ultimo argomento, non il secondo. Un errore comune è chiamare
array_udiff_assoc($a, $callback, $b). L'ordine è sempre: primo array, poi gli array con cui confrontare, infine il callback. - Il callback confronta i valori, non le chiavi. Le chiavi vengono gestite internamente con confronto rigoroso; non è possibile influenzare la corrispondenza delle chiavi da qui. Se serve anche un confronto personalizzato delle chiavi, utilizza
array_udiff_uassoc(). - Restituire un intero, non un boolean. Restituire
true/falsedal callback funziona per caso (vengono convertiti in1/0) ma è fragile — restituisci il risultato di<=>o un esplicito-1/0/1. - Il risultato conserva le chiavi originali del primo array; non viene reindicizzato.
Quando usarla
Utilizza array_udiff_assoc() quando contano sia la chiave sia un confronto personalizzato dei valori — ad esempio per confrontare due dataset con chiave di object, confrontare record in modo case-insensitive mantenendo i loro identificatori, o calcolare cosa è cambiato tra uno stato precedente e quello attuale. Se le chiavi non sono rilevanti, usa array_udiff(); se i valori sono semplici scalari, la più leggera array_diff_assoc() è solitamente sufficiente.
Conclusione
array_udiff_assoc() è uno strumento preciso per individuare le differenze tra array quando contano sia le chiavi sia una logica personalizzata sui valori. Combinando la corrispondenza rigorosa delle chiavi con un callback di confronto che puoi controllare, è possibile fare il diff di strutture dati complesse — object, array annidati, stringhe normalizzate — senza scrivere cicli annidati o controlli manuali.