Outra melhoria introduzida no PHP 5.5 foi o suporte ao comando list dentro de estruturas foreach. Neste artigo veremos como utilizar este novo suporte, mas antes, veremos rapidamente o que é o list e onde usá-lo.
Sobre o list
List é um elemento nativo da linguagem PHP e permite realizar atribuições de valores de um array para um conjunto de variáveis de forma simplificada. Mas, atenção: list não é uma função.
O funcionamento do list é o seguinte: é montada uma atribuição (utilizando o operador de atribuição, que é representado pelo símbolo "=") sendo que, na esquerda, fica uma lista de variáveis e, na direita, o array de onde serão obtidos os valores para seram atribuidos às variáveis. Os valores são pegos do array a partir da posição 0 (zero) e seguindo os valores inteiros positivos de forma incremental. Veja um exemplo:
$array = array(4, 7, 'a' => 8, 3, 9, 2); list($a, $b, $c) = $array;
No exemplo acima, as variáveis $a, $b e $c receberam os valores 4, 7 e 3, respectivamente. Note que a posição "a" foi ignorada, pois não é uma posição numérica. Além disso, as posições 4 e 5 foram ignoradas, pois a lista continha apenas 3 variáveis.
O código acima é "convertido" da seguinte forma:
$array = array(4, 7, 'a' => 8, 3, 9, 2); $c = $array[2]; $b = $array[1]; $a = $array[0];
Portanto, o elemento list é útil quando temos um array que já conhecemos a sua estrutura e queremos manipulá-las de forma mais legível, atribuindo seus valores a variáveis com nomes sugestivos. Note, ainda, que os valores são atribuídos às variáveis da direita para a esquerda, logo, é preciso cuidado se utilizar, por exemplo $x[] dentro de um list.
Observação: caso quisessemos pegar apenas a posição 0 e 2, poderiamos omitir a variável $b do exemplo:
$array = array(4, 7, 'a' => 8, 3, 9, 2); list($a, , $c) = $array;
Embora a sintaxe fique um pouco "deselegante", é a forma correta de se ignorar uma posição do array. Nem pense em colocar "null" naquela posição, pois o elemento list aceita apenas variáveis ou atributos acessíveis de objetos. Uma forma de deixar o código mais elegante, seria colocar um comentário de bloco na posição vazia, com o conteúdo /* ignora */ ou /* void */.
Utilização prática do list
Uma das utilizações práticas do list é para coletar múltiplos retornos de uma única função. Quando uma função precisa retornar mais de um valor, podemos fazer de duas formas: (i) retornando apenas o valor principal pela função e retornando os demais valores através de parâmetros passados por referência, ou (ii) retornando um array de tamanho fixo, em que cada posição do array representa um resultado.
Na segunda abordagem, a função pode optar por indexar o array com nomes (strings) ou simplesmente indexar o array numericamente. Caso o array seja indexado numericamente, podemos coletar os vários retornos da função através de um list. Veja o exemplo:
/** * Funcao que divide um numero por outro e retorna o quociente e o resto * @param int $dividendo * @param int $divisor * @return array */ function dividir($dividendo, $divisor) { $quociente = floor($dividendo / $divisor); $resto = $dividendo % $divisor; return array($quociente, $resto); } list($quociente, $resto) = dividir(5, 2);
No exemplo, o $quociente recebeu o valor 2, enquanto o $resto recebeu o valor 1.
Embora em boa parte dos casos seja melhor indexar o array com alguma string, em alguns casos pode ser melhor manter a indexação numérica, que é mais rápida e requer menos memória.
Outra utilização comum é a utilização do list em loops que percorrem registros. Por exemplo, ao realizar uma consulta a um banco de dados, podemos percorrer os registros retornados da seguinte forma:
... $stmt = $pdo->query('SELECT id, tipo, cor, tamanho FROM roupas'); while (list($id, $tipo, $cor, $tamanho) = $stmt->fetch(PDO::FETCH_NUM)) { ... }
Suporte do list em estruturas foreach
No PHP 5.5, foi introduzido o suporte do list em estruturas foreach. Isso significa que, ao percorrer os elementos em um foreach, podemos automaticamente atribuí-los a variáveis pré-definidas. A sintaxe é a seguinte:
... $stmt = $pdo->query('SELECT id, tipo, cor, tamanho FROM roupas'); foreach ($stmt->fetch(PDO::FETCH_NUM) as list($id, $tipo, $cor, $tamanho)) { ... }
Opcionalmente, é possível obter o índice do elemento percorrido no foreach:
... $stmt = $pdo->query('SELECT id, tipo, cor, tamanho FROM roupas'); foreach ($stmt->fetch(PDO::FETCH_NUM) as $i => list($id, $tipo, $cor, $tamanho)) { ... }
Os benefícios desta melhoria são: (i) eliminação da necessidade de uma variável para guardar o array obtido na iteração, poupando memória, (ii) redução do tamanho do código-fonte necessário para realizar a operação, e (iii) potencial ganho de legibilidade do código-fonte.
Em termos de funcionalidade, a diferença do foreach para um while é que o foreach reinicia o iterador automaticamente antes de iniciar a iteração (veja método Iterator::rewind).
5 comentários
ótimo artigo parabens pelo post!
Opa, obrigado, Anônimo.
Também adorei esse post! muito útil e muito bem explicado, como, aliás, é de seu feitio :)
bjs
acris
Muito bem explicado, mas não enxerguei as vantagens apontadas na recuperação de registros de Banco de Dados. Ninguém usa, a não ser em casos muito específicos, $stmt->fetch(PDO::FETCH_NUM). Em 99% das vezes, usamos PDO::FETCH_ASSOC ou PDO::FETCH_OBJECT, muito mais prático e legível. Redução do código-fonte? foreach ($stmt as $row){}, ou while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){} teriam o mesmo efeito. Redução de memória? O que pesa mais, um array com cinco posições ou cinco variáveis? Não estou desconstruindo o seu artigo, apenas fazendo algumas considerações. No mais, muito didático e bem escrito, parabéns!!!
Olá, Anônimo.
Concordo plenamente com as suas considerações. Eu também não uso, nunca usei e não pretendo usar FETCH_NUM. O exemplo foi apenas para mostrar o funcionamento e para os programadores saberem avaliar quando ele pode ou não ser útil e quando o ganho será significativo ou não.
Particularmente, acho este recurso bastante inútil, e creio que nunca utilizarei. Mas também acho que é bom saber que ele existe para que, se alguém usar em algum código, ao menos eu saiba o que ocorre.
Postar um comentário
Nota: fique a vontade para expressar o que achou deste artigo ou do blog.
Dica: para acompanhar as respostas, acesse com uma conta do Google e marque a opção "Notifique-me".
Atenção: o blogger não permite inclusão de tags nos comentários, por isso, use algum site externo para postar seu código com dúvidas e deixe o link aqui. Exemplo: pastebin.com