Operadores: aritméticos, de comparação e lógicos

1. Operadores Aritméticos: Operações Matemáticas Básicas

Os operadores aritméticos em PHP permitem realizar operações matemáticas fundamentais. Eles seguem a sintaxe tradicional encontrada em outras linguagens de programação.

<?php
$a = 10;
$b = 3;

echo "Adição: " . ($a + $b) . "\n";        // 13
echo "Subtração: " . ($a - $b) . "\n";     // 7
echo "Multiplicação: " . ($a * $b) . "\n"; // 30
echo "Divisão: " . ($a / $b) . "\n";       // 3.3333333333333 (float)
echo "Módulo: " . ($a % $b) . "\n";        // 1
echo "Exponenciação: " . ($a ** $b) . "\n";// 1000
?>

A divisão em PHP sempre retorna um valor float, a menos que ambos os operandos sejam inteiros e a divisão seja exata. O operador de módulo (%) funciona com inteiros e pode retornar resultados negativos se o dividendo for negativo.

Os operadores de incremento e decremento merecem atenção especial:

<?php
$x = 5;
echo ++$x; // Pré-incremento: 6 (incrementa antes de usar)
echo $x++; // Pós-incremento: 6 (usa o valor, depois incrementa)
echo $x;   // 7

$y = 5;
echo --$y; // Pré-decremento: 4
echo $y--; // Pós-decremento: 4
echo $y;   // 3
?>

2. Operadores de Atribuição Combinados com Aritmética

Além da atribuição simples (=), o PHP oferece operadores combinados que realizam uma operação aritmética e atribuem o resultado simultaneamente:

<?php
$total = 100;

$total += 50;  // equivalente a $total = $total + 50
$total -= 20;  // $total = $total - 20
$total *= 2;   // $total = $total * 2
$total /= 4;   // $total = $total / 4
$total %= 3;   // $total = $total % 3

echo $total; // 2 (após todas as operações)

// Operador de concatenação combinado
$nome = "João";
$nome .= " Silva"; // $nome = $nome . " Silva"
echo $nome; // João Silva
?>

A precedência dos operadores combinados é a mesma do operador de atribuição simples, sendo avaliados após a maioria dos outros operadores. Use parênteses para garantir a ordem desejada em expressões complexas.

3. Operadores de Comparação: Igualdade e Diferença

O PHP possui dois tipos de comparação de igualdade, o que pode gerar confusão para iniciantes:

<?php
// Igualdade frouxa (==) - compara apenas valores
var_dump(5 == "5");     // bool(true)
var_dump(0 == false);   // bool(true)
var_dump(null == "");   // bool(true)

// Igualdade estrita (===) - compara valor E tipo
var_dump(5 === "5");    // bool(false)
var_dump(0 === false);  // bool(false)
var_dump(null === "");  // bool(false)

// Diferença
var_dump(5 != "5");     // bool(false)
var_dump(5 <> "5");     // bool(false) - operador alternativo
var_dump(5 !== "5");    // bool(true)
?>

O "type juggling" (coerção automática de tipos) do PHP pode causar resultados inesperados. Por exemplo, "abc" == 0 retorna true, pois a string é convertida para inteiro (0). Sempre prefira === e !== quando a comparação de tipos for importante.

4. Operadores de Comparação: Relacionais e Nave Espacial

Os operadores relacionais comparam valores e retornam booleanos:

<?php
$a = 10;
$b = 20;

var_dump($a < $b);   // true
var_dump($a > $b);   // false
var_dump($a <= $b);  // true
var_dump($a >= $b);  // false

// Comparação de strings (ordem lexicográfica)
var_dump("apple" < "banana"); // true (a vem antes de b)
var_dump("10" < "2");        // true (compara como string, '1' < '2')
var_dump("10" < 2);          // false (converte string para número)
?>

O operador nave espacial (<=>), introduzido no PHP 7, é extremamente útil para ordenação:

<?php
echo 5 <=> 5;  // 0 (iguais)
echo 5 <=> 3;  // 1 (primeiro é maior)
echo 3 <=> 5;  // -1 (primeiro é menor)

// Exemplo prático com usort
$numeros = [3, 1, 4, 1, 5, 9];
usort($numeros, fn($a, $b) => $a <=> $b);
print_r($numeros); // [1, 1, 3, 4, 5, 9]
?>

5. Operadores Lógicos: AND, OR, NOT e XOR

Os operadores lógicos permitem combinar expressões booleanas:

<?php
$a = true;
$b = false;

// AND
var_dump($a && $b);  // false
var_dump($a and $b); // false (menor precedência)

// OR
var_dump($a || $b);  // true
var_dump($a or $b);  // true (menor precedência)

// NOT
var_dump(!$a);       // false

// XOR (ou exclusivo)
var_dump($a xor $b); // true (apenas um é verdadeiro)
var_dump($a xor $a); // false
?>

A diferença de precedência entre &&/|| e and/or pode causar bugs sutis:

<?php
$resultado = true and false; // $resultado = true (atribuição primeiro)
$resultado = true && false;  // $resultado = false (&& avaliado primeiro)

// Curto-circuito
$arquivo = null;
if ($arquivo && file_exists($arquivo)) { // Seguro: não avalia file_exists se $arquivo for null
    echo "Arquivo existe";
}
?>

6. Operador Ternário e Fusão Null (Null Coalescing)

O operador ternário oferece uma sintaxe concisa para condições simples:

<?php
$idade = 18;
$status = ($idade >= 18) ? "Adulto" : "Menor";
echo $status; // Adulto

// Aninhamento (evite para legibilidade)
$nota = 7.5;
$conceito = ($nota >= 9) ? "A" : (($nota >= 7) ? "B" : "C");
echo $conceito; // B
?>

O operador de fusão null (??) verifica se uma variável existe e não é null:

<?php
$nome = $_GET['nome'] ?? 'Visitante'; // Se não existir, usa 'Visitante'
echo $nome;

// Encadeamento
$endereco = $usuario->endereco ?? $usuario->enderecoPadrao ?? 'Não informado';

// Nullsafe operator (PHP 8+)
$cidade = $usuario?->endereco?->cidade; // Retorna null se qualquer parte for null
?>

7. Precedência e Associatividade na Prática

Conhecer a precedência dos operadores evita erros comuns:

<?php
// Precedência: ** > *, /, % > +, -
$resultado = 2 + 3 * 4;  // 14 (multiplicação primeiro)
$resultado = (2 + 3) * 4; // 20 (parênteses alteram)

// Lógicos: ! > && > || > and > or
$condicao = true || false && false; // true (&& avaliado primeiro)
$condicao = (true || false) && false; // false

// Exemplo complexo
$x = 5;
$y = 10;
$z = ($x > 3 && $y < 20) || !($x == $y);
var_dump($z); // true
?>

Sempre que houver dúvida, use parênteses para explicitar a ordem de avaliação. Isso melhora a legibilidade e evita bugs.

8. Casos Especiais e Boas Práticas

Operadores com arrays possuem comportamentos específicos:

<?php
// União de arrays (+)
$a = ['a' => 1, 'b' => 2];
$b = ['b' => 3, 'c' => 4];
$resultado = $a + $b; // ['a' => 1, 'b' => 2, 'c' => 4] (mantém primeiro)

// Comparação de arrays
var_dump([1, 2] == [1, 2]);   // true (mesmos valores)
var_dump([1, 2] === [1, 2]);  // true (mesmos valores e tipos)
var_dump([1, 2] == [2, 1]);   // false (ordem diferente)
?>

Erros comuns a evitar:

<?php
// Confundir = com ==
if ($x = 5) { // ATENÇÃO: atribuição, não comparação! Sempre true!
    echo "Isso sempre executa";
}

// Efeitos colaterais em expressões lógicas
$arquivo = fopen('dados.txt', 'r');
if ($linha = fgets($arquivo) && $linha !== false) { // Bug: && tem precedência maior
    echo $linha; // Mostra true/false, não o conteúdo
}
// Correção:
if (($linha = fgets($arquivo)) && $linha !== false) {
    echo $linha;
}
?>

Boas práticas incluem: usar === e !== como padrão, evitar aninhamento excessivo de ternários, e sempre verificar o tipo dos operandos em comparações.

Referências