# PHP para Iniciantes: Operadores de Anulidade

Primeiramente, preciso te contar que esse artigo não existe na documentação oficial do PHP. Eu inventei esse título - o que pode parecer genial e ao mesmo tempo estúpido - baseado no que acredito fazer sentido sobre o assunto da vez. E por ser um nome inventado, depois de ler tudo, comenta aí se fez sentido, pode ser? Obrigado desde já.

Esse é o último artigo da seção que fala sobre Operadores e **eu já falei sobre tudo o que será mencionado aqui**.

> Ué, Kiko... Se você já falou, por que escrever um artigo?

Por que o artigo onde escrevi foi o [Operador de Controle de Erro](https://blog.kaiquegarcia.dev/php-para-iniciantes-operador-de-controle-de-erro), o que pode levar a entender que os operadores que quero apresentar só servem para evitar erros e não é esse o ponto. Eu apenas mencionei formas de se fazer tratativas, assim como faço em todo artigo, não é mesmo?

Então hoje nós vamos falar sobre dois operadores relativamente recentes na linguagem:

- **null coalescing operator**, que chamarei de **operador de alternativa de anulidade** (mas a tradução correta é **operador de coalescência nula**);
- **nullsafe operator**, que vou traduzir para **operador de prevenção de anulidade**.

Vale ressaltar que ninguém os chama como as traduções que fiz, então se for comentar com alguém, usa o nome em inglês, beleza? Gosto de traduzir dessa forma para que iniciantes possam ter uma ideia clara do motivo da existência desses operadores e ter uma certa clareza no próprio nome.

Começando pela ordem cronológica de lançamentos...

## Operador `??` (*alternativa de anulidade*)

Esse operador surgiu na versão 7 do PHP e veio para abalar as equações ternárias. Basicamente, existia um monte de apliações PHP que, para evitar valores negativos (os `false` quando convertido para booleano), escrevia ternários redundantes. Por exemplo:

```php
<?php

$pessoa = ['nome' => null]; // essa pessoa não tem nome :O

$nomeDaPessoa = $pessoa['nome'] ? $pessoa['nome'] : 'Sem Nome';
var_dump($nomeDaPessoa); // string(Sem Nome);
```

Para quem não sabe, uma equação ternária é o equivalente a `if-else` que serve somente para atribuir um valor numa mesma variável. O código acima é o equivalente a:

```php
<?php

$pessoa = ['nome' => null];

if ($pessoa['nome']) {
    $nomeDaPessoa = $pessoa['nome'];
} else {
    $nomeDaPessoa = 'Sem Nome';
}

var_dump($nomeDaPessoa); // string(Sem Nome);
```

O benéficio de utilizar equação ternária nesses casos é que você não repete a declaração da variável `$nomeDaPessoa` duas vezes. E apesar de, nesse exemplo, a ternária estar relativamente legível, na prática não é bem assim.

O padrão é que o ternário acabe sendo uma linha extensa. **Tem quem coloque ternários dentro de ternários** (<strike>*confesso que já cometi esse crime*</strike>). Então a coisa vai ficando feia.

Daí veio o PHP 7 com essa solução maravilhosa. Se a intenção é usar o ternário para dar um comando "**use esse valor ou o outro se o primeiro não estiver definido**", você pode resumir isso com o **operador de alternativa de anulidade** (daí essa tradução):

```php
<?php

$pessoa = ['nome' => null];

$nomeDaPessoa = $pessoa['nome'] ?? 'Sem Nome';

var_dump($nomeDaPessoa); // string(Sem Nome)
```

Com isso, você não precisa repetir o `$pessoa['nome']` duas vezes. Além disso, você pode fazer uma cadeia de alternativas, que vão sendo "testadas" da esquerda pra direita (se você não isolar um grupo com parênteses):

```php
<?php

// não me pergunte por que alguém teria três nomes...
$pessoa = ['nome1' => null, 'nome2' => null, 'nome3' => 'Cleyton'];

$nomeDaPessoa = $pessoa['nome1'] ?? $pessoa['nome2'] ?? $pessoa['nome3'] ?? 'Sem Nome';

var_dump($nomeDaPessoa); // string(Cleyton)
```

Legal?! Então vamos para o próximo.

## Operador `?->` (*prevenção de anulidade*)

Este operador veio ainda mais tarde que anterior, chegando bem fresquinho no PHP 8. Sua principal função é garantir que o que quer que esteja querendo acessar de um objeto só seja acessado se o objeto não for nulo.

> Como assim, Kiko?

E lá vamos nós... :hehe:

```php
<?php

class Exemplo
{
    public function echo(): void
    {
        echo 'Deu sorte, gerou uma instância' . PHP_EOL;
    }

    public static function getInstance(): self|null
    {
        if (rand(0,1)) {
            return null;
        }
        return new self;
    }
}

for($index = 0; $index < 10000; $index++) {
    $exemplo = Exemplo::getInstance();
    $exemplo->echo();
}
```

No código acima, você chama o método estático `getInstance` para obter uma nova instância da classe `Exemplo`. O que acontece é: você tem 50% de chance de receber `null` ou a tal nova instância.

O que acontece na linha seguinte se você receber `null`? Bom, vai encerrar a execução com um **Fatal Error**, pois não tem como acessar o método `echo` de um  `null`.

```html
<b>Fatal Error</b>: Uncaught Error: Call to a member function echo() on null in [...]
```

Então **pode ser interessante se prevenir contra esse cenário**. E com esse operador isso é extremamente fácil: basta adicionar uma interrogação antes da chamada do método, ficando `?->echo()`:

```php
<?php

class Exemplo
{
    public function echo(): void
    {
        echo 'Deu sorte, gerou uma instância' . PHP_EOL;
    }

    public static function getInstance(): self|null
    {
        if (rand(0,1)) {
            return null;
        }
        return new self;
    }
}

for($index = 0; $index < 10000; $index++) {
    $exemplo = Exemplo::getInstance();
    $exemplo?->echo();
}
```

Assim, quando `$exemplo` for `null`, o interpretador não irá executar mais nada, apenas retornar `null`.

> Ele retorna `null` pra quem, Kiko?

Pra quem estiver recebendo o resultado da chamada. No caso acima, como o método `echo` é `void`, não esperamos retorno algum. Mas poderíamos estar retornando `boolean` e esse fluxo adicionaria um caso de exceção que aplica `null`.

Dito isso, é preciso estar atento(a) sobre onde você irá aplicar esse operador, pois se o cenário não prever um valor `null`, tudo pode virar uma catástrofe, talvez pior do que sem o operador, rs.

**Observação importante**: esse operador serve SOMENTE para leitura de dados. Se você o chamar num fluxo de atribuição ou tentar criar uma referência a partir dele, será recebido(a) com um belíssimo **Fatal Error**. Tenta aí:

```php
<?php

class Exemplo
{
    public string $nome = 'Cleyton';

    public static function getInstance(): self|null
    {
        if (rand(0,1)) {
            return null;
        }
        return new self;
    }
}


$exemplo = Exemplo::getInstance();
$exemplo?->nome = 'Clarissa'; // Fatal Error
// comente a linha de cima pra ver o Fatal Error debaixo
$nome = &$exemplo?->nome; // Fatal Error
```

Assim como o **null coalescing**, você também pode fazer uma cadeia de prevenções...

```php
<?php

$pessoa = null; // tá explícito que é null só por causa do exemplo, ok?!

$resultado = $pessoa?->buscaPai()?->buscaTelefone()?->mandaSms('Seu filho bateu nos moleques da escola');

var_dump($resultado); // NULL

```

E é isso! Um artigo bem curtinho pra conhecer esses operadores que merecem sim um artigo exclusivo pra falar sobre eles.

Curtiu? Comenta e compartilha! Chama os amigos pra estudar PHP e tirar dúvidas comigo, hehe. No próximo artigo, começaremos a próxima seção: **Estruturas de Controle**.

**Inté!**
