Files
archived-doc-pt-br/language/types/type-juggling.xml
Leonardo Lara Rodrigues 452d861bfb sync with en rev
2025-11-04 18:29:39 -03:00

477 lines
15 KiB
XML

<?xml version="1.0" encoding="utf-8"?><!-- EN-Revision: 87fd768a70bb136ad6ba94699e8c6332e0c115e0 Maintainer: leonardolara Status: ready --><!-- CREDITS: felipe,fabioluciano,geekcom,gabrielsanva,ae,leonardolara -->
<sect1 xml:id="language.types.type-juggling">
<title>Conversão automática de tipos</title>
<simpara>
O PHP não requer a tipagem explícita em declarações de variáveis.
Nesse caso, o tipo de uma variável é determinado pelo valor armazenado.
Ou seja, se uma <type>string</type> é armazenada numa variável
<varname>$var</varname>, então <varname>$var</varname> terá o tipo
<type>string</type>. Se após isso um valor <type>int</type> for armazenado
em <varname>$var</varname>, ele será do tipo <type>int</type>.
</simpara>
<para>
O PHP pode tentar converter o tipo de um valor em outro, automaticamente,
em alguns contextos. Esses contextos são:
<itemizedlist>
<listitem>
<simpara>Numérico</simpara>
</listitem>
<listitem>
<simpara>String</simpara>
</listitem>
<listitem>
<simpara>Lógico</simpara>
</listitem>
<listitem>
<simpara>Inteiro e string</simpara>
</listitem>
<listitem>
<simpara>Comparação</simpara>
</listitem>
<listitem>
<simpara>Função</simpara>
</listitem>
</itemizedlist>
</para>
<note>
<simpara>
Quando um valor precisa ser interpretado como um tipo diferente, o valor
em si <emphasis>não</emphasis> se altera, apenas uma "cópia" é convertido.
</simpara>
</note>
<simpara>
Para forçar uma variável ser avaliada como um certo tipo, veja a seção
<link linkend="language.types.typecasting">Conversão de tipo</link>. Se
desejar mudar o tipo de uma variável, veja a função <function>settype</function>.
</simpara>
<sect2>
<title>Contexto numérico</title>
<simpara>
Esse contexto é utilizando em
<link linkend="language.operators.arithmetic">operadores aritméticos</link>.
</simpara>
<simpara>
Esse contexto ocorre se um dos operandos é um <type>float</type> (e não
interpretável como <type>int</type>), se ambos os operandos são interpretados como
<type>float</type>, ou se o resultado é um <type>float</type>.
Se não, se os operandos são interpretados como <type>int</type>,
ou o resultado é um <type>int</type>.
A partir do 8.0.0, se um dos operandos não pode ser reinterpretado, um erro do tipo
<classname>TypeError</classname> é lançado.
</simpara>
</sect2>
<sect2>
<title>Contextos string</title>
<simpara>
Esse contexto ocorre ao se utilizar <function>echo</function>,
<function>print</function>,
<link linkend="language.types.string.parsing">interpolação de strings</link>,
o
<link linkend="language.operators.string">operador de concatenação</link>.
</simpara>
<simpara>
Nesse contexto, o valor será interpretado como <type>string</type>.
Se o valor não puder ser interpretado, então <classname>TypeError</classname> é lançado.
Anteriormente ao 7.4.0, um alerta <constant>E_RECOVERABLE_ERROR</constant> era emitido.
</simpara>
</sect2>
<sect2>
<title>Contextos lógicos</title>
<simpara>
Este contexto ocorre em instruções condicionais, no uso do
<link linkend="language.operators.comparison.ternary">operador ternário</link>,
ou em uma <link linkend="language.operators.logical">operação lógica</link>.
</simpara>
<simpara>
Nesse contexto, o valor será interpretado como <type>bool</type>.
</simpara>
</sect2>
<sect2>
<title>Contextos inteiros e string</title>
<simpara>
Este contexto ocorre quando utilizando
<link linkend="language.operators.bitwise">operadores bitwise</link>.
</simpara>
<simpara>
Este contexto ocorre se todos os operandos são do tipo <type>string</type>,
ou o valor retornado é <type>string</type>.
Se não, os operados são interpretados como <type>int</type>,
ou o resultado é um <type>int</type>.
A partir do PHP 8.0.0, se um dos operandos não puder ser reinterpretado, então
<classname>TypeError</classname> é lançado.
</simpara>
</sect2>
<sect2>
<title>Contextos de comparação</title>
<simpara>
Este contexto ocorre quando utilizando
<link linkend="language.operators.comparison">operadores de comparação</link>.
</simpara>
<simpara>
As conversões de tipo que ocorrem nesse contexto são explicados na
tabela de sobre comparação entre vários tipos, explicadas
<link linkend="language.operators.comparison.types">aqui</link>.
</simpara>
</sect2>
<sect2 xml:id="language.types.type-juggling.function">
<title>Contextos de função</title>
<simpara>
Este contexto ocorre quando um valor é um parâmetro tipado, ou quando uma propriedade
ou valor retornado de uma função declara um tipo.
</simpara>
<para>
Nesse contexto, o valor precisa do tipo informado.
Duas alternativas existem. A primeira: se o valor é do tipo
<type>int</type> e o tipo declarado é <type>float</type>, então o
inteiro é convertido num número de ponto flutuante.
A segunda alternativa: se o tipo declarado é um <emphasis>escalar</emphasis>,
<!-- e.g. An object that implements __toString will pass a string type -->
e o valor é conversível no tipo escalar, juntamente com
o modo de conversão coercivo no estado ativo
(o padrão), o valor pode ser convertido no valor escalar.
Veja abaixo uma descrição detalhada desse comportamento.
</para>
<warning>
<simpara>
<link linkend="functions.internal">Funções internas</link>
convertem automaticamente &null; para tipos escalares, mas
esse comportamento foi <emphasis>DESCONTINUADO</emphasis> desde o PHP 8.1.0.
</simpara>
</warning>
<sect3 xml:id="language.types.type-juggling.function.simple">
<title>Coerção de tipos com tipos declarados</title>
<itemizedlist>
<listitem>
<simpara>
Declaração <type>bool</type>: o valor é convertido para <type>bool</type>.
</simpara>
</listitem>
<listitem>
<simpara>
Declaração <type>int</type>: o valor é convertido para <type>int</type>
quando a conversão for bem definida. Por exemplo, quando uma string é
<link linkend="language.types.numeric-strings">numérica</link>.
</simpara>
</listitem>
<listitem>
<simpara>
Declaração <type>float</type>: o valor é convertido para <type>float</type>
quando a conversão for bem definida. Por exemplo, quando uma string é
<link linkend="language.types.numeric-strings">numérica</link>.
</simpara>
</listitem>
<listitem>
<simpara>
Declaração <type>string</type>: o valor é convertido para <type>string</type>.
</simpara>
</listitem>
</itemizedlist>
</sect3>
<sect3 xml:id="language.types.type-juggling.function.union">
<title>Conversão de tipos em tipos union</title>
<para>
Quando <literal>strict_types</literal> está desativado, declarações de tipos escalares
estão sujeitas a conversões implícitas e limitadas.
Se o tipo exato do valor não é parte da união, então o tipo final da conversão
é escolhido na seguinte ordem de preferência:
<orderedlist>
<listitem>
<simpara>
<type>int</type>
</simpara>
</listitem>
<listitem>
<simpara>
<type>float</type>
</simpara>
</listitem>
<listitem>
<simpara>
<type>string</type>
</simpara>
</listitem>
<listitem>
<simpara>
<type>bool</type>
</simpara>
</listitem>
</orderedlist>
Se o tipo existe na união e o valor puder ser convertido pela mesma
semântica do PHP, então esse tipo é escolhido.
Senão, um tipo seguinte é tentado.
</para>
<caution>
<para>
Existe uma exceção, no caso do valor ser uma string, e ambos int e float serem partes
da união, o tipo preferido será determinado pela semântica de
<link linkend="language.types.numeric-strings">strings numéricas</link>.
<!---->
Por exemplo, para <literal>"42"</literal> o tipo <type>int</type> é escolhido,
enquanto que para <literal>"42.0"</literal> o tipo escolhido é <type>float</type>.
</para>
</caution>
<note>
<para>
Tipos que não fazem parte da lista acima não são elegíveis para destinos
da conversão implícita. Em particular, não existem conversões implícitas para
os tipos <type>null</type>, <type>false</type> e <type>true</type>.
<!---->
</para>
</note>
<example>
<title>Exemplo de tipos que podem ser convertidos em tipos union</title>
<programlisting role="php">
<![CDATA[
<?php
// int|string
42 --> 42 // tipo exato
"42" --> "42" // tipo exato
new ObjectWithToString --> "Resultado de __toString()"
// e objero não compatível com int, padrão para string
42.0 --> 42 // float compatível com int
42.1 --> 42 // float compatível com int
1e100 --> "1.0E+100" // float muito grande para int, padrão para string
INF --> "INF" // float muito grande para int, padrão para string
true --> 1 // bool compatível com int
[] --> TypeError // array não é compatível com int ou string
// int|float|bool
"45" --> 45 // string numérica int
"45.0" --> 45.0 // string numérica float
"45X" --> true // string não numérica, padrão para bool
"" --> false // string não numérica, padrão para bool
"X" --> true // string não numérica, padrão para bool
[] --> TypeError // array não é compatível com int, float ou bool
?>
]]>
</programlisting>
</example>
</sect3>
</sect2>
<sect2 xml:id="language.types.typecasting">
<title>Conversão explícita</title>
<simpara>
Converte o valor do tipo para o tipo escolhido através da escrita do tipo
entre parênteses, antes do valor a ser convertido.
</simpara>
<example>
<title>Conversão de tipo</title>
<programlisting role="php">
<![CDATA[
<?php
$foo = 10; // $foo é um inteiro
$bar = (bool) $foo; // $bar é um booleano
var_dump($bar);
?>
]]>
</programlisting>
</example>
<simpara>
As conversões previstas são:
</simpara>
<simplelist>
<member><literal>(int)</literal> - converte para <type>int</type></member>
<member><literal>(bool)</literal> - converte para <type>bool</type></member>
<member><literal>(float)</literal> - converte para <type>float</type></member>
<member><literal>(string)</literal> - converte para <type>string</type></member>
<member><literal>(array)</literal> - converte para <type>array</type></member>
<member><literal>(object)</literal> - converte para <type>object</type></member>
<member><literal>(unset)</literal> - converte para <type>NULL</type></member>
</simplelist>
<note>
<para>
<literal>(integer)</literal> converte igual a <literal>(int)</literal>.
<literal>(boolean)</literal> converte igual a <literal>(bool)</literal>.
<literal>(binary)</literal> converte igual a <literal>(string)</literal>.
<literal>(double)</literal> e <literal>(real)</literal> converte igual a
<literal>(float)</literal>.
Essas conversões alternativas não são recomendados, ainda que existentes.
</para>
</note>
<warning>
<simpara>
A conversão <literal>(real)</literal> foi descontinuada a partir do PHP 7.4.0
e removida a partir do PHP 8.0.0.
</simpara>
</warning>
<warning>
<simpara>
A conversão <literal>(unset)</literal> foi descontinuada a partir do PHP 7.2.0.
Observe que a conversão <literal>(unset)</literal> tem o mesmo efeito que
informar o valor <type>NULL</type> para a variável ou chamada de função.
A conversão <literal>(unset)</literal> foi removida no PHP 8.0.0.
</simpara>
</warning>
<caution>
<simpara>
A conversão <literal>(binary)</literal> e o prefixo <literal>b</literal> ainda existem
para compatibilidade. Atualmente <literal>(binary)</literal> e
<literal>(string)</literal> são idênticos, no entanto isso pode mudar
e não deve ser considerado estável.
</simpara>
</caution>
<note>
<para>
Espaços são ignorados dentro dos parênteses de uma conversão.
Portanto, as linhas seguintes são equivalentes:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$foo = (int) $bar;
$foo = ( int ) $bar;
?>
]]>
</programlisting>
</informalexample>
</para>
</note>
<informalexample>
<simpara>
Convertendo <type>string</type> e variáveis para
<type>string</type>s binárias:
</simpara>
<programlisting role="php">
<![CDATA[
<?php
$binary = (binary) $string;
$binary = b"binary string";
?>
]]>
</programlisting>
</informalexample>
<!-- TODO Remove or move into string context section? -->
<simpara>
Em vez de converter uma variável para <type>string</type>, é possível
delimitar a variável entre aspas.
</simpara>
<example>
<title>Diferentes mecanismos de conversão</title>
<programlisting role="php">
<![CDATA[
<?php
$foo = 10; // $foo é int
$str = "$foo"; // $str é string
$fst = (string) $foo; // $fst também é string
// Isto exibe "são iguais"
if ($fst === $str) {
echo "são iguais", PHP_EOL;
}
?>
]]>
</programlisting>
</example>
<para>
Não é tão óbvio o que acontece ao converter entre certos
tipos. Para mais informações, veja as seções:
<simplelist>
<member><link linkend="language.types.boolean.casting">Convertendo para boolean</link></member>
<member><link linkend="language.types.integer.casting">Convertendo para integer</link></member>
<member><link linkend="language.types.float.casting">Convertendo para float</link></member>
<member><link linkend="language.types.string.casting">Convertendo para string</link></member>
<member><link linkend="language.types.array.casting">Convertendo para array</link></member>
<member><link linkend="language.types.object.casting">Convertendo para object</link></member>
<member><link linkend="language.types.resource.casting">Convertendo para resource</link></member>
<member><link linkend="language.types.null.casting">Convertendo para NULL</link></member>
<member><link linkend="types.comparisons">Tabela de conversão de tipos</link></member>
</simplelist>
</para>
<note>
<simpara>
O PHP suporta a indexação de <type>string</type> utilizando
a mesma sintaxe de <type>array</type>s, de forma que o exemplo seguinte
é válido em todas as versões do PHP:
</simpara>
<example>
<title>Usando índice de array com uma string</title>
<programlisting role="php">
<![CDATA[
<?php
$a = 'car'; // $a é uma string
$a[0] = 'b'; // $a ainda é uma string
echo $a; // bar
?>
]]>
</programlisting>
</example>
<simpara>
Veja a seção sobre <link linkend="language.types.string.substr">Acesso a caracteres
da string</link> para mais informações.
</simpara>
</note>
</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
-->