Files
archived-doc-pt-br/language/types/array.xml
2024-09-11 19:42:18 -03:00

1460 lines
38 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 8859c8b96cd9e80652813f7bcf561432a5e9f934 Maintainer: ae Status: ready --><!-- CREDITS: felipe,fabioluciano,rogeriopradoj,geekcom,ae,gabrielsanva,leonardolara -->
<sect1 xml:id="language.types.array">
<title>Arrays</title>
<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árias usos diferentes: ele pode ser tratado como um array,
uma lista (vetor), hashtable (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
$array = array(
"foo" => "bar",
"bar" => "foo",
);
// Utilizando a sintaxe curta
$array = [
"foo" => "bar",
"bar" => "foo",
];
?>
]]>
</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 a 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>
</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];
?>
]]>
</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> não existir ou estiver preenchido com or is set to &null; or &false;, será criado, servindo como
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.
Crir um array a partir de &null; e valores indefinidos ainda é permitido.
</simpara>
</note>
<para>
Para mudar um certo valor, apenas atribua um novo valor
para um elemento especificado por sua chave. Se você quiser
remover um par chave/valor, você precisa aplicar a função <function>unset</function> na chave.
</para>
<informalexample>
<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
unset($arr); // E isto apaga todo o array
?>
]]>
</programlisting>
</informalexample>
<note>
<para>
Como mencionado acima, se nenhuma chave for especificada, o maior índice <type>int</type> é
obtido, e a nova chave será esse o 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 sua última
reindexação do <type>array</type>. Veja o seguinte exemplo:
</para>
<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>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$source_array = ['foo', 'bar', 'baz'];
[$foo, $bar, $baz] = $source_array;
echo $foo; // imprime "foo"
echo $bar; // imprime "bar"
echo $baz; // imprime "baz"
?>
]]>
</programlisting>
</informalexample>
<para>
A desconstrução de arrays pode ser utilizada no &foreach; para desconstruir
um array multidimensional enquanto o percorre.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$source_array = [
[1, 'John'],
[2, 'Jane'],
];
foreach ($source_array as [$id, $name]) {
// Aqui $id e $name podem ser utilizados
}
?>
]]>
</programlisting>
</informalexample>
<para>
Elementos de arrays serão ignorados se a variável não for providenciada. Desconstrução
de arrays sempre iniciam no índice <literal>0</literal>.
</para>
<informalexample>
<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; // imprime "baz"
?>
]]>
</programlisting>
</informalexample>
<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>
<informalexample>
<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; // imprime 3
$source_array = ['foo', 'bar', 'baz'];
// Atribui o elemento de índice 2 na variável $baz
[2 => $baz] = $source_array;
echo $baz; // imprime "baz"
?>
]]>
</programlisting>
</informalexample>
<para>
Desconstrução de arrays podem ser utilizados para trocar duas variáveis.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$a = 1;
$b = 2;
[$b, $a] = [$a, $b];
echo $a; // imprime 2
echo $b; // imprime 1
?>
]]>
</programlisting>
</informalexample>
<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>
</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>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$a = array( 1 => 'um', 2 => 'dois', 3 => 'três' );
unset( $a[2] );
/* 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');
*/
$b = array_values($a);
// Agora $b é o array(0 => 'um', 1 =>'três')
?>
]]>
</programlisting>
</informalexample>
</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: faça e não faça</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>
<note>
<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>
<informalexample>
<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>
</informalexample>
&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>
</note>
<para>
Mais exemplos para demonstrar esse comportamento:
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
// Mostrando todos os erros
error_reporting(E_ALL);
$arr = array('fruta' => 'maçã', 'legume' => 'cenoura');
// Correto
print $arr['fruta']; // maçã
print $arr['legume']; // cenoura
// Errado. Isto funciona mas lança um erro PHP do
// nível E_NOTICE porque é utilizada uma constante indefinida (fruta)
//
// Repare: Quando utiliza-se a constante indefinida fruta, o PHP assume 'fruta'
print $arr[fruta]; // maçã
// Agora vamos definir uma constante para demonstrar o que pode acontecer. Nós
// vamos assimilar o valor 'legume' para a constante de nome fruta
define('fruta', 'legume');
// Observe a diferença agora
print $arr['fruit']; // maçã
print $arr[fruit]; // cenoura
// O exemplo seguinte é normal dentro de uma string. Constantes não são
// observadas dentro de strings e por isso nenhum E-NOTICE não é lançado aqui
print "Olá $arr[fruta]"; // Olá maçã
// Com uma exceção: chaves envolvendo arrays dentro de strings
// ativam a checagem de constantes, como em
print "Olá {$arr[fruta]}"; // Hello cenoura
print "Olá {$arr['fruta']}"; // Hello maçã
// 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 se aplica ao uso de superglobais em strings
print "Olá $arr['fruta']";
print "Olá $_GET['foo']";
// Nesse caso, use concatenação
print "Olá " . $arr['fruta']; // Olá maçã
?>
]]>
</programlisting>
</informalexample>
<para>
Quando a diretiva <link linkend="ini.error-reporting">error_reporting</link> for configurada
para mostrar erros de nível <constant>E_NOTICE</constant> (configurando-a como
<constant>E_ALL</constant>, por exemplo), se tornarão imediatamente
visíveis. Por padrão, a diretiva <link linkend="ini.error-reporting">
error_reporting</link> está configurada para não mostrar avisos.
</para>
<para>
Como especificado na seção <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>
Note 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>
<informalexample>
<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>
</informalexample>
<para>
Esses <literal>NUL</literal> podem ocasionar comportamentos inesperados:
</para>
<informalexample>
<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>
</informalexample>
<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>, você terá 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.
</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']
?>
]]>
</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
// string key
$arr1 = ["a" => 1];
$arr2 = ["a" => 2];
$arr3 = ["a" => 0, ...$arr1, ...$arr2];
var_dump($arr3); // ["a" => 2]
// integer key
$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>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
// Isso:
$a = array( 'color' => 'red',
'taste' => 'sweet',
'shape' => 'round',
'name' => 'apple',
4 // key will be 0
);
$b = array('a', 'b', 'c');
// é 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').
?>
]]>
</programlisting>
</informalexample>
<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
);
// apenas chaves numéricas
$array = array( 7,
8,
0,
156,
-10
);
// que é o mesmo que array( 0 => 7, 1 => 8, ...)
$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
);
// array vazio
$empty = array();
?>
]]>
<!-- 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
foreach ($colors as &$color) {
$color = mb_strtoupper($color);
}
unset($color); /* ensure that following writes to
$color will not modify the last array element */
print_r($colors);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Array
(
[0] => RED
[1] => BLUE
[2] => GREEN
[3] => YELLOW
)
]]>
</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);
?>
]]>
</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">
<![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",
)
);
// Alguns exemplo 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";
?>
]]>
</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>
<informalexample>
<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 sao os mesmos
?>
]]>
</programlisting>
</informalexample>
</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
-->