Files
archived-doc-pt-br/language/types/string.xml
2025-08-23 16:58:14 -03:00

1390 lines
41 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 2832df2e1bd7daa1ec29ffb167dce1c9feb8cc6b Maintainer: leonardolara Status: ready --><!-- CREDITS: felipe,thiago,fabioluciano,rogeriopradoj,geekcom,guimrl,ae,marcosmarcolin,leonardolara -->
<sect1 xml:id="language.types.string">
<title>Strings</title>
<para>
Uma <type>string</type> é uma série de caracteres, onde um caractere é
o mesmo que um byte. Isso significa que o PHP possui suporte a um conjunto de apenas 256 caracteres,
e, portanto, não possui suporte nativo a Unicode. Veja mais
<link linkend="language.types.string.details"> detalhes do tipo
string</link>.
</para>
<note>
<simpara>
Em sistemas de 32 bits, uma <type>string</type> pode ter até 2GB
(2147483647 bytes).
</simpara>
</note>
<sect2 xml:id="language.types.string.syntax">
<title>Sintaxe</title>
<para>
Uma <type>string</type> literal pode ser especificada de quatro formas diferentes.
</para>
<itemizedlist>
<listitem>
<simpara>
<link linkend="language.types.string.syntax.single">aspas simples</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.types.string.syntax.double">aspas duplas</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.types.string.syntax.heredoc">sintaxe heredoc</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.types.string.syntax.nowdoc">sintaxe nowdoc</link>
</simpara>
</listitem>
</itemizedlist>
<sect3 xml:id="language.types.string.syntax.single">
<title>Aspas simples</title>
<para>
A maneira mais simples de se especificar uma <type>string</type> é
delimitá-la entre aspas simples (o caractere <literal>'</literal>).
</para>
<para>
Para especificar um apóstrofo, escape-o com uma contrabarra
(<literal>\</literal>). Para especificar uma contrabarra literal, duplique-a
(<literal>\\</literal>). Todas as outras ocorrências da contrabarra serão tratadas
como uma contrabarra literal: isso significa que outras sequências de escape que
se esteja acostumado a utilizar, como <literal>\r</literal> ou <literal>\n</literal>, serão
literalmente impressas em vez de ter qualquer significado
especial.
</para>
<note>
<simpara>
Diferentemente das sintaxes <link linkend="language.types.string.syntax.double">com aspas duplas</link>
e <link linkend="language.types.string.syntax.heredoc">heredoc</link>,
<link linkend="language.variables">variáveis</link> e sequências de escape
para caracteres especiais <emphasis>não</emphasis> serão expandidas quando ocorrerem
dentro de uma <type>string</type> delimitada por aspas simples.
</simpara>
</note>
<example>
<title>Variantes de sintaxe</title>
<programlisting role="php">
<![CDATA[
<?php
echo 'isto é uma string comum', PHP_EOL;
echo 'Você pode incluir novas linhas em strings
dessa maneira que estará
tudo bem', PHP_EOL;
// Exibe: Arnold disse uma vez: "I'll be back"
echo 'Arnold disse uma vez: "I\'ll be back"', PHP_EOL;
// Exibe: Você excluiu C:\*.*?
echo 'Você excluiu C:\\*.*?', PHP_EOL;
// Exibe: Você excluiu C:\*.*?
echo 'Você excluiu C:\*.*?', PHP_EOL;
// Exibe: Isto não será substituído por \n uma nova linha
echo 'Isto não será substituído por \n uma nova linha', PHP_EOL;
// Exibe: Variáveis $também não $expandem
echo 'Variáveis $também não $expandem', PHP_EOL;
?>
]]>
</programlisting>
</example>
</sect3>
<sect3 xml:id="language.types.string.syntax.double">
<title>Aspas duplas</title>
<para>
Se a <type>string</type> for delimitada entre aspas duplas (<literal>"</literal>), o PHP
interpretará a seguinte sequência de escape como caracteres especiais:
</para>
<table>
<title>Sequências de escape</title>
<tgroup cols="2">
<thead>
<row>
<entry>Sequências</entry>
<entry>Significado</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>\n</literal></entry>
<entry>Nova linha (LF ou 0x0A (10) em ASCII)</entry>
</row>
<row>
<entry><literal>\r</literal></entry>
<entry>Retorno de carro (CR ou 0x0D (13) em ASCII)</entry>
</row>
<row>
<entry><literal>\t</literal></entry>
<entry>Tabulação horizontal (HT ou 0x09 (9) em ASCII)</entry>
</row>
<row>
<entry><literal>\v</literal></entry>
<entry>Tabulação vertical (VT ou 0x0B (11) em ASCII)</entry>
</row>
<row>
<entry><literal>\e</literal></entry>
<entry>Escape (ESC ou 0x1B (27) em ASCII)</entry>
</row>
<row>
<entry><literal>\f</literal></entry>
<entry>Form feed (FF ou 0x0C (12) em ASCII)</entry>
</row>
<row>
<entry><literal>\\</literal></entry>
<entry>contrabarra ou barra invertida</entry>
</row>
<row>
<entry><literal>\$</literal></entry>
<entry>Sinal de cifrão</entry>
</row>
<row>
<entry><literal>\"</literal></entry>
<entry>aspas duplas</entry>
</row>
<row>
<entry><literal>\[0-7]{1,3}</literal></entry>
<entry>
Octal: uma sequência de caracteres que coincide com a expressão regular <literal>[0-7]{1,3}</literal>
é um caractere em notação octal (por exemplo, <literal>"\101" === "A"</literal>),
o qual é silenciosamente turcado para um byte (por exemplo <literal>"\400" === "\000"</literal>)
</entry>
</row>
<row>
<entry><literal>\x[0-9A-Fa-f]{1,2}</literal></entry>
<entry>
Hexadecimal: uma sequência de caracteres que coincide com a expressão regular
<literal>[0-9A-Fa-f]{1,2}</literal> é um caractere em notação decimal
(por exemplo, <literal>"\x41" === "A"</literal>)
</entry>
</row>
<row>
<entry><literal>\u{[0-9A-Fa-f]+}</literal></entry>
<entry>
Unicode: uma sequência de caracteres coincidindo com a expressão regular <literal>[0-9A-Fa-f]+</literal>
é um codepoint Unicode, o qual terá como resultado uma string contendo a representação UTF-8 desses codepoints.
Os colchetes são requeridos. Por exemplo, <literal>"\u{41}" === "A"</literal>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Como com as <type>string</type>s entre aspas simples, escapar qualquer outro caractere
resultará em uma contrabarra sendo impressa.
</para>
<para>
O recurso mais importante de <type>string</type>s delimitadas por aspas duplas é o fato de que
nomes de variáveis serão expandidos. Veja a
<link linkend="language.types.string.parsing">interpolação de strings</link> para
detalhes.
</para>
</sect3>
<sect3 xml:id="language.types.string.syntax.heredoc">
<title>Heredoc</title>
<simpara>
Uma terceira maneira de delimitar <type>string</type>s é a sintaxe heredoc:
<literal>&lt;&lt;&lt;</literal>. Após este operador, um identificador é
fornecido seguido de uma nova linha. A própria <type>string</type> é colocada em seguida e a seguir
o mesmo identificador novamente para fechar a string.
</simpara>
<simpara>
O identificador de fechamento pode ser indentado com espaços ou tabulações, e nesse caso
a indentação será removida de todas as linhas da doc string.
Anteriormente ao PHP 7.3.0, o identificador <emphasis>precisava</emphasis>
estar no começo da linha.
</simpara>
<simpara>
Além disso, o identificador de fechamento precisa seguir as mesmas convenções de nomes
de outros identificadores do PHP: ele precisa conter apenas caracteres alfanuméricos e
underlines, e precisa começar com uma letra ou underline.
</simpara>
<example>
<title>Exemplo Heredoc simples no PHP 7.3.0</title>
<programlisting role="php">
<![CDATA[
<?php
// Sem indentação
echo <<<END
a
b
c
\n
END;
// 4 espaços de indentação
echo <<<END
a
b
c
END;
]]>
</programlisting>
&example.outputs.73;
<screen>
<![CDATA[
a
b
c
a
b
c
]]>
</screen>
</example>
<simpara>
Se o identificador de fechamento estiver identado diferentemente das linhas do corpo, um <classname>ParseError</classname> será lançado:
</simpara>
<example>
<title>Identificador de fechamento indentado diferente das linhas do corpo</title>
<programlisting role="php">
<![CDATA[
<?php
echo <<<END
a
b
c
END;
]]>
</programlisting>
&example.outputs.73;
<screen>
<![CDATA[
Parse error: Invalid body indentation level (expecting an indentation level of at least 3) in example.php on line 4
]]>
</screen>
</example>
<simpara>
Se o identificador de fechamento é identado, tabulações podem ser utilizadas, no entanto
tabulações e espaços <emphasis>não podem</emphasis> estar misturados ou diferentes,
entre a indentação do fechamento e a indentação do corpo
Nesses casos, um <classname>ParseError</classname> será lançado.
Essas restrições de whitespace estão incluídas dados que a mistura de tabulações
e espaços são prejudiciais à legibilidade.
</simpara>
<example>
<title>Indentação diferente entre corpo e fechamento</title>
<programlisting role="php" annotations="non-interactive">
<![CDATA[
<?php
// Todos esses códidos falharão.
// Indentação diferente entre corpo (espaços) e fechamento (tabulações)
{
echo <<<END
a
END;
}
// Misturar tabulações e espaços no corpo
{
echo <<<END
a
END;
}
// Misturar espaços e tabulações no identificador de fechamento
{
echo <<<END
a
END;
}
]]>
</programlisting>
&example.outputs.73;
<screen>
<![CDATA[
Parse error: Invalid indentation - tabs and spaces cannot be mixed in example.php line 8
]]>
</screen>
</example>
<simpara>
O identificador de fechamento do corpo não necessita de um
ponto e vírgula ou nova linha. Por exemplo, o seguinte código
é permitido a partir do PHP7.3.0:
</simpara>
<example>
<title>Continuando uma expressão após o identificador de fechamento</title>
<programlisting role="php">
<![CDATA[
<?php
$values = [<<<END
a
b
c
END, 'd e f'];
var_dump($values);
]]>
</programlisting>
&example.outputs.73;
<screen>
<![CDATA[
array(2) {
[0] =>
string(11) "a
b
c"
[1] =>
string(5) "d e f"
}
]]>
</screen>
</example>
<warning>
<simpara>
Se o identificador de fechamento for encontrado no começo da linha, existe
a ambiguidade de ele ser considerado ou não parte do texto, podendo
também ser considerado como fechamento, pode causar um <classname>ParseError</classname>.
</simpara>
<example>
<title>Identificador de fechamento no corpo da string pode causar um ParseError</title>
<programlisting role="php">
<![CDATA[
<?php
$values = [<<<END
a
b
END ING
END, 'd e f'];
]]>
</programlisting>
&example.outputs.73;
<screen>
<![CDATA[
Parse error: syntax error, unexpected identifier "ING", expecting "]" in example.php on line 5
]]>
</screen>
</example>
<simpara>
Para evitar esse problema, basta seguir a seguinte regra:
<emphasis>escolha identificadores que não aparecem no corpo
do texto</emphasis>.
</simpara>
</warning>
<warning>
<simpara>
Anteriormente ao PHP 7.3.0, era muito importante notar que a linha com
o identificador de fechamento não poderia conter outros caracteres, exceto um ponto e vírgula
(<literal>;</literal>).
Isso significava que o identificador de fechamento
<emphasis>não poderia ser identado</emphasis>, e que não poderia haver espaços
ou tabulações antes ou depois do ponto e vírgula. É importante notar também que
o primeiro caractere antes do fechamento deveria ser uma newline, como
definido pelo sistema operacional. Ou seja, <literal>\n</literal> em
sistemas Unix, incluindo o macOS. O identificador de fechamento também
deveria ser seguido de um newline.
</simpara>
<simpara>
Se essa regra não for seguida, e o identificador de fechamento não estiver "limpo", ele
não será considerado como fechamento, e o PHP continuará lendo o script como se fosse
texto. Se um identificador de fechamento correto não for encontrado até o final do
arquivo, um erro de interpretação será lançado na última linha.
</simpara>
<example>
<title>Exemplo inválido, antes do PHP 7.3.0</title>
<programlisting role="php">
<!-- Este é um exemplo INVÁLIDO -->
<![CDATA[
<?php
class foo {
public $bar = <<<EOT
bar
EOT;
}
// O identificador não deve ser indentado
?>
]]>
</programlisting>
</example>
<example>
<title>Exemplo válido, mesmo antes do PHP 7.3.0</title>
<programlisting role="php">
<!-- Este é um exemplo VÁLIDO -->
<![CDATA[
<?php
class foo {
public $bar = <<<EOT
bar
EOT;
}
?>
]]>
</programlisting>
</example>
<para>
Heredocs não podem ser usados para inicializar propriedades de classe.
</para>
</warning>
<para>
Textos heredoc se comportam como <type>string</type>s delimitadas por aspas duplas, sem
as aspas duplas. Isso significa que aspas simples em heredocs não precisam ser
escapadas, apesar de que os códigos de escape listados acima podem continuar sendo utilizados. Variáveis
são expandidas, mas o mesmo cuidado deve ser tomado ao expressar variáveis complexas
dentro do heredoc assim como nas <type>string</type>s.
</para>
<example>
<title>Exemplo de delimitação de strings heredoc</title>
<programlisting role="php">
<![CDATA[
<?php
$str = <<<EOD
Exemplo de uma string
distribuída em várias linhas
utilizando a sintaxe heredoc.
EOD;
/* Exemplo mais complexo, com variáveis */
class foo
{
var $foo;
var $bar;
function __construct()
{
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$name = 'Meu nome';
echo <<<EOT
Meu nome é "$name". Eu estou imprimindo $foo->foo.
Agora, eu estou imprimindo {$foo->bar[1]}.
Isto deve imprimir um 'A' maiúsculo: \x41
EOT;
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Meu nome é "Meu nome". Eu estou imprimindo Foo.
Agora, eu estou imprimindo Bar2.
Isto deve imprimir um 'A' maiúsculo: A]]>
</screen>
</example>
<para>
É possível também utilizar a sintaxe Heredoc para passar dados para argumentos de
funções:
</para>
<example>
<title>Exemplo de Heredoc em argumentos</title>
<programlisting role="php">
<![CDATA[
<?php
var_dump(array(<<<EOD
foobar!
EOD
));
?>
]]>
</programlisting>
</example>
<para>
É possível inicializar variáveis estáticas e
propriedades/constantes de classe utilizando a sintaxe heredoc:
</para>
<example>
<title>Utilizando o Heredoc na inicialização de valores estáticos</title>
<programlisting role="php" annotations="non-interactive">
<![CDATA[
<?php
// Variáveis estáticas
function foo()
{
static $bar = <<<LABEL
Nada aqui...
LABEL;
}
// Classe propriedades/constantes
class foo
{
const BAR = <<<FOOBAR
Exemplo de constante
FOOBAR;
public $baz = <<<FOOBAR
Exemplo de propriedade
FOOBAR;
}
?>
]]>
</programlisting>
</example>
<para>
O identificador de abertura do Heredoc pode ser opcionalmente
delimitado por aspas duplas:
</para>
<example>
<title>Usando aspas duplas no Heredoc</title>
<programlisting role="php">
<![CDATA[
<?php
echo <<<"FOOBAR"
Olá, mundo!
FOOBAR;
?>
]]>
</programlisting>
</example>
</sect3>
<sect3 xml:id="language.types.string.syntax.nowdoc">
<title>Nowdoc</title>
<para>
Nowdocs estão para aspas simples assim como os heredocs estão para aspas duplas em
strings. Um nowdoc é especificado similarmente a um heredoc, mas <emphasis>
nenhuma interpolação é feita</emphasis> dentro de um nowdoc. A construção é ideal para
colocar códigos PHP ou outros grandes blocos de texto sem a necessidade de
usar escapes. Compartilha algumas características em comum com a construção SGML
<literal>&lt;![CDATA[ ]]&gt;</literal>, assim é declarado um bloco de
texto onde nada será analisado.
</para>
<para>
Um nowdoc é identificado com a mesma sequência <literal>&lt;&lt;&lt;</literal>
usada para heredocs, mas o identificador precisa ficar entre
aspas simples, por exemplo. <literal>&lt;&lt;&lt;'EOT'</literal>. Todas as regras para
identificadores heredoc também se aplicam para identificadores nowdoc, especialmente aquelas
referentes a aparência do identificador de fechamento.
</para>
<example>
<title>Exemplo de string em Nowdoc</title>
<programlisting role="php">
<![CDATA[
<?php
echo <<<'EOD'
Exemplo de string abrangendo várias linhas
usando a sintaxe nowdoc. As barras invertidas são sempre tratadas literalmente,
por exemplo. \\ e \'.
EOD;
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Exemplo de string abrangendo várias linhas
usando a sintaxe nowdoc. As barras invertidas são sempre tratadas literalmente,
por exemplo. \\ e \'.
]]>
</screen>
</example>
<example>
<title>Exemplo de Nowdoc, com variáveis</title>
<programlisting role="php">
<![CDATA[
<?php
class foo
{
public $foo;
public $bar;
function __construct()
{
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$name = 'MyName';
echo <<<'EOT'
Meu nome é "$nome". Estou imprimindo alguns $foo->foo.
Agora, estou imprimindo alguns {$foo->bar[1]}.
Isso não deve imprimir um 'A' maiúsculo: \x41
EOT;
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Meu nome é "$nome". Estou imprimindo alguns $foo->foo.
Agora, estou imprimindo alguns {$foo->bar[1]}.
Isso não deve imprimir um 'A' maiúsculo: \x41]]>
</screen>
</example>
<example>
<title>Exemplo de dado estático</title>
<programlisting role="php" annotations="non-interactive">
<![CDATA[
<?php
class foo {
public $bar = <<<'EOT'
bar
EOT;
}
?>
]]>
</programlisting>
</example>
</sect3>
<sect3 xml:id="language.types.string.parsing">
<title>Interpolação de strings</title>
<simpara>
Quando uma <type>string</type> é especificada dentro de aspas duplas ou heredoc,
as <link linkend="language.variables">variáveis</link> podem ser substituídas dentro dela.
</simpara>
<simpara>
Há dois tipos de sintaxe: uma
<link linkend="language.types.string.parsing.basic">básica</link> e uma
<link linkend="language.types.string.parsing.advanced">avançada</link>.
A sintaxe básica é a mais comum e conveniente. Provê uma maneira de
incorporar uma variável, o valor de um <type>array</type> ou uma propriedade de <type>object</type>
em uma <type>string</type> com o mínimo de esforço.
</simpara>
<sect4 xml:id="language.types.string.parsing.basic">
<title>Sintaxe básica</title>
<simpara>
Se um sinal de cifrão (<literal>$</literal>) for encontrado, os caracteres
que o seguem, e que podem ser usados em nome de variável, serão interpretados
como tal e substituídos.
</simpara>
<example>
<title>Interpolação de string</title>
<programlisting role="php">
<![CDATA[
<?php
$suco = "maçã";
echo "Ele bebeu um pouco de suco de $suco." . PHP_EOL;
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Ele bebeu um pouco de suco de maçã.
]]>
</screen>
</example>
<simpara>
Formalmente, a estrutura para a sintaxe básica de substituição de variável é
o seguinte:
</simpara>
<informalexample>
<programlisting>
<![CDATA[
string-variável::
nome-de-variável (posição-ou-propriedade)?
| ${ expressão }
posição-ou-propriedade::
posição-na-string
| propriedade-na-string
posição-na-string::
[ nome ]
| [ nome-de-variável ]
| [ inteiro-literal ]
propriedade-na-string::
-> nome
nome-de-variável::
$ nome
nome::
[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*
]]>
</programlisting>
</informalexample>
<warning>
<para>
A sintaxe <literal>${ expressão }</literal> foi descontinuada a partir do
PHP 8.2.0, já que pode ser interpretada como
<link linkend="language.variables.variable">variáveis variáveis</link>:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
const foo = 'bar';
$foo = 'foo';
$bar = 'bar';
var_dump("${foo}");
var_dump("${(foo)}");
?>
]]>
</programlisting>
&example.outputs.82;
<screen>
<![CDATA[
Deprecated: Using ${var} in strings is deprecated, use {$var} instead in file on line 6
Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in file on line 9
string(3) "foo"
string(3) "bar"
]]>
</screen>
&example.outputs;
<screen>
<![CDATA[
string(3) "foo"
string(3) "bar"
]]>
</screen>
</informalexample>
A sintaxe <link linkend="language.types.string.parsing.advanced">avançada</link>
de interpolação de string deve ser usada em seu lugar.
</para>
</warning>
<note>
<simpara>
Se não for possível formar um nome válido, o símbolo de cifrão permanece
literalmente na string:
</simpara>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
echo "Nenhuma interpolação $ aconteceu\n";
echo "Nenhuma interpolação $\n aconteceu\n";
echo "Nenhuma interpolação $2 aconteceu\n";
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Nenhuma interpolação $ aconteceu
Nenhuma interpolação $
aconteceu
Nenhuma interpolação $2 aconteceu
]]>
</screen>
</informalexample>
</note>
<example>
<title>Interpolando o valor da primeira dimensão de um array ou propriedade</title>
<programlisting role="php">
<![CDATA[
<?php
$sucos = array("maça", "laranja", "chave_string" => "roxo");
echo "Ele bebeu um pouco de suco de $sucos[0].";
echo PHP_EOL;
echo "Ele bebeu um pouco de suco de $sucos[1].";
echo PHP_EOL;
echo "Ele bebeu um pouco de suco de $sucos[chave_string].";
echo PHP_EOL;
class A {
public $s = "string";
}
$o = new A();
echo "Valor do objeto: $o->s.";
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Ele bebeu um pouco de suco de maçã.
Ele bebeu um pouco de suco de laranja.
Ele bebeu um pouco de suco de roxo.
Valor do objeto: string.
]]>
</screen>
</example>
<note>
<simpara>
A chave do array deve ser sem aspas, e por isso não é possível
referenciar uma constante como chave com a sintaxe básica. Use a sintaxe
<link linkend="language.types.string.parsing.advanced">avançada</link>
em seu lugar.
</simpara>
</note>
<simpara>
A partir do PHP 7.1.0 índices numéricos <emphasis>negativos</emphasis> são
suportados.
</simpara>
<example><title>Índices numéricos negativos</title>
<programlisting role="php">
<![CDATA[
<?php
$string = 'string';
echo "O caractere no índice -2 é $string[-2].", PHP_EOL;
$string[-3] = 'o';
echo "Alterar o caractere no índice -3 para 'o' dá $string.", PHP_EOL;
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
O caractere no índice -2 é n.
Alterar o caractere no índice -3 para o dá strong.
]]>
</screen>
</example>
<simpara>
Para qualquer coisa mais complexa, a sintaxe
<link linkend="language.types.string.parsing.advanced">avançada</link>
deve ser usada.
</simpara>
</sect4>
<sect4 xml:id="language.types.string.parsing.advanced">
<title>Sintaxe avançada (com chaves)</title>
<simpara>
A sintaxe avançada permite a interpolação de
<emphasis>variáveis</emphasis> com acessadores arbitrários.
</simpara>
<simpara>
Qualquer variável escalar, elemento de array ou propriedade de objeto
(<modifier>static</modifier> ou não) com uma
representação de uma <type>string</type> pode ser incluída com essa sintaxe.
A expressão é escrita da mesma forma como apareceria fora da
<type>string</type> e então coloque-o entre <literal>{</literal> e
<literal>}</literal>. Já que que <literal>{</literal> não pode escapado, esta
sintaxe será somente reconhecida quando o <literal>$</literal> seguir,
imediatamente, o <literal>{</literal>. Use <literal>{\$</literal> para obter um literal
<literal>{$</literal>. Alguns exemplos que tornam isto claro:
</simpara>
<example>
<title>Sintaxe com chaves</title>
<programlisting role="php">
<![CDATA[
<?php
const DATA_KEY = 'chave-const';
$fantastico = 'fantástico';
$arr = [
'1',
'2',
'3',
[41, 42, 43],
'chave' => 'Valor indexado',
'chave-const' => 'Chave com sinal de menos',
'foo' => ['foo1', 'foo2', 'foo3']
];
// Não vai funcionar, resultado: Isso é { fantástico}
echo "Isso é { $fantastico}";
// Funciona, resultado: Isso é fantástico
echo "Isso é {$fantastico}";
class Square {
public $width;
public function __construct(int $width) { $this->width = $width; }
}
$square = new Square(5);
// Funciona
echo "Este quadrado tem {$square->width}00 centímetros de largura.";
// Funciona, as chaves entre aspas funcionam apenas usando a sintaxe de chaves
echo "Isso funciona: {$arr['chave']}";
// Funciona
echo "Isso funciona: {$arr[3][2]}";
echo "Isso funciona: {$arr[DATA_KEY]}";
// Ao usar arrays multidimensionais, sempre use chaves em torno dos arrays
// quando dentro de strings
echo "Funciona: {$arr['foo'][2]}";
echo "Funciona: {$obj->values[3]->name}";
echo "Funciona: {$obj->$staticProp}";
// Não funciona, imprime: C:\diretório\{fantástico}.txt
echo "C:\diretório\{$fantastico}.txt";
// Funciona, imprime: C:\diretório\fantástico.txt
echo "C:\\diretório\\{$fantastico}.txt";
?>
]]>
</programlisting>
</example>
<note>
<simpara>
Como esta sintaxe permite expressões arbitrárias, é possível usar
<link linkend="language.variables.variable">variáveis variáveis</link>
dentro da sintaxe avançada.
</simpara>
</note>
</sect4>
</sect3>
<sect3 xml:id="language.types.string.substr">
<title>Acesso e modificação da string por caractere</title>
<para>
É possível acessar e modificar caracteres dentro de <type>string</type>s
especificando a posição, baseada em zero, do caractere desejado na
<type>string</type> usando colchetes, parecido com <type>array</type>s, por exemplo
<varname>$str[42]</varname>. Imagine uma <type>string</type> como um
<type>array</type> de caracteres. As funções
<function>substr</function> e <function>substr_replace</function>,
podem ser utilizadas quando se deseja extrair ou substituir mais que 1 caractere.
</para>
<note>
<simpara>
A partir do PHP 7.1.0, posições negativas para strings são suportadas. Estas especificam
a posição do final da string.
Antes, posições negativas emitiam um <constant>E_NOTICE</constant> para leitura
(gerando um string vazia) e um <constant>E_WARNING</constant> para escrita
(deixando a string intocada).
</simpara>
</note>
<note>
<simpara>
Anteriormente ao PHP 8.0.0, <type>string</type>s também poderiam ser usados utilizando chaves, por exemplo
<varname>$str{42}</varname>.
Essa sintaxe por chaves foi descontinuada desde o PHP 7.4.0 e não é mais suportada a partir do PHP 8.0.0.
</simpara>
</note>
<warning>
<simpara>
Escrever em uma posição fora do intervalo preenche a string com espaços.
Tipos diferentes de inteiro são convertidos para inteiro.
Tipo ilegal de deslocamento emite um <constant>E_WARNING</constant>.
Apenas o primeiro caractere de uma string atribuída é usado.
A partir de PHP 7.1.0, a atribuição de uma string vazia lança um erro fatal. Antes,
era atribuído o byte NULL.
</simpara>
</warning>
<warning>
<simpara>
Internamente, as strings do PHP são arrays de bytes. Como resultado, acessar ou
modificar uma string usando colchetes não é seguro com multi-bytes e
deve ser feito somente em strings que utilizem apenas um byte em sua codificação,
como a ISO-8859-1.
</simpara>
</warning>
<note>
<simpara>
A partir do PHP 7.1.0, aplicar um operador de índice vazio em uma string lança um erro fatal
Antes, a string vazia era convertida em um array.
</simpara>
</note>
<example>
<title>Alguns exemplos com strings</title>
<programlisting role="php">
<![CDATA[
<?php
// Obtém o primeiro caractere de uma string
$str = 'Isto é um teste.';
$first = $str[0];
var_dump($first);
// Obtém o terceiro caractere de uma string
$third = $str[2];
var_dump($third);
// Obtém o último caractere de uma string
$str = 'Isto ainda é um teste.';
$last = $str[strlen($str)-1];
var_dump($last);
// Modifica o último caractere de uma string
$str = 'Olhe para a onda';
$str[strlen($str)-1] = 'e';
var_dump($str);
?>
]]>
</programlisting>
</example>
<para>
Índices de strings devem ser inteiros ou strings parecidos com inteiros,
de outra forma um aviso é lançado.
</para>
<example>
<title>Exemplo de índices inválidos em strings</title>
<programlisting role="php">
<![CDATA[
<?php
$str = 'abc';
$keys = [ '1', '1.0', 'x', '1x' ];
foreach ($keys as $keyToTry) {
var_dump(isset($str[$keyToTry]));
try {
var_dump($str[$keyToTry]);
} catch (TypeError $e) {
echo $e->getMessage(), PHP_EOL;
}
echo PHP_EOL;
}
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
bool(true)
string(1) "b"
bool(false)
Cannot access offset of type string on string
bool(false)
Cannot access offset of type string on string
bool(false)
Warning: Illegal string offset "1x" in Standard input code on line 10
string(1) "b"
]]>
</screen>
</example>
<note>
<para>
Acessar variáveis de outros tipos (excluindo-se arrays ou objetos que
implementem certas interfaces) usando <literal>[]</literal> ou
<literal>{}</literal> silenciosamente retornará &null;.
</para>
</note>
<note>
<para>
Caracteres dentro de strings literais podem ser acessados
utilizando <literal>[]</literal> ou <literal>{}</literal>.
</para>
</note>
<note>
<para>
Acessar caracteres em strings utilizando a sintax por
<literal>{}</literal> foi descontinuada desde o PHP 7.4,
e não existe no PHP 8.0.
</para>
</note>
</sect3>
</sect2><!-- end syntax -->
<sect2 xml:id="language.types.string.useful-funcs">
<title>Funções e operadores úteis</title>
<para>
<type>String</type>s podem ser concatenadas utilizando o operador '.' (ponto). Note
que o operador '+' (adição) <emphasis>não</emphasis> funciona para isso.
Veja <link linkend="language.operators.string">operadores de string</link> para
mais informações.
</para>
<para>
Há bastantes funções úteis para manipulação de <type>string</type>s.
</para>
<simpara>
Veja a <link linkend="ref.strings">seção de funções de string</link> para
funções gerais e <link linkend="ref.pcre">funções de expressões regulares compatíveis com Perl</link>
para funcionalidades avançadas de localização &amp; e substituição.
</simpara>
<simpara>
Há também <link linkend="ref.url">funções para strings URL</link> e
funções para criptografia/descriptografia de strings
(<link linkend="ref.sodium">Sodium</link> e
<link linkend="ref.hash">Hash</link>).
</simpara>
<simpara>
Finalmente, veja também as <link linkend="ref.ctype">funções de tipos de
caracteres</link>.
</simpara>
</sect2>
<sect2 xml:id="language.types.string.casting">
<title>Conversão em strings</title>
<para>
Um valor pode ser convertido em uma <type>string</type> utilizando o modificador
<literal>(string)</literal> ou a função <function>strval</function>.
A conversão em <type>string</type> é automaticamente realizada no escopo de uma
expressão onde uma <type>string</type> é necessária. Isto acontece no uso das funções
<function>echo</function> ou <function>print</function> ou quando
o valor de uma variável é comparado com uma <type>string</type>. As seções <link
linkend="language.types">Tipos</link> e <link
linkend="language.types.type-juggling">Conversão de Tipos</link> tornarão
um pouco mais claro o assunto. Veja também a função <function>settype</function>.
</para>
<para>
O valor <type>bool</type> &true; é convertido para a <type>string</type>
<literal>"1"</literal>. O <type>bool</type> &false; é convertido para
<literal>""</literal> (uma string vazia). Isso permite converter nos dois
sentidos entre os valores <type>bool</type> e <type>string</type>.
</para>
<para>
Um <type>int</type> ou um <type>float</type> é convertido para uma
<type>string</type> representando o número textualmente (incluindo a parte
do expoente nos <type>float</type>s). Números de ponto flutuante podem ser
convertidos usando a notação exponencial (<literal>4.1E+6</literal>).
</para>
<note>
<para>
A partir do PHP 8.0.0, o caractere de ponto decimal sempre é
um ponto ("<literal>.</literal>"). Anteriormente ao PHP 8.0.0,
o ponto decimal era definido pelo locale do script
(LC_NUMERIC). Veja mais detalhes na função <function>setlocale</function>.
</para>
</note>
<para>
<type>Array</type>s são sempre convertidos para uma <type>string</type>
<literal>"Array"</literal>; por isso <function>echo</function> e
<function>print</function> não podem, por si só, mostrar o conteúdo de um
<type>array</type>. Para visualizar um único elemento, use uma construção como
<literal>echo $arr['foo']</literal>. Veja abaixo dicas de como visualizar todo seu
conteúdo.
</para>
<para>
Para converter <type>object</type>s em <type>string</type>s, o método
mágico <link linkend="language.oop5.magic">__toString</link> deve ser usado.
</para>
<para>
<type>Resource</type>s são sempre convertidos para <type>string</type>s na
estrutura <literal>"Resource id #1"</literal> onde <literal>1</literal> é
o número único do <type>resource</type> atribuído pelo PHP
em tempo de execução. Apesar de que a estrutura exata desta string não seja confiável
e esteja sujeita a modificações, será sempre única a um dado recurso
dentro do ciclo de vida de um script sendo executado (por exemplo, em uma requisição Web ou em um processo
CLI) e não será reutilizada. Para obter o tipo de um <type>resource</type>, utilize
a função <function>get_resource_type</function>.
</para>
<para>
&null; é sempre convertido para uma string vazia.
</para>
<para>
Como declarado acima, converter diretamente um <type>array</type>,
<type>object</type> ou <type>resource</type> para uma <type>string</type> não
fornece nenhuma informação útil sobre o valor, a não ser seu tipo. Veja as
funções <function>print_r</function> e <function>var_dump</function>
para maneiras mais efetivas de inspecionar o conteúdo destes tipos.
</para>
<para>
A maioria dos valores no PHP também podem ser convertidos em <type>string</type>s para armazenamento
permanente. Este método é chamado de serialização e pode ser feito com a função
<function>serialize</function>.
</para>
</sect2>
<sect2 xml:id="language.types.string.details">
<title>Detalhes do tipo string</title>
<para>
A <type>string</type> no PHP é implementada como um array de bytes e um
inteiro indicando seu tamanho no buffer. Não existem informações de como
esses bytes são traduzidos em caracteres, ficando essa tarefa com o programador.
Não existem limitações sobre a composição dos valores da string; em
particular, bytes com valor <literal>0</literal> (“NUL bytes”) são permitidos
em qualquer lugar da string (entretanto, algumas funções, mencionadas neste manual como não
“binary safe”, podem repassar as strings para bibliotecas que ignorem os dados
após o byte nulo.)
</para>
<para>
Esta natureza do tipo string explica o motivo de não haver o tipo "byte" disponível
no PHP as strings assumem este papel. Funções que não retornam nenhuma informação textual por
exemplo, dados arbitrários lidos de um socket de rede continuarão retornando
strings.
</para>
<para>
Dado que o PHP não dita uma codificação específica para strings, pode-se
questionar como strings literais seriam codificadas. Por exemplo, a string
<literal>"á"</literal> é equivalente a <literal>"\xE1"</literal> (ISO-8859-1),
<literal>"\xC3\xA1"</literal> (UTF-8, C form),
<literal>"\x61\xCC\x81"</literal> (UTF-8, D form) ou qualquer outra representação
possível? A resposta é que a string poderá ser codificada em qualquer forma
que o arquivo de script estiver codificado. Assim, se o script for escrito na
codificação ISO-8859-1, a string será codificada como ISO-8859-1 e assim por diante. Entretanto,
isso não se aplica se o Zend Multibyte estiver ativado; neste caso, o script
pode ser escrito em uma codificação arbitrária (que é declarada explicitamente ou é
detectada) e então convertida em um codificação interna, a qual
será a codificação utilizada nas strings literais.
Note que há algumas restrições na codificação do script (ou na
codificação interna caso o Zend Multibyte esteja ativo) isso quase sempre
significa que essa codificação deve ser um conjunto que contenha dentro de si a ASCII, como
UTF-8 ou ISO-8859-1. Note, entretanto, que codificações que são dependentes de estado, onde
os mesmos valores de bytes possam ser utilizados tanto em estados iniciais quanto não iniciais,
podem ser problemáticos.
</para>
<para>
Claro que, para serem úteis, funções que operam em textos podem ter que
fazer certas suposições sobre como as strings foram codificadas. Infelizmente, existem
muitas variações sobre este assunto através das funções do PHP:
</para>
<itemizedlist>
<listitem>
<simpara>
Algumas funções assumem que a string foi codificada em alguma (qualquer) codificação de byte
único, mas elas não precisam interpretar estes bytes como caracteres
específicos. Este é por exemplo o caso das funções <function>substr</function>,
<function>strpos</function>, <function>strlen</function> ou
<function>strcmp</function>. Outra forma de refletir sobre essas funções é
que elas operam em buffers de memória, isto é, elas trabalham com bytes e deslocamento
de bytes.
</simpara>
</listitem>
<listitem>
<simpara>
Outras funções recebem a codificação da string, possivelmente elas
assumem um padrão se nenhuma informação lhes for passada. Este é o caso da função
<function>htmlentities</function> e da maioria das funções
da extensão <link linkend="book.mbstring">mbstring</link>.
</simpara>
</listitem>
<listitem>
<simpara>
Outras utilizam o idioma atual (veja <function>setlocale</function>), mas
elas operam byte-a-byte.
</simpara>
</listitem>
<listitem>
<simpara>
Finalmente, elas podem simplesmente assumir que a string esteja utilizando uma codificação específica,
geralmente UTF-8. Este é o caso da maioria das funções das extensões
<link linkend="book.intl">intl</link> e
<link linkend="book.pcre">PCRE</link>
(na segunda, somente quando o modificador <literal>u</literal> é utilizado).
</simpara>
</listitem>
</itemizedlist>
<para>
Por fim, isso significa que escrever programas corretos utilizando Unicode depende de
evitar cuidadosamente funções que não funcionam e que provavelmente
irão corromper os dados e usar, em substituição, funções que se comportem corretamente,
geralmente das extensões <link linkend="book.intl">intl</link> e
<link linkend="book.mbstring">mbstring</link>.
Entretanto, usar funções que manipulam codificação Unicode é somente o
começo. Não importa as funções que a linguagem provê, é essencial
saber a especificação Unicode. Por exemplo, um programa que supõem que só
existem minúsculas e mínusculas está fazendo uma suposição errada.
</para>
</sect2>
</sect1><!-- end string -->
<!-- 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
-->