PHP Arrays Indexados

Até agora, cada variável guardou um valor: um nome, uma idade, um preço. Mas a vida é cheia de listas: a lista de compras, as notas de uma turma, os produtos de uma loja. Um array é uma variável que guarda vários valores, um atrás do outro, cada um numa posição numerada. Esta aula mostra o tipo mais simples, o array indexado, em que as posições são números: 0, 1, 2…

Você vai aprender
  • O que é um array e por que ele existe.
  • Como criar um array com [ ] e com array() (e que os dois são a mesma coisa).
  • Por que a primeira posição é 0, e não 1.
  • Como ler, mudar e adicionar itens, e contar quantos são com count.
  • O que acontece quando você pede uma posição que não existe (Warning: Undefined array key).
  • Como ver o array inteiro com print_r e var_dump.

Os exemplos rodam na máquina fictícia da Ana (usuária ana, computador notebook), com os arquivos na pasta ~/site. As saídas mostradas são as do PHP 8.5 de verdade.


O problema: uma variável para cada coisa

A Ana quer guardar a lista de compras da semana. Com o que você já sabe, ela faria assim:

<?php
$item1 = "arroz";
$item2 = "feijão";
$item3 = "café";
echo $item1, "\n", $item2, "\n", $item3, "\n";

Funciona, mas pense no que vem depois: se a lista tiver 30 itens, são 30 variáveis. Para mostrar todos, 30 echos. Para saber quantos itens há, você teria de contar no olho. E se ela lembrar de mais um item, precisa inventar $item31 e mudar o resto do programa.

O array resolve isso: uma variável só, com todos os itens dentro.

A ideia: um armário com gavetas numeradas

Imagine um armário com gavetas. Cada gaveta tem um número na frente e guarda uma coisa. O armário inteiro tem um nome ($compras); para pegar algo, você diz o nome do armário e o número da gaveta.

Gaveta (índice)012
Conteúdo (valor)"arroz""feijão""café"

Dois nomes que você vai ver o tempo todo:

  • Índice (ou chave, em inglês key): o número da gaveta.
  • Valor (value): o que está guardado nela.

Cada par "índice + valor" é um elemento (ou item) do array.


Criar um array

<?php
$compras = ["arroz", "feijão", "café"];
echo $compras[0], "\n";
echo $compras[1], "\n";
echo $compras[2], "\n";
$compras
O nome da variável, como qualquer outra. É costume usar um nome no plural, porque ela guarda várias coisas.
=
Atribuição: "guarde à esquerda o que está à direita".
[ ]
Os colchetes criam o array. Tudo o que estiver entre eles vira item.
"arroz", "feijão", "café"
Os valores, separados por vírgula. O PHP numera sozinho: o primeiro ganha o índice 0, o segundo o 1, o terceiro o 2.
$compras[0]
Lê o valor da gaveta 0: o nome do array, colchetes e o índice dentro.
$ php compras.php
arroz
feijão
café

Repare que os colchetes aparecem em dois papéis: criando o array (["arroz", …]) e acessando uma posição ($compras[0]). Quando vêm logo depois do nome de uma variável, é acesso.

Um item por linha (e a vírgula no final)

Quando a lista é grande, escreva um item por linha. O PHP aceita uma vírgula depois do último item, e isso é até recomendado: para acrescentar um item no fim, você só escreve uma linha nova, sem mexer na anterior.

<?php
$compras = [
    "arroz",
    "feijão",
    "café",     // esta vírgula final é permitida
];
echo count($compras), "\n";
$ php virgula.php
3

[ ] ou array()?

Existe uma segunda forma de criar arrays, mais antiga: a palavra array com parênteses. As duas criam exatamente o mesmo array. Veja a prova, com o var_dump (que mostra tudo por dentro) e a comparação === ("idêntico", da aula Comparação):

<?php
$a = ["arroz", "feijão", "café"];
$b = array("arroz", "feijão", "café");
var_dump($a);
var_dump($b);
var_dump($a === $b);
$ php iguais.php
array(3) {
  [0]=>
  string(5) "arroz"
  [1]=>
  string(7) "feijão"
  [2]=>
  string(5) "café"
}
array(3) {
  [0]=>
  string(5) "arroz"
  [1]=>
  string(7) "feijão"
  [2]=>
  string(5) "café"
}
bool(true)              « os dois arrays são idênticos
FormaDesdeQuando você vai ver
["arroz", "café"]PHP 5.4 (2012)Código moderno. Use esta.
array("arroz", "café")Sempre existiuCódigo antigo, tutoriais velhos, WordPress. Leia sem susto: é a mesma coisa.
Por que "feijão" tem string(7), se são 6 letras?

O var_dump conta bytes, não letras. Letras acentuadas como ã e é ocupam 2 bytes cada em UTF-8. Por isso "café" aparece como string(5). Isso é explicado na aula Acentos e mbstring.


Os índices começam no 0

Esta é a parte que mais confunde no começo: a primeira posição é a 0. Pense no índice como "quantos passos eu ando a partir do começo". Para pegar o primeiro item você anda zero passos; para o segundo, um passo.

Você diz…ÍndiceCódigo
o 1º item0$compras[0]
o 2º item1$compras[1]
o 3º item2$compras[2]
o último item (de 3)3 − 1 = 2$compras[count($compras) - 1]

Regra prática: num array de N itens, os índices vão de 0 até N − 1. Um array de 3 itens não tem o índice 3.

Quase todas as linguagens de programação contam assim (C, Java, JavaScript, Python…). Vale se acostumar logo.


Mudar, contar e adicionar

<?php
$compras = ["arroz", "feijão", "café"];
$compras[1] = "feijão preto";
echo "Quantos itens: ", count($compras), "\n";
$compras[] = "leite";
$compras[] = "pão";
echo "Quantos itens: ", count($compras), "\n";
print_r($compras);
echo "Último: ", $compras[count($compras) - 1], "\n";
LinhaO que faz
$compras[1] = "feijão preto";Troca o valor da gaveta 1. O valor antigo ("feijão") é jogado fora.
count($compras)Conta os itens (count = contar). Devolve um número inteiro.
$compras[] = "leite";Acrescenta no fim. Colchetes vazios querem dizer "a próxima gaveta livre". O PHP escolhe o índice sozinho: aqui, o 3.
print_r($compras);Mostra o array inteiro, com índices e valores.
$compras[count($compras) - 1]O último item: 5 itens, último índice 4.
$ php mudar.php
Quantos itens: 3
Quantos itens: 5
Array
(
    [0] => arroz
    [1] => feijão preto
    [2] => café
    [3] => leite
    [4] => pão
)
Último: pão

O [] vazio é a forma mais usada de "colocar mais um na lista". Ele funciona até se a variável ainda não existir: o PHP cria um array novo na hora.

<?php
$lista[] = "ovo";       // $lista não existia: vira ["ovo"]
print_r($lista);
$ php do-zero.php
Array
(
    [0] => ovo
)

Mesmo assim, é mais claro começar com um array vazio, $lista = [];, e depois ir acrescentando. Quem lê o código entende na hora que $lista é uma lista.

Mude à vontade: troque itens, acrescente outros com $compras[] = …; e veja como o print_r e o count respondem.

<?php
$compras = ["arroz", "feijão", "café"];

$compras[] = "leite";
$compras[0] = "arroz integral";

echo "A lista tem ", count($compras), " itens\n";
echo "O primeiro é: ", $compras[0], "\n";
print_r($compras);

Um array pode guardar qualquer tipo

Os itens não precisam ser todos textos. Um array pode ter números, booleanos, null, até outros arrays (veja Arrays Multidimensionais). Na prática, porém, uma lista costuma ter itens do mesmo tipo: só nomes, só preços.

<?php
$coisas = ["café", 3, 4.5, true, null];
print_r($coisas);
var_dump($coisas);

Este exemplo serve também para comparar as duas formas de "olhar dentro" de um array.


Imprimir um array: print_r e var_dump

A primeira coisa que todo mundo tenta é o echo. Não dá certo:

<?php
$compras = ["arroz", "feijão", "café"];
echo $compras;
echo "\n";
echo "Lista: $compras\n";
$ php echoarray.php

Warning: Array to string conversion in /home/ana/site/echoarray.php on line 3
Array

Warning: Array to string conversion in /home/ana/site/echoarray.php on line 5
Lista: Array

O echo só sabe escrever texto. Quando recebe um array, o PHP avisa Array to string conversion ("conversão de array para string") e escreve a palavra Array no lugar, o que não ajuda ninguém. Para ver o conteúdo, use uma destas funções:

$ php imprimir.php
Array
(
    [0] => café
    [1] => 3
    [2] => 4.5
    [3] => 1                « o true aparece como 1
    [4] =>                  « o null aparece vazio
)
array(5) {
  [0]=>
  string(5) "café"
  [1]=>
  int(3)
  [2]=>
  float(4.5)
  [3]=>
  bool(true)
  [4]=>
  NULL
}
FunçãoMostraUse para
print_r($a)Índices e valores, de forma enxuta. Não mostra os tipos: true vira 1, null e false somem.Dar uma olhada rápida no conteúdo.
var_dump($a)Tudo: quantos itens (array(5)), o tipo e o tamanho de cada valor.Investigar um problema, ver se algo é "3" (texto) ou 3 (número).

As duas foram apresentadas na aula var_dump e print_r. Lá você também vê o truque de envolver a saída com <pre> quando o PHP gera uma página web, para o navegador respeitar as quebras de linha.

Mostrar a lista bonita para o usuário

print_r e var_dump são ferramentas do programador. Para mostrar a lista a quem usa o site, percorra o array com um foreach, ou junte os itens num texto com implode ("juntar", com um separador):

<?php
$compras = ["arroz", "feijão", "café"];
foreach ($compras as $item) {
    echo "- $item\n";
}
for ($i = 0; $i < count($compras); $i++) {
    echo "$i: {$compras[$i]}\n";
}
echo "Primeiro item: $compras[0]\n";
echo implode(", ", $compras), "\n";
$ php percorrer.php
- arroz
- feijão
- café
0: arroz
1: feijão
2: café
Primeiro item: arroz
arroz, feijão, café
  • O foreach passa por cada item, do primeiro ao último, sem você se preocupar com índices. É a forma mais usada (aula foreach).
  • O for com $i de 0 até count - 1 também funciona, quando você precisa do número da posição (aula for).
  • Dentro de aspas duplas, $compras[0] funciona direto; com uma expressão no índice, como $i, prefira as chaves: {$compras[$i]} (aula Interpolação).

Pedir um índice que não existe

O array da Ana tem 3 itens (índices 0, 1 e 2). O que acontece se o programa pedir o índice 5?

<?php
$compras = ["arroz", "feijão", "café"];
echo "Item: ", $compras[5], "\n";
echo "Fim do programa\n";
$ php inexistente.php
Item:
Warning: Undefined array key 5 in /home/ana/site/inexistente.php on line 3

Fim do programa

Leia a mensagem por partes (o jeito de ler qualquer erro está na aula Lendo Erros do PHP):

Warning
"Aviso". Não é um erro fatal: o programa continua (repare no "Fim do programa").
Undefined array key 5
"Chave de array indefinida: 5". Não existe gaveta número 5.
in /home/ana/site/inexistente.php on line 3
Em que arquivo e em que linha aconteceu.

No lugar do valor que não existe, o PHP usa null (nada), e o echo de null não escreve nada. O "Item: " saiu antes do aviso porque o echo com vírgulas escreve cada parte na ordem: escreveu "Item: ", foi buscar $compras[5], avisou, e seguiu.

Índices negativos não contam de trás para frente

Em algumas linguagens, [-1] é "o último". No PHP, não: -1 é só mais um índice, que aqui não existe.

<?php
$compras = ["arroz", "feijão", "café"];
echo $compras[-1], "\n";
var_dump($compras[5]);
echo $compras[5] ?? "não tem", "\n";
$ php negativo.php

Warning: Undefined array key -1 in /home/ana/site/negativo.php on line 3


Warning: Undefined array key 5 in /home/ana/site/negativo.php on line 4
NULL                    « o valor de uma posição que não existe é null
não tem                 « com ??, nenhum aviso

A última linha mostra a forma certa de ler uma posição que talvez não exista: o operador ?? (aula ?? e ?->). $compras[5] ?? "não tem" quer dizer "o item 5, ou, se ele não existir, "não tem"", sem aviso nenhum. Para pegar o último item, use count($compras) - 1 como índice, ou a função array_last do PHP 8.5 (veja Funções de Array).

Por que as linhas em branco antes do Warning?

No terminal, o PHP escreve uma linha vazia antes de cada aviso, para ele não grudar no texto que veio antes. Num navegador, o mesmo aviso aparece como Warning: … em negrito, no meio da página. Em sites de verdade os avisos ficam escondidos do público e vão para um arquivo de log (aula Tipos de Erro).


Tirar um item com unset (e o buraco que fica)

Para apagar um item, use unset ("desdefinir"). Mas atenção: os outros itens não mudam de índice. Fica um buraco.

<?php
$compras = ["arroz", "feijão", "café", "leite"];
unset($compras[1]);
print_r($compras);
echo count($compras), "\n";
$compras[] = "pão";
print_r($compras);
$compras = array_values($compras);
print_r($compras);
$ php unset.php
Array
(
    [0] => arroz
    [2] => café             « o índice 1 sumiu; o café continua no 2
    [3] => leite
)
3
Array
(
    [0] => arroz
    [2] => café
    [3] => leite
    [4] => pão              « o [] usa o maior índice + 1, e não preenche o buraco
)
Array
(
    [0] => arroz            « array_values renumerou: 0, 1, 2, 3
    [1] => café
    [2] => leite
    [3] => pão
)

Depois de um unset, um laço for de 0 até count - 1 vai tropeçar no buraco (pediria o índice 1, que não existe). O foreach não tem esse problema. Se precisar dos índices em sequência de novo, use array_values, que devolve uma cópia renumerada. Outras formas de tirar itens (do começo, do fim, do meio) estão em Funções de Array.

O mesmo acontece se você escrever num índice "lá na frente": o PHP não preenche o caminho.

<?php
$numeros = [10, 20, 30];
$numeros[10] = 99;
$numeros[] = 100;
print_r($numeros);
echo count($numeros), "\n";
$ php buraco.php
Array
(
    [0] => 10
    [1] => 20
    [2] => 30
    [10] => 99
    [11] => 100
)
5                       « 5 itens, e não 12: as gavetas 3 a 9 não existem

Isso mostra uma verdade importante sobre o PHP: os índices são etiquetas, não posições fixas. Na próxima aula, Arrays Associativos, as etiquetas deixam de ser números e passam a ser nomes, como "nome" e "idade".


Quando dá errado

Warning: Undefined array key 3
$ php mostra.php

Warning: Undefined array key 3 in /home/ana/site/mostra.php on line 3

O que aconteceu: o código pediu um índice que não existe. As causas mais comuns: esquecer que o primeiro índice é 0 (um array de 3 itens vai até o 2); usar count($a) como índice do último em vez de count($a) - 1; um for com <= no lugar de <; ou um buraco deixado por unset.

Como resolver: faça um print_r do array para ver os índices que existem de verdade. Se a posição pode mesmo faltar, use $a[3] ?? "padrão".

Warning: Array to string conversion e aparece Array na tela
$ php echoarray.php

Warning: Array to string conversion in /home/ana/site/echoarray.php on line 3
Array

O que aconteceu: você mandou o echo (ou uma string entre aspas) escrever o array inteiro. O echo só escreve textos e números.

Como resolver: para depurar, print_r ou var_dump. Para o usuário, foreach ou implode(", ", $a). Se a ideia era escrever um item, faltou o índice: echo $compras[0];.

Fatal error: Cannot use [] for reading
<?php
$compras = ["arroz", "feijão"];
echo $compras[];
$ php leitura.php

Fatal error: Cannot use [] for reading in /home/ana/site/leitura.php on line 3
Stack trace:
#0 {main}

O que aconteceu: os colchetes vazios significam "a próxima posição livre". Isso só faz sentido para guardar ($compras[] = "x";), nunca para ler: não há nada lá ainda. É um erro fatal: o PHP nem começa a rodar o arquivo. As linhas Stack trace são o "caminho" até o erro, que o PHP 8.5 passou a mostrar também nos erros fatais.

Como resolver: coloque o índice que você quer ler ($compras[0]) ou, se a intenção era acrescentar, use =: $compras[] = "leite";.

Undefined variable seguido de Trying to access array offset on null
<?php
$compras = ["arroz", "feijão"];
echo $compra[0];
$ php semvar.php

Warning: Undefined variable $compra in /home/ana/site/semvar.php on line 3

Warning: Trying to access array offset on null in /home/ana/site/semvar.php on line 3

O que aconteceu: um erro de digitação: $compra (singular) no lugar de $compras. O primeiro aviso diz que a variável não existe; como uma variável que não existe vale null, o segundo diz "tentando acessar uma posição (offset) de array em null".

Como resolver: confira o nome da variável letra por letra. Quando vierem dois avisos na mesma linha, resolva sempre o primeiro: o segundo costuma ser consequência dele.


Referência rápida

Você quer…CódigoResultado
Criar um array$a = ["x", "y", "z"];Índices 0, 1, 2
Criar (forma antiga)$a = array("x", "y", "z");O mesmo array
Criar vazio$a = [];count($a) é 0
Ler um item$a[0]"x"
Ler, com valor padrão$a[9] ?? "nada""nada", sem aviso
Trocar um item$a[1] = "Y";["x", "Y", "z"]
Acrescentar no fim$a[] = "w";Índice = maior índice + 1
Contarcount($a)Número de itens
Último item$a[count($a) - 1]Se os índices estiverem em sequência
Apagar um itemunset($a[1]);Fica um buraco no índice 1
Renumerar$a = array_values($a);Índices 0, 1, 2… de novo
Ver o conteúdoprint_r($a); / var_dump($a);Para o programador
Juntar num textoimplode(", ", $a)"x, y, z"

Missão final

Missão: o programa abaixo tem dois problemas. Ele mostra Array em vez da quantidade de itens, e pede o último item com um índice que não existe (veja o aviso). Corrija para a saída ser Itens: 4 e Último: leite, sem nenhum aviso. Use count nas duas linhas, para o programa continuar certo se a lista crescer.

<?php
$compras = ["arroz", "feijão", "café"];
$compras[] = "leite";

echo "Itens: " . $compras . "\n";
echo "Último: " . $compras[4] . "\n";
<?php
$compras = ["arroz", "feijão", "café"];
$compras[] = "leite";

echo "Itens: " . count($compras) . "\n";
echo "Último: " . $compras[count($compras) - 1] . "\n";

Exercícios

1. O primeiro item

Complete para mostrar arroz, o primeiro item da lista:

$compras = ["arroz", "feijão", "café"];
echo $compras[];

2. Mais um na lista

Complete para acrescentar "pão" no fim do array, sem escrever o índice:

$compras = "pão";

3. Quantos são?

Complete com a função que conta os itens de um array:

echo ($compras);

4. Em $cores = ["azul", "verde", "rosa", "preto"];, qual é o valor de $cores[2]?

5. O que acontece em echo $cores[4]; com o array da pergunta anterior?

6. Qual função mostra o tipo de cada item (por exemplo, se é int(3) ou string(1) "3")?

7. Depois de $a = ["x", "y", "z"]; unset($a[0]); $a[] = "w";, quais são os índices de $a?


Resumo

  • Um array guarda vários valores numa variável só. No array indexado, cada valor tem um número: o índice.
  • Crie com ["a", "b"] (moderno) ou array("a", "b") (antigo): são iguais.
  • Os índices começam no 0; num array de N itens, o último é o N − 1. Índice negativo não conta de trás para frente.
  • $a[i] lê, $a[i] = … troca, $a[] = … acrescenta no fim, count($a) conta.
  • Índice que não existe: Warning: Undefined array key e o valor vira null. Use ?? quando a posição puder faltar.
  • echo não mostra arrays (sai Array e um aviso). Use print_r/var_dump para depurar e foreach/implode para o usuário.
  • unset deixa buracos; array_values renumera.