Files
archived-doc-pt-br/language/types/array.xml
Leonardo Lara Rodrigues 55bc81d567 sync with en rev
2026-01-06 15:08:57 -03:00

1566 lines
40 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 3061900171d4ae84d532571bfd6eda823726dad4 Maintainer: leonardolara Status: ready --><!-- CREDITS: felipe,fabioluciano,rogeriopradoj,geekcom,ae,gabrielsanva,leonardolara -->
<sect1 xml:id="language.types.array">
<title>Arrays</title>
<para>
Para uma lista de todas as funções de array, consulte o capítulo sobre <link linkend="ref.array">funções de array</link> na documentação.
</para>
<para>
Um <type>array</type> no PHP é na verdade um mapa ordenado. Um mapa é um tipo que
relaciona <emphasis>valores</emphasis> a <emphasis>chaves</emphasis>. Este tipo
é otimizado para vários usos diferentes: ele pode ser tratado como um array,
uma lista (vetor), tabela de hashes (que é uma implementação de mapa), dicionário,
coleção, pilha, fila e provavelmente mais. Assim como existe a possibilidade dos valores do <type>array</type>
serem outros <type>array</type>s, árvores e
<type>array</type>s multidimensionais.
</para>
<para>
A explicação dessas estruturas está além do escopo deste manual, mas
pelo menos um exemplo é dado para cada uma delas. Para mais informações, busque a
considerável literatura que existe sobre esse extenso tópico.
</para>
<sect2 xml:id="language.types.array.syntax">
<title>Sintaxe</title>
<sect3 xml:id="language.types.array.syntax.array-func">
<title>Especificando com <function>array</function></title>
<para>
Um <type>array</type> pode ser criado com o construtor de linguagem
<function>array</function>. Ele leva qualquer quantidade de pares separados por vírgula
<literal><replaceable>chave</replaceable> =&gt; <replaceable>valor</replaceable></literal>
como argumentos.
</para>
<synopsis>
array(
<optional><replaceable>chave</replaceable> =&gt; </optional><replaceable>valor</replaceable>,
<optional><replaceable>chave2</replaceable> =&gt; </optional><replaceable>valor2</replaceable>,
<optional><replaceable>chave3</replaceable> =&gt; </optional><replaceable>valor3</replaceable>,
...
)</synopsis>
<!-- Do not fix the whitespace for the synopsis end element. A limitation of PhD prevents proper trimming -->
<para>
A vírgula após o último elemento do array é opcional e pode ser omitida. Isso geralmente é feito
para arrays em uma única linha, por exemplo, <literal>array(1, 2)</literal> é preferível em vez de
<literal>array(1, 2, )</literal>. Para arrays escritos em várias linhas, por outro lado, a vírgula à direita do último elemento é
usada frequentemente, para permitir a adição de forma simples de novos elementos ao final.
</para>
<note>
<para>
Existe uma sintaxe curta que substitui
<literal>array()</literal> por <literal>[]</literal>.
</para>
</note>
<example>
<title>Um array simples</title>
<programlisting role="php">
<![CDATA[
<?php
$array1 = array(
"foo" => "bar",
"bar" => "foo",
);
// Utilizando a sintaxe curta
$array2 = [
"foo" => "bar",
"bar" => "foo",
];
var_dump($array1, $array2);
?>
]]>
</programlisting>
</example>
<para>
A <replaceable>chave</replaceable> pode ser um <type>int</type>
ou uma <type>string</type>. O <replaceable>valor</replaceable> pode ser
de qualquer tipo.
</para>
<para xml:id="language.types.array.key-casts">
Adicionalmente, as seguintes coerções ocorrerão a <replaceable>chave</replaceable>:
<itemizedlist>
<listitem>
<simpara>
<type>string</type>s contendo quaisquer <type>int</type>s válidos, que não sejam precedidos do sinal de <literal>+</literal>, serão convertidos para o tipo
<type>int</type>. Por exemplo, a chave<literal>"8"</literal> será, na verdade,
armazenada como <literal>8</literal>. Entretanto, <literal>"08"</literal> não
será convertido, por não ser um inteiro decimal válido.
</simpara>
</listitem>
<listitem>
<simpara>
<type>float</type>s também são convertidos para <type>int</type>s, isso significa que
a parte fracionária será removida. Por exemplo, a chave <literal>8.7</literal> será na verdade
armazenada como <literal>8</literal>.
</simpara>
</listitem>
<listitem>
<simpara>
<type>bool</type>s são convertidos para <type>int</type>s, igualmente, por exemplo, a chave
&true;, será na verdade armazenada como <literal>1</literal>
e a chave &false; como <literal>0</literal>.
</simpara>
</listitem>
<listitem>
<simpara>
<type>null</type> será convertido para uma string vazia, por exemplo, a chave
<literal>null</literal> na verdade será armazenada como <literal>""</literal>.
</simpara>
</listitem>
<listitem>
<simpara>
<type>array</type>s e <type>object</type>s <emphasis>não podem</emphasis> ser usados como chaves.
Fazer isso resultará em um aviso: <literal>Illegal offset type</literal>.
</simpara>
</listitem>
</itemizedlist>
</para>
<para>
Se vários elementos na declaração do array utilizam a mesma chave, apenas o último
será utilizado, enquanto todos os outros serão sobrescritos.
</para>
<example>
<title>Exemplo de conversão de tipo e sobrescrita</title>
<programlisting role="php">
<![CDATA[
<?php
$array = array(
1 => "a",
"1" => "b",
1.5 => "c",
true => "d",
);
var_dump($array);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
array(1) {
[1]=>
string(1) "d"
}
]]>
</screen>
<para>
Como todas as chaves do exemplo acima foram convertidas para <literal>1</literal>, o valor será sobrescrito
a cada novo elemento e o valor final atribuído <literal>"d"</literal>, será o único que restará.
</para>
</example>
<para>
As chaves dos arrays no PHP podem conter, ao mesmo tempo, <type>int</type> e <type>string</type>,
porque o PHP não faz distinção entre arrays indexados e associativos.
</para>
<example>
<title>Misturando <type>int</type> e <type>string</type> nas chaves</title>
<programlisting role="php">
<![CDATA[
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
var_dump($array);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
array(4) {
["foo"]=>
string(3) "bar"
["bar"]=>
string(3) "foo"
[100]=>
int(-100)
[-100]=>
int(100)
}
]]>
</screen>
</example>
<para>
A <replaceable>key</replaceable> é opcional. Se não for especificada, o PHP
utilizará o incremento da chave do tipo <type>int</type> com maior valor utilizado.
</para>
<example>
<title>Arrays indexados sem chaves</title>
<programlisting role="php">
<![CDATA[
<?php
$array = array("foo", "bar", "hello", "world");
var_dump($array);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
array(4) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
[2]=>
string(5) "hello"
[3]=>
string(5) "world"
}
]]>
</screen>
</example>
<para>
É possível especificar a chave somente para alguns elementos e omití-las para outros:
</para>
<example>
<title>Chaves em alguns elementos</title>
<programlisting role="php">
<![CDATA[
<?php
$array = array(
"a",
"b",
6 => "c",
"d",
);
var_dump($array);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
array(4) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[6]=>
string(1) "c"
[7]=>
string(1) "d"
}
]]>
</screen>
<para>
Como pode ver, o último valor <literal>"d"</literal> foi atribuído à chave
<literal>7</literal>. Isso acontece porque a chave com maior inteiro antes dela
era <literal>6</literal>.
</para>
</example>
<example>
<title>Exemplo de sobrescrita e cast de tipo complexo</title>
<para>
Este exemplo inclui todas as variações de cast de tipo de chaves e sobrescrita
de elementos.
</para>
<programlisting role="php">
<![CDATA[
<?php
$array = array(
1 => 'a',
'1' => 'b', // o valor "a" será sobrescrito por "b"
1.5 => 'c', // o valor "b" será sobrescrito por "c"
-1 => 'd',
'01' => 'e', // não é uma string de inteiro e NÃO sobrescreve a chave 1
'1.5' => 'f', // não é uma string de inteiro e NÃO sobrescreve a chave 1
true => 'g', // o valor "c" será sobrescrito por "g"
false => 'h',
'' => 'i',
null => 'j', // o valor "i" será sobrescrito por "j"
'k', // o valor "k" será alocado na chave 2. Isto porque é o maior inteiro após a chave 1
2 => 'l', // o valor "k" será sobrescrito por "l"
);
var_dump($array);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
array(7) {
[1]=>
string(1) "g"
[-1]=>
string(1) "d"
["01"]=>
string(1) "e"
["1.5"]=>
string(1) "f"
[0]=>
string(1) "h"
[""]=>
string(1) "j"
[2]=>
string(1) "l"
}
]]>
</screen>
</example>
<example>
<title>Exemplo de índice negativo</title>
<simpara>
Ao atribuir uma chave inteira negativa <literal>n</literal>, o PHP irá
atribuir <literal>n+1</literal> à chave seguinte.
</simpara>
<programlisting role="php">
<![CDATA[
<?php
$array = [];
$array[-5] = 1;
$array[] = 2;
var_dump($array);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
array(2) {
[-5]=>
int(1)
[-4]=>
int(2)
}
]]>
</screen>
<warning>
<simpara>
Antes do PHP 8.3.0, atribuir uma chave inteira negativa <literal>n</literal> causaria
a atribuição de <literal>0</literal> à chave seguinte, portando o exemplo anterior
teria este resultado:
</simpara>
<informalexample>
<screen>
<![CDATA[
array(2) {
[-5]=>
int(1)
[0]=>
int(2)
}
]]>
</screen>
</informalexample>
</warning>
</example>
</sect3>
<sect3 xml:id="language.types.array.syntax.accessing">
<title>Acessando elementos do array com colchetes</title>
<para>
Elementos do array podem ser acessados utilizando a sintaxe <literal>array[chave]</literal>.
</para>
<example>
<title>Acessando elementos do array</title>
<programlisting role="php">
<![CDATA[
<?php
$array = array(
"foo" => "bar",
42 => 24,
"multi" => array(
"dimensional" => array(
"array" => "foo"
)
)
);
var_dump($array["foo"]);
var_dump($array[42]);
var_dump($array["multi"]["dimensional"]["array"]);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
string(3) "bar"
int(24)
string(3) "foo"
]]>
</screen>
</example>
<note>
<para>
Anteriormente ao PHP 8.0.0, chaves e colchetes podiam ser utilizados
para acessar elementos de um array (por exemplo, <literal>$array[42]</literal> e <literal>$array{42}</literal> irão
fazer a mesma coisa que o exemplo anterior).
O acesso por chaves foi descontinuado a partir do PHP 7.4.0 e não é mais suportado a partir do PHP 8.0.0.
</para>
</note>
<example>
<title>Referenciando elemento de um array</title>
<programlisting role="php">
<![CDATA[
<?php
function getArray() {
return array(1, 2, 3);
}
$secondElement = getArray()[1];
var_dump($secondElement);
?>
]]>
</programlisting>
</example>
<note>
<para>
Tentativas de acesso a uma chave de array que não foi definida é
o mesmo que acessar qualquer outra variável indefinida:
uma mensagem de erro de nível <constant>E_WARNING</constant>
(<constant>E_NOTICE</constant> anteriormente ao PHP 8.0.0) será
emitida, e o resultado será &null;.
</para>
</note>
<note>
<para>
Acessar um array através de uma chave que não é <type>string</type>
retorna &null;. Anteriormente ao PHP 7.4.0 não era emitida uma mensagem.
A partir do PHP 7.4.0 emite um <constant>E_NOTICE</constant>;
e a partir do PHP 8.0.0 é emitido um <constant>E_WARNING</constant>.
</para>
</note>
</sect3>
<sect3 xml:id="language.types.array.syntax.modifying">
<title>Criando/modificando com a sintaxe de colchetes</title>
<para>
Você pode também modificar um <type>array</type> existente explicitamente assimilando
valores a ele.
</para>
<para>
Isto é feito apenas assimilando valores para o <type>array</type> enquanto especifica a
chave em colchetes. Você pode omitir a chave, colocando um par vazio
de colchetes (<literal>[]</literal>).
</para>
<synopsis>
$arr[<replaceable>chave</replaceable>] = <replaceable>valor</replaceable>;
$arr[] = <replaceable>valor</replaceable>;
// <replaceable>chave</replaceable> pode ser tanto um <type>int</type> quanto uma <type>string</type>
// <replaceable>valor</replaceable> pode ser qualquer valor de qualquer tipo</synopsis>
<para>
Se <varname>$arr</varname> ainda não existir ou estiver definido como &null; ou &false;, ele será criado, por isso também
é uma alternativa para criação de um <type>array</type>. Entretanto, essa prática é
desencorajada por que se <varname>$arr</varname> conter
algum valor (por exemplo, uma <type>string</type> de uma variável de requisição), então este
valor permanecerá e o <literal>[]</literal> funcionará como
um <link linkend="language.types.string.substr">operador de acesso
a string</link>. Sempre será recomendado a inicialização de uma variável por atribuição
direta.
</para>
<note>
<simpara>
A partir do PHP 7.1.0, aplicar um operador de índice vazio a uma string lança um erro fatal.
Antes, a string era silenciosamente convertida em um array.
</simpara>
</note>
<note>
<simpara>
A partir do PHP 8.1.0, criar um novo array a partir do valor &false; foi descontinuado.
Criar um array a partir de &null; e valores indefinidos ainda é permitido.
</simpara>
</note>
<para>
Para mudar um certo valor, apenas atribua um novo valor
a um elemento especificado por sua chave. Se a intenção for
remover um par de chave/valor, é necessário aplicar a função <function>unset</function> na chave.
</para>
<example>
<title>Usando colchetes com arrays</title>
<programlisting role="php">
<![CDATA[
<?php
$arr = array(5 => 1, 12 => 2);
$arr[] = 56; // Isto é o mesmo que $arr[13] = 56;
// nesse ponto do script
$arr["x"] = 42; // Isto acrescenta um novo elemento
// para o array com a chave "x"
unset($arr[5]); // Isto remove um elemento do array
var_dump($arr);
unset($arr); // E isto apaga todo o array
var_dump($arr);
?>
]]>
</programlisting>
</example>
<note>
<para>
Como mencionado acima, se nenhuma chave for especificada, o maior índice <type>int</type> é
obtido, e a nova chave será esse máximo + 1. Se nenhum
índice <type>int</type> existir ainda, a chave será
<literal>0</literal> (zero).
</para>
<para>
Note que a chave inteira de maior valor utilizada <emphasis>não
precisa necessariamente existir no <type>array</type></emphasis>. Ele precisa ter existido
no <type>array</type> em algum momento desde a última
reindexação do <type>array</type>. Veja o exemplo a seguir:
</para><!-- N.T.: reindexação (sem hífen) é preferível -->
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
// Criando um array normal
$array = array(1, 2, 3, 4, 5);
print_r($array);
// Agora apagando todos os itens, mas deixando o array intacto:
foreach ($array as $i => $value) {
unset($array[$i]);
}
print_r($array);
// Acrescentando um item (note que a chave é 5, em vez de zero).
$array[] = 6;
print_r($array);
// Reindexando:
$array = array_values($array);
$array[] = 7;
print_r($array);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
Array
(
)
Array
(
[5] => 6
)
Array
(
[0] => 6
[1] => 7
)
]]>
</screen>
</informalexample>
</note>
</sect3>
<sect3 xml:id="language.types.array.syntax.destructuring">
<title>Desconstruindo arrays</title>
<para>
Arrays podem ser desconstruídos utilizando <literal>[]</literal> (a partir do PHP 7.1.0) ou
<function>list</function>. Esses
constructos podem ser utilizados para desconstruir o array em variáveis distintas.
</para>
<example>
<title>Desconstruindo arrays</title>
<programlisting role="php">
<![CDATA[
<?php
$source_array = ['foo', 'bar', 'baz'];
[$foo, $bar, $baz] = $source_array;
echo $foo, PHP_EOL; // exibe "foo"
echo $bar, PHP_EOL; // exibe "bar"
echo $baz, PHP_EOL; // exibe "baz"
?>
]]>
</programlisting>
</example>
<para>
A desconstrução de arrays pode ser utilizada no &foreach; para desconstruir
um array multidimensional enquanto o percorre.
</para>
<example>
<title>Desconstruindo arrays em Foreach</title>
<programlisting role="php">
<![CDATA[
<?php
$source_array = [
[1, 'John'],
[2, 'Jane'],
];
foreach ($source_array as [$id, $name]) {
echo "{$id}: '{$name}'\n";
}
?>
]]>
</programlisting>
</example>
<para>
Elementos de arrays serão ignorados se a variável não for providenciada. A desconstrução
de arrays sempre inicia no índice <literal>0</literal>.
</para>
<example>
<title>Ignorando Elementos</title>
<programlisting role="php">
<![CDATA[
<?php
$source_array = ['foo', 'bar', 'baz'];
// Atribui o elemento de índice 2 na variável $baz
[, , $baz] = $source_array;
echo $baz; // exibe "baz"
?>
]]>
</programlisting>
</example>
<para>
A partir do PHP 7.1.0, é possível desconstruir arrays associativos. Isto
permite fácil seleção do elemento correto de uma forma indexada numericamente
dado que os índices podem ser especificados.
</para>
<example>
<title>Desconstruindo arrays associativos</title>
<programlisting role="php">
<![CDATA[
<?php
$source_array = ['foo' => 1, 'bar' => 2, 'baz' => 3];
// Atribui o elemento de índice 'baz' na variável $three
['baz' => $three] = $source_array;
echo $three, PHP_EOL; // exibe 3
$source_array = ['foo', 'bar', 'baz'];
// Atribui o elemento de índice 2 na variável $baz
[2 => $baz] = $source_array;
echo $baz, PHP_EOL; // exibe "baz"
?>
]]>
</programlisting>
</example>
<para>
A desconstrução de arrays pode ser utilizada para trocar duas variáveis.
</para>
<example>
<title>Trocando duas variáveis</title>
<programlisting role="php">
<![CDATA[
<?php
$a = 1;
$b = 2;
[$b, $a] = [$a, $b];
echo $a, PHP_EOL; // exibe 2
echo $b, PHP_EOL; // exibe 1
?>
]]>
</programlisting>
</example>
<note>
<para>
O operador de espalhamento (<literal>...</literal>) não é suportado em atribuições.
</para>
</note>
<note>
<para>
Tentar acessar uma chave indefinida têm o mesmo efeito de
acessar uma variável indefinida:
um aviso <constant>E_WARNING</constant>
(<constant>E_NOTICE</constant> anteriormente ao PHP 8.0.0) será
emitido, e o resultado será &null;.
</para>
</note>
<note>
<para>
A desconstrução de um valor escalar atribui &null; a todas as variáveis.
</para>
</note>
</sect3>
</sect2><!-- end syntax -->
<sect2 xml:id="language.types.array.useful-funcs">
<title>Funções úteis</title>
<para>
Há uma série de funções úteis para trabalhar com arrays.
Veja a seção sobre <link linkend="ref.array">funções para arrays</link>.
</para>
<note>
<para>
A função <function>unset</function> permite apagar chaves de um
<type>array</type>. Esteja avisado que o array <emphasis>não</emphasis> será
reindexado. Se um comportamento como "remover e deslocar" é o desejado, o
<type>array</type> poderá ser reindexado utilizando a
função <function>array_values</function>.
</para>
<example>
<title>Eliminando elementos intermediários</title>
<programlisting role="php">
<![CDATA[
<?php
$a = array( 1 => 'um', 2 => 'dois', 3 => 'três' );
/* irá produzir um array que pode ser definido como
$a = array( 1=>'um', 3=>'três');
e NÃO
$a = array( 1 => 'um', 2 => 'três');
*/
unset($a[2]);
var_dump($a);
$b = array_values($a);
// Agora $b é o array(0 => 'um', 1 =>'três')
var_dump($b);
?>
]]>
</programlisting>
</example>
</note>
<para>
A estrutura de controle &foreach;
existe especificamente para lidar com <type>array</type>s. Ele
provê uma maneira fácil de percorrer um <type>array</type>.
</para>
</sect2>
<sect2 xml:id="language.types.array.donts">
<title>Array: o que fazer e o que não fazer</title>
<sect3 xml:id="language.types.array.foo-bar">
<title>Porque <literal>$foo[bar]</literal> está errado?</title>
<para>
Sempre utilize delimitadores em torno dos índices do array. Por exemplo,
<literal>$foo['bar']</literal> está correto, enquanto que
<literal>$foo[bar]</literal>, não está. Mas porque? É comum encontrar
essa sintaxe em scripts antigos:
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$foo[bar] = 'inimigo';
echo $foo[bar];
// etc
?>
]]>
</programlisting>
</informalexample>
<para>
Isto está errado, mas funciona. A razão é que este código possui uma
constante indefinida (<literal>bar</literal>) em vez de uma <type>string</type> (<literal>'bar'</literal> - repare nas
aspas simples). Isto funciona, porque o PHP converte automaticamente uma
<emphasis>string base</emphasis> (uma <type>string</type> não delimitada que
não corresponde a nenhum símbolo conhecido) em uma <type>string</type> que contém
a <type>string</type> base. Por exemplo, se não existir uma constante definida com o
nome <constant>bar</constant>, então o PHP irá substituí-la pela
<type>string</type> <literal>'bar'</literal> e usá-la.
</para>
<warning>
<simpara>
O fallback que trata uma constante indefinida como uma string lança um erro
do nível <constant>E_NOTICE</constant>.
Isso foi descontinuado desde o PHP 7.2.0, e lança um erro
do nível <constant>E_WARNING</constant>.
A partir do PHP 8.0.0, esse fallback foi removido e agora lança uma
exceção <classname>Error</classname>.
</simpara>
</warning>
<simpara>
Isto não significa que deve-se <emphasis>sempre</emphasis> delimitar as chaves. Não
delimite chaves que sejam <link linkend="language.constants">constantes</link> ou
<link linkend="language.variables">variáveis</link>, porque isso impedirá
o PHP de interpretá-las.
</simpara>
<example>
<title>Delimitando chaves</title>
<programlisting role="php">
<![CDATA[
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', false);
// Arrays simples:
$array = array(1, 2);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
echo "\nVerificando $i: \n";
echo "Ruim: " . $array['$i'] . "\n";
echo "Bom: " . $array[$i] . "\n";
echo "Ruim: {$array['$i']}\n";
echo "Bom: {$array[$i]}\n";
}
?>
]]>
</programlisting>
</example>
&example.outputs;
<screen>
<![CDATA[
Verificando 0:
Notice: Undefined index: $i in /path/to/script.html on line 9
Ruim:
Bom: 1
Notice: Undefined index: $i in /path/to/script.html on line 11
Ruim:
Bom: 1
Verificando 1:
Notice: Undefined index: $i in /path/to/script.html on line 9
Ruim:
Bom: 2
Notice: Undefined index: $i in /path/to/script.html on line 11
Ruim:
Bom: 2
]]>
</screen>
<para>
Mais exemplos para demonstrar esse comportamento:
</para>
<example>
<title>Mais exemplos</title>
<programlisting role="php">
<![CDATA[
<?php
// Mostrando todos os erros
error_reporting(E_ALL);
$arr = array('fruta' => 'maçã', 'legume' => 'cenoura');
// Correto
echo $arr['fruta'], PHP_EOL; // maçã
echo $arr['legume'], PHP_EOL; // cenoura
// Errado. Isto não funciona e lança um erro PHP por causa
// de uma constante indefinida de nome 'fruta'
//
// Error: Undefined constant "fruta"
try {
echo $arr[fruta];
} catch (Error $e) {
echo get_class($e), ': ', $e->getMessage(), PHP_EOL;
}
// Esta instrução define uma constante para demonstrar o que acontece. O valor 'legume'
// é atribuído a uma constante denominada 'fruta'
define('fruta', 'legume');
// Observe a diferença agora
echo $arr['fruta'], PHP_EOL; // maçã
echo $arr[fruta], PHP_EOL; // cenoura
// O exemplo seguinte está ok, já que está dentro de uma string. Constantes não são
// observadas dentro de strings e por isso nenhum erro acontece aqui
echo "Olá $arr[fruta]", PHP_EOL; // Olá maçã
// Com uma exceção: chaves envolvendo arrays dentro de strings
// ativam a checagem de constantes, como em
echo "Olá {$arr[fruta]}", PHP_EOL; // Olá cenoura
echo "Olá {$arr['fruta']}", PHP_EOL; // Olá maçã
// Concatenação é uma outra opção
echo "Olá " . $arr['fruta'], PHP_EOL; // Olá maçã
?>
]]>
</programlisting>
</example>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
// E isso não funciona, resultando em um erro de interpretação do tipo:
// Parse error: parse error, expecting T_STRING' or T_VARIABLE' or T_NUM_STRING'
// Isso também se aplica ao uso de superglobais em strings
print "Olá $arr['fruta']";
print "Olá $_GET['foo']";
?>
]]>
</programlisting>
</informalexample>
<para>
Como especificado na seção sobre <link linkend="language.types.array.syntax">sintaxe</link>,
o que estiver entre os colchetes ('<literal>[</literal>' e
'<literal>]</literal>'), precisa ser uma expressão. Isso significa que códigos como
estes funcionam:
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
echo $arr[algumafuncao($bar)];
?>
]]>
</programlisting>
</informalexample>
<para>
Isto é um exemplo de utilização de um valor de retorno de função como um índice de array.
O PHP também aceita constantes:
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$error_descriptions[E_ERROR] = "Um erro fatal ocorreu";
$error_descriptions[E_WARNING] = "O PHP emitiu um alarme";
$error_descriptions[E_NOTICE] = "Apenas um aviso informal";
?>
]]>
</programlisting>
</informalexample>
<para>
Observe que <constant>E_ERROR</constant> também é um identificador válido, assim como
<literal>bar</literal> no primeiro exemplo. Mas no último exemplo seria, na verdade,
o mesmo que escrever:
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$error_descriptions[1] = "Um erro fatal ocorreu";
$error_descriptions[2] = "O PHP emitiu um alarme";
$error_descriptions[8] = "Apenas um aviso informal";
?>
]]>
</programlisting>
</informalexample>
<para>
porque <constant>E_ERROR</constant> é igual a <literal>1</literal>, e assim por diante.
</para>
<sect4 xml:id="language.types.array.foo-bar.why">
<title>Então porque isso é tão ruim?</title>
<para>
Se em algum ponto do futuro, o time do PHP quiser acrescentar outra
constante ou palavra chave, ou você mesmo introduzir outra constante na
sua aplicação, você terá problemas. Por exemplo, já não se pode utilizar as palavras <literal>empty</literal> e
<literal>default</literal> dessa maneira, desde que elas são
<link linkend="reserved">palavras reservadas especiais</link>.
</para>
<note>
<simpara>
Para reforçar, dentro de uma <type>string</type> delimitada por aspas duplas,
é válido não englobar o índice do array com aspas simples, então <literal>"$foo[bar]"</literal>
é válido. Veja os exemplos anteriores para detalhes assim como a seção sobre
<link linkend="language.types.string.parsing">interpretação de variáveis
em strings</link>.
</simpara>
</note>
</sect4>
</sect3>
</sect2>
<sect2 xml:id="language.types.array.casting">
<title>Convertendo para array</title>
<para>
Para qualquer dos tipos: <type>int</type>, <type>float</type>,
<type>string</type>, <type>bool</type> e <type>resource</type>,
converter um valor para um <type>array</type>, resultará em um array com um único
elemento com índice zero e valor escalar convertido. Em
outras palavras, <code>(array) $scalarValue</code> é exatamente o mesmo que
<literal>array($scalarValue)</literal>.
</para>
<para>
Se um <type>object</type> é convertido para um <type>array</type>, o resultado
será um <type>array</type> em que seus elementos serão as propriedades do
<type>object</type>. As chaves serão os nomes das propriedades com pequenas notáveis
exceções: propriedades inteiras serão inacessíveis;
variáveis privadas tem o nome da classe prefixando o nome da
variável; variáveis protegidas tem um '*' prefixando o nome da variável. Esses
valores prefixados têm um byte <literal>NUL</literal> em cada lado.
<link linkend="language.oop5.properties.typed-properties">Propriedades tipadas</link>
não inicializadas são ignoradas.
</para>
<example>
<title>Convertendo para um array</title>
<programlisting role="php">
<![CDATA[
<?php
class A {
private $B;
protected $C;
public $D;
function __construct()
{
$this->{1} = null;
}
}
var_export((array) new A());
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
array (
'' . "\0" . 'A' . "\0" . 'B' => NULL,
'' . "\0" . '*' . "\0" . 'C' => NULL,
'D' => NULL,
1 => NULL,
)
]]>
</screen>
</example>
<para>
Esses <literal>NUL</literal> podem ocasionar comportamentos inesperados:
</para>
<example>
<title>Convertendo um objeto em um Array</title>
<programlisting role="php">
<![CDATA[
<?php
class A {
private $A; // Transformado na chave '\0A\0A'
}
class B extends A {
private $A; // Transformado na chave '\0B\0A'
public $AA; // Transformado na chave 'AA'
}
var_dump((array) new B());
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
array(3) {
["BA"]=>
NULL
["AA"]=>
NULL
["AA"]=>
NULL
}
]]>
</screen>
</example>
<para>
Acima aparecem duas chaves chamadas 'AA', embora uma delas é,
na verdade, nomeada '\0A\0A'.
</para>
<para>
Converter um valor &null; para um <type>array</type> resultará em um
<type>array</type> vazio.
</para>
</sect2>
<sect2 xml:id="language.types.array.comparing">
<title>Comparando</title>
<para>
É possível comparar arrays utilizando a função <function>array_diff</function> e
com a utilização dos
<link linkend="language.operators.array">operadores de array</link>.
</para>
</sect2>
<sect2 xml:id="language.types.array.unpacking">
<title>Expansão de arrays</title>
<para>
Um array prefixado com <code>...</code> será expandido no local desse operador.
Somente arrays e objetos que implementem <interfacename>Traversable</interfacename> podem ser expandidos.
A expansão de arrays com <code>...</code> está disponível desde o PHP 7.4.0. Ele também é chamado de
operador de expansão.
</para>
<para>
É possível realizar a expansão várias vezes, e adicionar elementos antes ou depois do operador<code>...</code>:
<example>
<title>Expansão de arrays</title>
<programlisting role="php">
<![CDATA[
<?php
// Utilizando a sintaxe curta.
// Também funciona com a sintax array().
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; // [1, 2, 3]
$arr3 = [0, ...$arr1]; // [0, 1, 2, 3]
$arr4 = [...$arr1, ...$arr2, 111]; // [1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; // [1, 2, 3, 1, 2, 3]
function getArr() {
return ['a', 'b'];
}
$arr6 = [...getArr(), 'c' => 'd']; // ['a', 'b', 'c' => 'd']
var_dump($arr1, $arr2, $arr3, $arr4, $arr5, $arr6);
?>
]]>
</programlisting>
</example>
</para>
<para>
Expandir um array com <code>...</code> segue a semântica da função <function>array_merge</function>.
Ou seja, chaves strings sobrescrevem valores antigo e chaves inteiros são renumerados:
<example>
<title>Expansão de arrays com chaves duplicadas</title>
<programlisting role="php">
<![CDATA[
<?php
// chave string
$arr1 = ["a" => 1];
$arr2 = ["a" => 2];
$arr3 = ["a" => 0, ...$arr1, ...$arr2];
var_dump($arr3); // ["a" => 2]
// chave inteira
$arr4 = [1, 2, 3];
$arr5 = [4, 5, 6];
$arr6 = [...$arr4, ...$arr5];
var_dump($arr6); // [1, 2, 3, 4, 5, 6]
// Que resulta em [0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5, 5 => 6]
// pois as chaves inteiras anteriores não são preservadas.
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
Chaves que não sejam inteiros ou strings lançam um <classname>TypeError</classname>.
Essas chaves podem ser geradas por um objeto <interfacename>Traversable</interfacename>.
</para>
</note>
<note>
<para>
Anteriormente ao PHP 8.1, expansão de arrays com chave string não era suportado:
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$arr1 = [1, 2, 3];
$arr2 = ['a' => 4];
$arr3 = [...$arr1, ...$arr2];
// Fatal error: Uncaught Error: Cannot unpack array with string keys in example.php:5
$arr4 = [1, 2, 3];
$arr5 = [4, 5];
$arr6 = [...$arr4, ...$arr5]; // works. [1, 2, 3, 4, 5]
?>
]]>
</programlisting>
</informalexample>
</note>
</sect2>
<sect2 xml:id="language.types.array.examples">
<title>Exemplos</title>
<para>
O tipo array do PHP é muito versátil. Temos aqui alguns exemplos:
</para>
<example>
<title>Versatilidade do array</title>
<programlisting role="php">
<![CDATA[
<?php
// Isso:
$a = array( 'color' => 'red',
'taste' => 'sweet',
'shape' => 'round',
'name' => 'apple',
4 // a chave será 0
);
$b = array('a', 'b', 'c');
var_dump($a, $b);
// ...é totalmente equivalente a isso:
$a = array();
$a['color'] = 'red';
$a['taste'] = 'sweet';
$a['shape'] = 'round';
$a['name'] = 'apple';
$a[] = 4; // a chave será 0
$b = array();
$b[] = 'a';
$b[] = 'b';
$b[] = 'c';
// Após a execução do código acima, $ será o array
// array('color' => 'red', 'taste' => 'sweet', 'shape' => 'round',
// 'name' => 'apple', 0 => 4), e $b será o array
// array(0 => 'a', 1 => 'b', 2 => 'c'), ou simplesmente array('a', 'b', 'c').
var_dump($a, $b);
?>
]]>
</programlisting>
</example>
<example>
<title>Utilizando array()</title>
<programlisting role="php">
<![CDATA[
<?php
// Array como (propriedade-)mapa
$map = array( 'versao' => 4,
'OS' => 'Linux',
'lang' => 'inglês',
'short_tags' => true
);
var_dump($map);
// apenas chaves numéricas
// isto é o mesmo que array(0 => 7, 1 => 8, ...)
$array = array( 7,
8,
0,
156,
-10
);
var_dump($array);
$switching = array( 10, // chave = 0
5 => 6,
3 => 7,
'a' => 4,
11, // chave = 6 (o índice máximo era 5)
'8' => 2, // chave = 8 (inteiro!)
'02' => 77, // chave = '02'
0 => 12 // o valor 10 será sobrescrito por 12
);
var_dump($switching);
// array vazio
$empty = array();
var_dump($empty);
?>
]]>
<!-- TODO example of
- overwriting keys
- using vars/functions as key/values
- warning about references
-->
</programlisting>
</example>
<example xml:id="language.types.array.examples.loop">
<title>Coleção</title>
<programlisting role="php">
<![CDATA[
<?php
$cores = array('vermelho', 'azul', 'verde', 'amarelo');
foreach ($cores as $cor) {
echo "Você gosta de $cor?\n";
}
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Você gosta de vermelho?
Você gosta de azul?
Você gosta de verde?
Você gosta de amarelo?
]]>
</screen>
</example>
<para>
É possível alterar diretamente os valores de um <type>array</type>
passando-os como referência.
</para>
<example xml:id="language.types.array.examples.changeloop">
<title>Alterando valores em um laço</title>
<programlisting role="php">
<![CDATA[
<?php
$cores = array('vermelho', 'azul', 'verde', 'amarelo');
foreach ($cores as &$cor) {
$cor = mb_strtoupper($cor);
}
unset($cor); /* garante que as próximas alterações em
$cor não modificam o último elemento do array */
print_r($cores);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Array
(
[0] => VERMELHO
[1] => AZUL
[2] => VERDE
[3] => AMARELO
)
]]>
</screen>
</example>
<para>
Este exemplo cria um array na base 1.
</para>
<example>
<title>Array baseado em 1</title>
<programlisting role="php">
<![CDATA[
<?php
$primeiroquarto = array(1 => 'Janeiro', 'Fevereiro', 'Março');
print_r($primeiroquarto);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Array
(
[1] => Janeiro
[2] => Fevereiro
[3] => Março
)
]]>
</screen>
</example>
<example>
<title>Preenchendo um array</title>
<programlisting role="php">
<![CDATA[
<?php
// preenchendo um array com todos os itens de um diretório
$handle = opendir('.');
while (false !== ($file = readdir($handle))) {
$files[] = $file;
}
closedir($handle);
var_dump($files);
?>
]]>
</programlisting>
</example>
<para>
<type>array</type>s são ordenados. A ordem pode ser modificada utilizando várias
funções de ordenação. Veja a seção de <link linkend="ref.array">funções de arrays</link>
para mais informações. A função <function>count</function>
pode ser utilizada para contar o número de itens em um <type>array</type>.
</para>
<example>
<title>Ordenando arrays</title>
<programlisting role="php" annotations="non-interactive">
<![CDATA[
<?php
sort($files);
print_r($files);
?>
]]>
</programlisting>
</example>
<para>
Como o valor de um <type>array</type> pode ser qualquer coisa, isso significa que também poderá ser
outro <type>array</type>. Isso habilita a criação de <type>array</type>s
recursivos e multidimensionais.
</para>
<example>
<title>Arrays recursivos e multidimensionais</title>
<programlisting role="php">
<![CDATA[
<?php
$fruits = array ( "frutas" => array ( "a" => "laranja",
"b" => "banana",
"c" => "maçã"
),
"numeros" => array ( 1,
2,
3,
4,
5,
6
),
"buracos" => array ( "primeiro",
5 => "segundo",
"terceiro",
)
);
var_dump($fruits);
// Alguns exemplos de endereços dos valores do array acima
echo $fruits["buracos"][5]; // imprime "segundo"
echo $fruits["frutas"]["a"]; // imprime "laranja"
unset($fruits["buracos"][0]); // remove "primeiro"
// Criando um novo array multidimensional
$sucos["maca"]["verde"] = "bom";
var_dump($juices);
?>
]]>
</programlisting>
</example>
<para>
Atribuições de <type>array</type> sempre envolvem cópias de valores. Use o
<link linkend="language.operators">operador de referência</link> para copiar um
<type>array</type> por referência.
</para>
<example>
<title>Copiando arrays</title>
<programlisting role="php">
<![CDATA[
<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 é modificado,
// $arr1 continua sendo apenas array(2, 3)
$arr3 = &$arr1;
$arr3[] = 4; // agora $arr1 e $arr3 são os mesmos
var_dump($arr1, $arr2, $arr3);
?>
]]>
</programlisting>
</example>
</sect2>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->