# PHP para Iniciantes: Operadores Lógicos

Como eu já falei sobre os [Operadores Bitwise](https://blog.kaiquegarcia.dev/php-para-iniciantes-operadores-bitwise), vou presumir que você já entende 90% do conteúdo mesmo se nunca tiver lido sobre isso em outro lugar.

Eu falo dessa forma porque é preciso entender operadores lógicos para trabalhar com bits, ao menos a lógica da álgebra booleana. Na computação quântica, tudo fica meio diferente, mas pode ficar tranquilo(a) pois nem vou tocar nesse assunto.

O lance é que eu mencionei tabela da verdade naquele artigo e isso é a base para compreender as operações lógicas que vamos falar hoje.

> Então você vai reescrever as tabelas da verdade, Kiko?

**Sim**.

Porém, diferente dos operadores bitwise, os operadores de hoje só trabalham com **booleanos**. Não significa que você está sendo forçado a converter os dados antes de utilizá-los, mas com certeza o interpretador vai tentar fazer essa transformação.

Dito isso, primeiro eu vou fazer um resumo sobre casting de outros tipos de dados primitivos para `boolean`, pois sei que essa informação ficou bem espalhada ao longo dos artigos, e depois vou mostrar os operadores destacando suas possibilidades com uma tabela da verdade. Vamos começar?

## Casting para booleano

Se você já conhece os termos **truthy** ou **falsy**, você provavelmente já entende do que irei falar nesta seção. Se for o caso, sinta-se a vontade para saltar para a próxima, ok?

Enfim, muitas vezes precisamos constatar fatos na lógica de programação, sempre almejando ter a maior precisão possível. Estes fatos devem ser destacados de tal forma que você não poderia contradizê-los.

Falando dessa forma, significa que uma afirmação na lógica ou **é verdade** ou **é falsa**. Não existe meio termo. Isso é o que representamos como um **booleano**.

Na maioria das vezes, os booleanos que criamos destacam uma afirmação que perguntamos, sendo facilmente legível para saber o que estamos tentando validar. Mas e quando, ao invés de uma pergunta, temos apenas uma informação?

Por exemplo, qual é o valor booleano da string `'Kaique'`? Por que raios você quer saber se `'Kaique'` é verdadeiro ou falso? É exatamente essa a sensação que dá quando você converte um dado para booleano sem armazenar em uma variável clara, retirando a total semântica sem contexto algum.

Continuando com o exemplo, se, ao invés de somente perguntar se é verdade ou falso, eu armazenasse `$nome = 'Kaique'` e depois `$temNome = boolval($nome)`, faria mais sentido?

**Provavelmente sim**. O fato é que tudo depende do contexto e de qual verdade você busca no seu código. Os castings não estão aí só de enfeite, obviamente.

> Tá, Kiko, acho que entendi... Mas quais são as conversões que você tava mencionando?

É bem simples! Vou escrever uma tabelinha abaixo com os tipos de dados primitivos, com exceção do booleano que já é booleano:

| Tipo | Valores Falsos | Valores Verdadeiros |
| --- | --- | --- |
| `int` | `0` | qualquer outro valor |
| `float` | `0.0` | qualquer outro valor |
| `string` | `''` (texto vazio) ou `'0'` (numérico `int` 0) | qualquer outro valor, **incluindo o `'0.0'`** (numérico `float` 0.0) |
| `array` | `[]` (array vazio) | qualquer outro valor |
| `object` | nunca, se realmente for um objeto | qualquer valor |
| `callable` | nunca, se realmente for um acionável | qualquer valor |
| `iterable` | nunca, se realmente for um iterável | qualquer valor |
| `resource` | nunca, se realmente for um recurso | qualquer valor |
| `null` | qualquer valor | nunca, se realmente for nulo |

> Caraca, Kiko, por que o texto numérico `'0.0'` dá `true`?! Sendo que o ponto flutuante `0.0` dá false...

Essa é uma boa pergunta e um dos maiores erros de design do PHP. Você pode até dar uma boa pesquisada sobre isso, tem muitas discussões fervorosas sobre o assunto e o ponto é: por que o interpretador aceita que '0' seja falso, mas não '0.0'? O bom senso pode nos levar ao engano aqui. O ideal era que somente a string vazia fosse `false`, mas criaram uma exceção para o texto numérico `'0'`, gerando o **CAOS**.

<center>![XABLAU](https://c.tenor.com/NK6cB_LTu3YAAAAM/good-morning-xablau.gif)</center>

E se aceita o texto numérico `'0'`, há quem argumente que também poderia ter aceitado os booleanos escritos `'false'` ou `'true'`, porém eu discordo desse ponto. Afinal, nós **realmente temos um conceito de texto numérico**. Nunca existiu **texto booleano** na linguagem, não faria sentido armazenar booleanos como strings.

**Conclusão do rolê**: muito cuidado ao lidar com **texto numérico** e casting para **booleano**. Pode dar muito ruim.

Agora que você sabe quando cada tipo de dado é `false` ou `true`, vamos seguir para os operadores com exemplos variados. Bora lá?

----

## Operador `AND` ou `&&`

Começando com a tabela da verdade:

| `$a` | `$b` | `$a && $b` |
| --- | --- | --- |
| `false` | `false` | `false` |
| `false` | `true` | `false` |
| `true` | `false` | `false` |
| `true` | `true` | `true` |

Podemos destacar apenas a última linha da tabela, que é o único momento em que o resultado da operação dá `true`: quando tanto o primeiro quanto o segundo dado são `true`.

Semanticamente falando, `$a && $b` significa "*`$a` e `$b` são verdade*", por isso que permanece daquela forma.

> Kiko, não seria mais legível escrever `$a and $b`?

Sim, seria! Mas os operadores `and` e `&&` não são exatamente iguais. Eles diferem na ordem de precedência e o `and` pode causar uma confusão enorme, pois ele tem menos prioridade do que os operadores de atribuição.

Por exemplo:

```php
<?php

$nome = 'Kaique';
$aniversario= '31/10'; // tá chegando hein? :hehehehe:

$temNomeEAniversario = $nome && $aniversario;
var_dump($temNomeEAniversario); // bool(true)

$temNomeEAniversario = $nome and $aniversario;
var_dump($temNomeEAniversario); // string('Kaique')
```

> QUE

Exatamente... No último exemplo, o que realmente acontece no interpretador é `($temNomeEAniversario = $nome) && $aniversario`, antes mesmo de qualquer casting acontecer. Então se você mudar `$aniversario` para `''`, somente a primeira comparação vai dar certo, pois a segunda continuará sendo `'Kaique'`.

Se você se interessou sobre ordem de precedência, eu mencionei no artigo [Operadores - Precedência](https://blog.kaiquegarcia.dev/php-para-iniciantes-operadores-precedencia). Não vou mais mencionar esses exemplos nos próximos pois são basicamente a mesma coisa: o **operador escrito semanticamente** tem menos prioridade do que os operadores de atribuição.

## Operador `OR` ou `||`

| `$a` | `$b` | `$a or $b` |
| --- | --- | --- |
| `false` | `false` | `false` |
| `false` | `true` | `true` |
| `true` | `false` | `true` |
| `true` | `true` | `true` |

No caso desse operador, sempre que um dos dados envolvidos for verdade, o resultado será `true`. A leitura semântica de ` $a || $b` é "*`$a` ou `$b` é verdade*", podendo ser ambos simultaneamente.

## Operador `XOR`

**Aviso**: esse não tem alternativa com símbolo, somente por semântica, o que pode ser um risco utilizar. Então, sempre que precisar dele, agrupe-o com os dados que deseja operar!

| `$a` | `$b` | `$a xor $b` |
| --- | --- | --- |
| `false` | `false` | `false` |
| `false` | `true` | `true` |
| `true` | `false` | `true` |
| `true` | `true` | `false` |

O `XOR` é um `eXclusive OR`, que significa `Ou exclusivo`, e funciona exatamente como o operador anterior, exceto que não aceita o caso de quando os dois dados são verdade (última linha).

A leitura semântica de `$a xor $b` é "*somente `$a` ou somente `$b` é verdade*".

## Operador `!`

Esse é o clássico da programação: o operador de negação. Diferente dos anteriores, esse age somente no dado à sua direita, ao invés de dois dados. Por tanto, a tabela da verdade não usa duas variáveis como as anteriores:

| `$a` | `!$a` |
| --- | --- |
| `false` | `true` |
| `true` | `false` |

E é isso mesmo, ele apenas reverte o valor. Sua semântica em cada caso é bem simples:

- `!false` => `true` = `o falso é falso, logo é verdade`.
- `!true` => `false` = `a verdade é falsa, logo é falso`.

Então a leitura semântica de `!$a` é "*o inverso de `$a`*", onde só sabemos se é verdade quando sabemos que `$a` é falso.

----

## Exemplo

Vamos brincar? Copie esse código e cole no [PHP Sandbox Online](https://sandbox.onlinephpfunctions.com/). O código abaixo irá gerar a tabela da verdade de cada operador! Legal?

```php
<?php

// Gerador de tabelas da verdade
// https://blog.kaiquegarcia.dev
// Pode brincar à vontade ;)

// Primeiramente, mapeamos funções que serão nossos operadores com dois argumentos
$operadores = [
    'and' => fn($a, $b) => $a && $b,
    'or' => fn($a, $b) => $a || $b,
    'xor' => fn($a, $b) => ($a xor $b),
];

// Criamos uma função para converter booleano em string "true" ou "false" (só pra exibir bonitinho)
function strbool($bool) {
    return $bool ? 'true' : 'false';
}

// Depois fazemos um loop sobre os operadores de duplo argumento
foreach ($operadores as $operacao => $funcao) {
    echo "Operador $operacao" . PHP_EOL;

    // iniciamos o cabeçalho da tabela: | coluna 1 | coluna 2 | coluna 3 |
    echo '| $a | $b | $a  ' . $operacao . ' $b |' . PHP_EOL;
    echo '| --- | --- | --- |' . PHP_EOL;

    // fazemos um loop de 0,1 para variar $a
    for ($a = 0; $a < 2; $a++) {
        // e mais um loop de 0,1 para variar $b
        for ($b = 0; $b < 2; $b++) {
            // mesmo esquema do cabeçalho: | coluna 1 | coluna 2 | coluna 3 |
            echo '| ' . strbool($a) . ' | ' . strbool($b) . ' | ' . strbool($funcao($a, $b)) . ' |' . PHP_EOL;
        }
    }

    // Uma quebra de linha só pra separar na impressão
    echo PHP_EOL;
}

// Depois fazemos mais uma tabela pro operador de negação, que só usa um argumento

echo 'Operador de negação' . PHP_EOL;
echo '| $a | !$a |' . PHP_EOL;
echo '| --- | --- |' . PHP_EOL;

for ($a = 0; $a < 2; $a++) {
    echo '| ' . strbool($a) . ' | ' . strbool(!$a) . ' |' . PHP_EOL;
}
```

E por hoje é só! Curtiu? Comenta e compartilha! Deu pra ver como eu gosto de lógica, né? Essa é uma parte essencial para o bom entendimento de como o código se comporta. Óbvio que saber *só isso* não é exatamente um diferencial, é o básico. Sendo assim, nem preciso pedir para investir nisso, certo?

No próximo artigo, falaremos sobre o **Operador de concatenação** (e sua versão com atribuição). **Spoiler**: nós usamos ele hoje no gerador de tabelas da verdade! **Muito!** Mas irei explicar melhor no próximo, fechado?

**Inté!**
