PHP do Básico ao Avançado – Aula 6 – Estruturas de repetição e loopings

Tempo de Leitura: 8 Minutos

As estruturas de repetição, permitem que o seu script repita um determinado bloco de código por um número finito de vezes, por exemplo, uma quantidade fixa de vezes, enquanto uma determinada condição permaneça válida, são usadas nas mais diversas condições e são parte fundamental da programação de computadores, sendo das estruturas mais utilizadas em programação e merecem uma atenção especial.

Conforme o tipo de looping (ou laço) desejado, diferentes estruturas podem ser usadas, e cada qual permite uma forma diferente de iteração e finalização. Vamos conhecer as estruturas que o PHP utiliza, e as formas de utilização destas.

WHILE (enquanto)

Laços while são os mais simples tipos de laços do PHP. Possui comportamento semelhante ao C. Ele instrui o PHP a executar as declarações contidas de maneira repetida, enquanto a expressão usada for avaliada como TRUE. O valor da expressão é checado a cada iteração do laço, então, mesmo que seu valor mude durante a a execução das declarações aninhadas, a execução não será interrompida até o final da iteração (Nota Técnica: ITERAÇÃO é como chamamos a cada volta do laço, ou seja, cada vez que o PHP executa as declarações dentro do laço é uma iteração). Entretanto, se a expressão do while for avaliada como FALSE desde o início, as declarações aninhadas não serão executadas nenhuma vez. Sua sintaxe padrão é:

while (expressão) {
  //instruções que serão executadas repetidamente
}

Este tipo de laço é usado quando podemos ou não ter sua execução iniciada, ou seja, este tipo de laço dependendo da avaliação pode nunca ser iniciado, e seu conteúdo nunca executado. Seu principal uso é para repetições onde não seja conhecido o número máximo de execuções vamos a um exemplo clássico:

<?php
$db = new PDO('sqlite:agenda_pessoal.db3');
$contatos = $db->query('SELECT * FROM contatos');
echo '<h1>Contatos</h1>';
while($contato = $contatos->fetch(PDO::FETCH_ASSOC)) {
   echo $contato['id'].'-'.$contato['nome'].' - '.$contato['fone'].'<br>';
}
?>

Neste exemplo acima, primeiro, abrimos uma conexão com o banco de dados, depois, executamos uma consulta que retorna os registros contendo uma lista de contatos, e percorremos essa lista com o laço while, se a lista estiver vazia o laço while nunca é executado. Este é o uso mais básico, pois não sabemos qual a quantidade de registros retornada, e o banco de dados também pode estar vazio.

do … while

O laço do-while é muito similar ao laço while, com a exceção da expressão de avaliação ser verificada ao final de cada iteração em vez de no começo. A maior diferença para o laço while é que a primeira iteração do laço do-while sempre é executada (a expressão de avaliação é executada somente no final da iteração).

Um uso típico, é para repetição de entradas de usuário, veja um exemplo abaixo, este trecho de código foi extraído de um sistema de reservas de chalés, onde na primeira tela é escolhido o número de PAX (passageiros) e em uma segunda etapa, é gerado um formulário para cadastrar os dados desses PAX, veja abaixo:

<form action=salvaPax.php method=POST>
<?php 
// editado somente parte do código
$i=1;
$nPax=int($_POST['nPax']); //recebe da chamada anterior o número de PAX e na segunda tela, abre o espaço para cadastro
do{
   echo 'NOME PAX: <input type="text" name="pax[]" id="pax_'.$i.'">';
   $i++
}while($i<$nPax);
?>
</form>

Neste exemplo, para fazer a cotação, o cliente preenche a quantidade de hospedes, e ao solicitar a reserva, é necessário a informação de alguns dados, como nome, identidade, cpf, sexo entre outros, como é obrigatório que exista ao menos 1 hospede na reserva, o laço garante, que ao menos 1 entrada no formulário seja apresentada.

Outros usos incluem uma repetição de chamada caso uma API esteja indisponível e seja necessário seus dados, onde deverá haver ao menos 1 chamada, e caso a resposta seja um código de erro, então uma nova requisição é enfileirada.

Muitos bugs são decorrência da pessoa não perceber que uma tal condição que se supunha ser verdadeira durante e após um loop na verdade não é (levando ao processo tedioso de depurar o loop passo a passo no debugger) por este motivo, muitas vezes não usamos um loop do…while criando artifícios como flags, para controlar um loop while, onde na verdade deveríamos usar outros tipos de looping.

O problema do do..while é que ele surge em situações em que é obrigatório que o corpo do laço execute ao menos uma vez. Por que é obrigatório? Normalmente porque tem alguma variável que não foi inicializada direito, um valor que pode ou não ser nulo, etc. Porque se nada disso fosse verdade, se o estado do programa fosse perfeitamente válido mesmo se o loop não executasse nenhuma vez, não haveria a necessidade do do..while. Sendo assim, a análise de um código que usa o do..while é mais trabalhosa do que um que não usa. Pois a princípio, na primeira iteração do loop o invariante ainda não é necessariamente verdadeiro, enquanto em todas as seguintes ele precisa ser.

Consequentemente, é necessário escrever um corpo que simultaneamente: 1) leve o programa de um estado em que o invariante é falso para um que o invariante é verdadeiro; 2) com as mesmas instruções, parte de um estado em que o invariante vale para outro que ele continue valendo. Isso é complicado, e acaba exigindo que se pense em cada linha de código duas vezes (na primeira iteração vai acontecer isso, nas outras vai acontecer aquilo), inclusive com a possibilidade de se introduzir ifs para tratar de modo diferenciado da primeira iteração e das demais.

for

O loop for, é usado quando sabemos o exato número de iterações que deve ocorrer, ou quando uma análise retorna um valor fixo, e não se altera ou se altera em passos iguais, são considerados uma das estruturas mais complexas em programação, e a sua sintaxe básica é:

for (expr1; expr2; expr3){
  // instruções que serão executadas
}

A primeira expressão (expr1) é avaliada (executada), uma vez, incondicionalmente, no início do laço. No começo de cada iteração a expr2 é avaliada. Se a avaliada como TRUE, o laço continuará e as instruções aninhada serão executadas. Se avaliada como FALSE, a execução do laço terminará. No final de cada iteração, a expr3 é executada.

Cada uma das expressões podem ser vazias ou conter múltiplas expressões separadas por vírgulas. Na expr2, todas as expressões separadas por vírgula são avaliadas mas o resultado é obtido da última parte. Se a expr2 estiver vazia significa que o laço deve ser executado indefinidamente (isto não é inútil como se imagina, pois muitas vezes deseja-se interromper o laço utilizando a instrução break ao invés de usar a expressão verdade do for) em outras oportunidades daremos exemplos mais práticos desse uso.

Um uso corriqueiro e errado do loop for é percorrer arrays, para esta função, temos uma estrutura mais rápida que é o foreach, do qual falaremos mais tarde, para o laço for tradicional, um uso muito corriqueiro é para gerar senhas, veja um exemplo abaixo:

function GeraSenha( $len = 12){
    $characters = '[email protected]#$%&*()-_=+,.;:/?';
    $randstring = '';
    for ($i = 0; $i < $len; $i++) {
        $randstring .= $characters[rand(0, strlen($characters)-1)];
    }
    return $randstring;
}

echo GeraSenha();
echo '<br>';
echo GeraSenha(6)
?>

Este exemplo é bem simples, e ilustra bem muitos conceitos que estudamos até agora. Explicando, primeiro criamos uma função (o que veremos como fazer na nossa próxima aula), depois definimos uma string que contém uma sequencia de caracteres válidos para gerar nossa senha, essa sequencia poderia incluir outros, ou retirar alguns caso você queira utilizar essa função em seus próprios projetos. Depois entramos em um looping que vai ser executado um número X de vezes, e esse número é definido pela variável $len para poder gerar senhas com comprimentos variados.
Dentro do looping, simplesmente geramos um número aleatório entre 0 e o tamanho da string-1 usamos esse -1 pois o PHP inicia a contagem a partir do 0, e pegamos o caractere que corresponde a posição atual, concatenando-o com a string $randstring até o comprimento definido no nosso $len. E por fim, devolvemos (return) o valor dessa string para o método ou script que chamou nossa função.

Lá no script, ecoamos a saída dessa função, com um comprimento padrão, e depois forçando o comprimento de 6 caracteres.

foreach

O construtor foreach fornece uma maneira fácil de iterar sobre arrays. O foreach funciona somente em arrays e objetos, e emitirá um erro ao tentar usá-lo em uma variável com um tipo de dado diferente ou em uma variável não inicializada. Possui duas sintaxes:

foreach (array_expression as $value){
   //conteúdo do laço
}

foreach (array_expression as $key => $value){
    //conteúdo do laço
}

A primeira forma, itera sobre arrays informados na array_expression e a cada iteração, o valor do elemento atual é atribuído a $value e o ponteiro interno do array avança uma posição (então, na próxima iteração, se estará olhando para o próximo elemento).

A segunda forma var, adicionalmente, atribuir a chave do elemento corrente a variável $key a cada iteração. Usada para percorrer arrays associativos (chave/valor).

É muito mais rápido para iterar em todos os elementos do array, do que o uso da instrução for, quando o foreach inicia sua primeira execução, o ponteiro interno do array é automaticamente redefinido para o primeiro elemento. Isso indica que não é necessário chamar a função reset() antes de um laço foreach, como ocorre com o laço for.

Um exemplo de uso muito comum é para tratar a saída de funções, veja o exemplo usando um array associativo:

<?php
$cor=array(
  'preto'=>'#000000',
  'branco'=>'#FFFFFF',
  'vermelho'=>'#FF0000',
  'verde'=>'#00FF00',
  'azul'=>'#0000FF',
  'rosa'=>'#FF00FF',
  'ciano'=>'#00FFFF',
  'amarelo'=>'#FFFF00',
  'cinza'=>'#999999',
  'laranja'=>'#FF9900'
);
echo "<select name='cor' id='id_cor' class='form-control'>";
foreach($cor as $k=>$v){
    echo "<option value='$v'>$k</option>";
}
echo '</select>';
?>

Note que no exemplo acima, poderiamos tem uma função que retorna as cores, ou mesmo um banco de dados, enfim, o foreach é uma poderosa estrutura para iterar sobre os elemntos de um array, e muito importante para a linguagem PHP, sendo uma das mais utilizadas em diversos tipos de scripts com as mais variadas funções.

Conclusão

Até este momento, falamos sobre as definições, do PHP já tendo abordado a base da linguagem, e a estrutura de um script, bem como as principais definições de variáveis e tipos de dados, e as estruturas usadas no controle do fluxo de execução. Na nossa próxima aula, vamos falar sobre as funções definidas pelo usuário, como elas podem ser criadas, o escopo, além de outras particularidades do uso destas e da criação de bibliotecas reutilizáveis, que são a base para o desenvolvimento de estruturas mais complexas e para a padronização do código.