# PHP para Iniciantes: Estruturas de Controle - CONTINUE

*"**Continue** a nadar"* é uma frase que marcou toda uma geração e que remete a sensação de **loops infinitos**, certo? Mas se você partir desse ponto de vista, vai acabar tendo uma ideia errada. Na programação, `continue` é um verbo executado dentro de um laço e não é exatamente um *"Ok, continue o que está fazendo"* (se fosse o caso, bastaria não colocar instrução alguma...), está mais para *"Pera, deu ruim, encerra aqui e **continue** do próximo laço"*.

> Como assim, Kiko?

Calma, vamos do começo.

## Uma reflexão sobre semântica

O verbo `continue` afeta as mesmas estruturas que o `break`: `while`, `do-while`, `for`, `foreach` e `switch`. No entanto, peço que evite utilizar em `switch`, especificamente, pois não faz sentido algum e a partir do PHP 7.3 já está gerando **Warning** - o que significa que em algum momento será um erro, oficialmente falando.

> Ok, Kiko, eu nem vi switch ainda e você já tá falando o que não usar?

Hehehehe, sim... Faz parte, né?

Voltando a reflexão, vamos relembrar a semântica simplificada do `for`:

- `PARA (configuração dos loops) FAÇA (ação)`

Certo? Nesse cenário, o `continue` seria um verbo acionado dentro da `ação`. Por tanto, sua reflexão precisa ser a nível de unicidade de um laço. Então imagine que você tem algum critério para processar cada laço, mas que esse critério não deve interromper todo o fluxo, apenas ignorar os laços que não forem aceitos.

> Isso não é a mesma coisa que o `break`, Kiko?

**Não!** Vai ficar mais claro a seguir. Mas o ponto é que o `break` **ENCERRA** os laços, enquanto o `continue` apenas salta para a próxima iteração.

Voltando ao cenário, geralmente os critérios são feitos em `if` e, sendo o caso, nós temos a semântica `SE (isso) ENTÃO (aquilo)`. Aqui, `aquilo = continue`. Com isso, a semântica do `continue` se soma à semântica do `if`: `SE (isso) ENTÃO CONTINUE PARA A PRÓXIMA ITERAÇÃO`.

> `continue` = `CONTINUE PARA A PRÓXIMA ITERAÇÃO`? Orra, Kiko... Não tinha algo mais curto não?

Se o cenário fosse uma fila de atendimento, seria `CHAME O PRÓXIMO`. Tudo depende do contexto.

## A sintaxe

Bem, agora que você já entendeu a semântica, você pode aplicar o `continue` do mesmo jeito que o `break`, exceto que o inteiro colocado posteriormente representa qual dos laços encadeados você quer afetar.

> Como assim, Kiko?

Bem, você lembra da sintaxe `break <número>`? Também temos `continue <número>`. Mas na minha explicação do `break`, eu comentei que era a quantidade de laços *a encerrar*, porque é basicamente o que ele faz. Já o continue, não. Apenas um laço recebe o comando `continue`, o número que você informa serve para identificar a profundidade onde o comando tem de afetar.

Vamos para o exemplo? Imagine que temos uma sequência numérica e, a partir dela, queremos extrair os números pares. Tem algumas formas de se fazer isso... A melhor é com `array_filter`, mas não vem ao caso. A ideia aqui é usar uma estrutura onde seja possível aplicar o `continue`, ou seja, `while` / `do-while` / `for` / `foreach`. Escolhi o último, porque é o mais simples de ler. Vamos lá?

```php
<?php

$numeros = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

function ehPar(int $numero): bool
{
    return ($numero % 2) === 0; // resto da divisão por 2 é estritamente igual a 0
}

$pares = []; // lista de pares a popular

foreach ($numeros as $numero) {
    if (! ehPar($numero)) { // se não for par
        continue; // continue para a próxima iteração
    }
    // se for par
    $pares[] = $numero; // coloque na lista de pares
}

var_dump($pares); // array(0, 2, 4, 6, 8)
```

> Ué, Kiko, não era `continue <número>`?

Sim! Mas se você não informar nada, será o equivalente a `continue 1`, assim como no `break`. Nesse caso, como só tinha um loop, era essa minha intenção mesmo.

> Então você pode dar algum exemplo real onde o `continue` afeta algum laço acima, Kiko?

Er... Ok, deixe-me pensar um pouco.

<center> ![Thinking.......](https://media.giphy.com/media/xThuWjALRV2QRodVvy/giphy.gif) </center>

Ok, tive uma ideia. Imagine que, por algum motivo, você tem uma lista de dados completamente bagunçados. É uma estrutura similar a uma **matriz** (array dentro de array), só que as colunas estão desordenadas. Você precisa percorrer todo o array para coletar os dados cujo primeiro valor inteiro é par. Isso vai gerar alguns `continue`, vamos ver? Bom, acho que o ideal é fazer em partes.

### A entrada

```php
$bagunca = [
    ['K', 1.83, 0, 'Kiko'],
    [3, 'Y', 1.73, 'Medalha'],
    ['derBrian', 8, 'V', 1.69],
];
```

### A saída esperada

```php
$resultado = [
    ['K', 1.83, 0, 'Kiko'],
    ['derBrian', 8, 'V', 1.69],
];
```

### Os laços

Bem, Antes de qualquer coisa, nós precisamos percorrer o array, certo? Começamos com um primeiro foreach:

```php
foreach ($bagunca as $item) {
    // a mágica vai acontecer aqui
    // onde $item é um array, por exemplo, ['K', 1.83, 0, 'Kiko']
}
```

Então, precisaremos percorrer o array `$item` para encontrar a primeira "propriedade" que é inteira. Para validar, usaremos a função `is_int()`:

```php
// dentro do foreach de cima
foreach ($item as $valor) {
    if (is_int($valor)) {
        // o que acontece?
    }
    // e se não for?
}
```

Aqui temos duas possibilidades: tratar com `break` ao encontrar (`if positivo`) ou com `continue` ao não encontrar (`if negativo`). Como a aula é sobre `continue`, já sabe o que escolhi:

```php
foreach($item as $valor) {
    if (! is_int($valor)) {
        continue;
    }
    // ok, mas o que acontece quando é int?
}
```

Já temos um exemplo, uhuuu... Mas ainda falta validar se o inteiro é **par**. O que acontece se não for? Bem, aquele `$item` torna-se inválido. Nesse caso, precisamos saltar para o próximo `$item`, que é gerado no loop de fora......... Ok, tá virando bagunça. Vamos juntar o que temos até agora:

```php
foreach ($bagunca as $item) {
    foreach ($item as $valor) {
        if (! is_int($valor)) {
            continue;
        }
        // alguma mágica aqui...
    }
    // e esperamos que, ao chegar aqui, todas as validações passaram e precisamos incluir esse $item em algum lugar
}
```

Para validar se `$valor` é par, usaremos a expressão `($valor % 2) === 0`, que checa se é divisível por 2. Mas como a ideia é validar com `continue`, precisamos negar essa sentença, procurando pelos ímpares. Ou seja, basta trocar o `===` por `!==`:

```php
foreach ($bagunca as $item) {
    foreach ($item as $valor) {
        if (! is_int($valor)) {
            continue;
        }
        if (($valor % 2) !== 0) {
            continue 2; // ou seja, afete o 2° foreach de dentro para fora, que é o foreach($bagunca)
        }
        // e se chegou até aqui, é porque validou tudo! ou seja, vamos encerrar esse loop
        break;
    }
    // TODO
}
```

E agora? Já validamos tudo:

- se não for `int`, continua buscando o inteiro. Nesse cenário, é garantido que ao menos um dos dados em `$item` é inteiro, então não se preocupe com a possibilidade de não vir um;
- se não for par, ignoramos aquele `$item` e passamos para o próximo;
- se for `int` e par, então o `$item` passou nos critérios e deve ser armazenado em... `$resultado`! Variável que ainda não criamos. Vamos criar logo?

```php
<?php
$bagunca = [
    ['K', 1.83, 0, 'Kiko'],
    [3, 'Y', 1.73, 'Medalha'],
    ['derBrian', 8, 'V', 1.69],
];

$resultado = [];
foreach ($bagunca as $item) {
    foreach ($item as $valor) {
        if (! is_int($valor)) {
            continue;
        }
        if (($valor % 2) !== 0) {
            continue 2;
        }
        break;
    }
    $resultado[] = $item;
}

var_dump($resultado); // array(['K', 1.83, 0, 'Kiko'], ['derBrian', 8, 'V', 1.69])
```

> Como seria esse código com `break`, Kiko?

Bem mais simples, mas mais difícil de ler:

```php
<?php
$bagunca = [
    ['K', 1.83, 0, 'Kiko'],
    [3, 'Y', 1.73, 'Medalha'],
    ['derBrian', 8, 'V', 1.69],
];

$resultado = [];
foreach ($bagunca as $item) {
    foreach ($item as $valor) {
        if (is_int($valor) && ($valor % 2) === 0) { // se é inteiro && é par
            $resultado[] = $item; // então adiciona o item
            break; // e fim de papo, encerra esse loop e começa o outro logo rapá
        }
    }
}

var_dump($resultado); // array(['K', 1.83, 0, 'Kiko'], ['derBrian', 8, 'V', 1.69])
```

Nesse cenário, como não tem mais nenhum código depois do `foreach ($item)`, daria para trocar o `break` por um `continue 2`, mas o princípio não é esse. O `break` aplicado ali ainda permite executar algum código depois do `foreach` de dentro encerrar, sabe? O `continue 2` não daria essa oportunidade.

Além disso, apesar de um único `if` ser bonito, isso não é exatamente uma forma interessante de programar. Na visão do produto, você juntou duas regras em uma. Ao precisar dar uma manutenção, você precisará tomar cuidado pra sua alteração não afetar o comportamento de outra regra, sabe?

Quando é só duas regras é fácil ler. Eu já vi código com quase 10 regras em um `if` só. Na real, eu já fiz isso e precisei dar manutenção depois... Não façam isso. Vai por mim.

> Tá bom, Kiko... Mas só por curiosidade, como seria com `array_filter`?

<center> ![Olha só... Gostei](https://media.giphy.com/media/NEvPzZ8bd1V4Y/giphy.gif) </center>

```php
<?php

$bagunca = [
    ['K', 1.83, 0, 'Kiko'],
    [3, 'Y', 1.73, 'Medalha'],
    ['derBrian', 8, 'V', 1.69],
];

$resultado = array_filter($bagunca, function($item) {
    $inteiros = array_filter($item, 'is_int'); // pega somente os valores inteiros
    $primeiroInteiro = array_pop($inteiros);
    return ($primeiroInteiro % 2) === 0; // se for par, entra no array_filter. se não, é ignorado
});

var_dump($resultado); // array(['K', 1.83, 0, 'Kiko'], ['derBrian', 8, 'V', 1.69])
```

Enfim, por hoje é só! Deu para entender as possibilidades de uso de um `continue`? Espero que sim! E se curtiu, comenta e compartilha! No próximo artigo vamos falar sobre o tão mencionado `switch`. Dá pra viver sem, mas é bom conhecer! Vai perder?

**Inté!!**
