A Função array_udiff_assoc() do PHP Explicada
Aprenda como array_udiff_assoc() do PHP funciona: diferencia arrays por chave e um callback personalizado de valores. Exemplos e dicas práticas.
array_udiff_assoc() compara dois ou mais arrays e retorna as entradas do primeiro array que não aparecem em nenhum dos outros. O que a torna especial é como ela compara: as chaves são comparadas com verificação estrita interna, enquanto os valores são comparados por uma função de callback fornecida por você. Esta página explica a assinatura, percorre exemplos práticos (strings, múltiplos arrays e objetos) e aborda as armadilhas mais comuns.
Sintaxe
array_udiff_assoc(
array $array,
array ...$arrays,
callable $value_compare_func
): array$array— o array a comparar a partir de. Apenas suas entradas podem aparecer no resultado....$arrays— um ou mais arrays para comparar contra. Você pode passar quantos quiser.$value_compare_func— um callback que compara dois valores. Deve retornar um inteiro menor que, igual a ou maior que 0 quando o primeiro argumento é considerado respectivamente menor que, igual a ou maior que o segundo — o mesmo contrato usado porusort()e pelo operador spaceship (<=>).
Retorna um novo array com os pares chave/valor sobreviventes de $array. O callback é sempre o último argumento.
Como funciona a comparação
Uma entrada do primeiro array é mantida a menos que outro array tenha tanto a mesma chave (comparada internamente como string) quanto um valor que o callback reporte como igual (retorna 0). Em outras palavras:
- Chaves → comparação estrita interna (o
assocno nome). - Valores → seu callback (o
u, de user-defined, definido pelo usuário).
Esta é a principal diferença em relação a array_diff_assoc(), que compara valores com cast para (string), e em relação a array_udiff(), que ignora as chaves completamente.
Exemplo básico
<?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);
?>Percorrendo chave a chave:
a→"red"vs"red": chaves coincidem, callback retorna0(igual) → removido.b→"green"vs"blue": chaves coincidem, valores diferem → mantido.c→"blue"vs"green": chaves coincidem, valores diferem → mantido.
Portanto, a saída é:
Array
(
[b] => green
[c] => blue
)Comparando contra vários arrays
Você pode passar mais de um array para comparar. Uma entrada sobrevive apenas se estiver ausente de todos os outros arrays. Aqui o callback compara strings por comprimento primeiro, depois 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
// )Apenas item2 difere: "banana" (6 letras) e "cherry" (6 letras) têm o mesmo comprimento, então o callback vai para strcmp(), que os reporta como diferentes. item1 e item3 são idênticos nos dois arrays e são descartados.
Comparando objetos
A verdadeira força de array_udiff_assoc() aparece quando os valores são objetos ou arrays — coisas que não podem ser comparadas com um simples cast para string. O callback decide o que significa "igual". Aqui dois carrinhos são comparados apenas pelo preço, ignorando o nome do produto:
<?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 tem o mesmo preço nos dois carrinhos e é removido; o preço de p2 mudou, então ele sobrevive.
Armadilhas
- O callback é o último argumento, não o segundo. Um erro comum é chamar
array_udiff_assoc($a, $callback, $b). A ordem é sempre: primeiro array, depois os arrays para comparar, então o callback. - O callback compara valores, não chaves. As chaves são tratadas internamente com comparação estrita; você não pode influenciar a correspondência de chaves aqui. Se você precisar de uma comparação de chave personalizada também, use
array_udiff_uassoc(). - Retorne um inteiro, não um boolean. Retornar
true/falsedo callback funciona por acidente (eles são convertidos para1/0) mas é frágil — retorne o resultado de<=>ou um-1/0/1explícito. - O resultado mantém as chaves originais do primeiro array; ele não reindexa.
Quando usar
Use array_udiff_assoc() quando tanto a chave quanto uma comparação de valor personalizada importam — por exemplo, diferenciando dois conjuntos de dados com chaves de objetos, comparando registros sem distinção de maiúsculas e minúsculas enquanto mantém seus identificadores, ou calculando o que mudou entre um estado anterior e o atual. Se as chaves não importam, use array_udiff(); se seus valores são escalares simples, o mais leve array_diff_assoc() geralmente é suficiente.
Conclusão
array_udiff_assoc() é uma ferramenta precisa para encontrar diferenças entre arrays quando tanto as chaves quanto a lógica de valor personalizada importam. Combinando correspondência estrita de chaves com um callback de comparação que você controla, você pode diferenciar estruturas de dados complexas — objetos, arrays aninhados, strings normalizadas — sem escrever loops aninhados ou verificações manuais.