PHP 7.4.0beta4 released!

Strings

Uma string é 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 detalhes do tipo string.

Nota: O tipo string possui o tamanho máximo de 2GB (máximo de 2147483647 bytes)

Sintaxe

Uma string literal pode ser especificada de quatro formas diferentes.

Aspas simples

A maneira mais simples de se especificar uma string é delimitá-la entre aspas simples (o caractere ').

Para especificar um apóstrofo, escape-o com uma contrabarra (\). Para especificar uma contrabarra literal, dobre-a (\\). 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 \r ou \n, serão literalmente impressas em vez de ter qualquer significado especial.

Nota: Diferentemente das sintaxes com aspas duplas e heredoc, variáveis e sequências de escape para caracteres especiais não serão expandidas quando ocorrerem dentro de uma string delimitada por aspas simples.

<?php
echo 'isto é uma string comum';

echo 
'Você pode incluir novas linhas em strings,
dessa maneira que estará
tudo bem'
;

// Imprime: Arnold disse uma vez: "I'll be back"
echo 'Arnold disse uma vez: "I\'ll be back"';

// Imprime: Você tem certeza em apagar C:\*.*?
echo 'Você tem certeza em apagar C:\\*.*?';

// Imprime: Você tem certeza em apagar C:\*.*?
echo 'Você tem certeza em apagar C:\*.*?';

// Imprime: Isto não será substituido: \n uma nova linha
echo 'Isto não será substituido: \n uma nova linha';

// Imprime: Variáveis $também não $expandem
echo 'Variáveis $também não $expandem';
?>

Aspas duplas

Se a string for delimitada entre aspas duplas ("), o PHP interpretará a seguinte sequência de escape como caracteres especiais:

Sequências de escape
Sequências Significado
\n fim de linha (LF ou 0x0A (10) em ASCII)
\r retorno de carro (CR ou 0x0D (13) em ASCII)
\t TAB horizontal (HT ou 0x09 (9) em ASCII)
\v TAB vertical (VT ou 0x0B (11) em ASCII) (desde o PHP 5.2.5)
\e escape (ESC or 0x1B (27) em ASCII) (desde o PHP 5.4.4)
\f form feed (FF ou 0x0C (12) em ASCII) (desde o PHP 5.2.5)
\\ contrabarra ou barra invertida
\$ sinal de cifrão
\" aspas duplas
\[0-7]{1,3} a sequência de caracteres correspondente a expressão regular é um caractere em notação octal, que silenciosamente é extravasada para caber em um byte (e.g. "\400" === "\000")
\x[0-9A-Fa-f]{1,2} a sequência de caracteres correspondente a expressão regular é um caractere em notação hexadecimal
\u{[0-9A-Fa-f]+} a sequência de caracteres correspondente a expressão regular é um código Unicode, que será impresso como uma string que representa um código UTF-8 (adicionado no PHP 7.0.0)

Como com as strings entre aspas simples, escapar qualquer outro caractere resultará em uma contrabarra sendo impressa. Em versões anteriores ao PHP 5.1.1, a contrabarra em \{$var} não era impressa.

O recurso mais importante de strings delimitadas por aspas duplas é o fato de que nomes de variáveis serão expandidos. Veja interpretação de strings para detalhes.

Heredoc

Uma terceira maneira de delimitar strings é a sintaxe heredoc: <<<. Após este operador, um identificador é fornecido seguido de uma nova linha. A própria string é colocada em seguida e a seguir o mesmo identificador novamente para fechar a string.

O identificador de fechamento precisa começar na primeira coluna da linha. Além disso, o identificador precisa seguir as mesmas regras de nomeação que qualquer outro rótulo no PHP: deve conter somente caracteres alfanuméricos e sublinhados, e precisa começar com um caractere não numérico ou sublinhado.

Aviso

É muito importante notar que a linha que contêm o identificador de fechamento não deve conter nenhum outro caractere, com exceção do ponto-e-vírgula (;). Isso significa que o identificador não deve ser indentado e não deve ter nenhum espaço ou tabulações antes ou depois do ponto-e-vírgula. Também é importante perceber que o primeiro caractere antes do identificador de fechamento deve ser uma nova linha como definido pelo sistema operacional local. Isso é, \n em sistemas UNIX, incluindo o MAC OS X. O identificador de fechamento também deve ser seguido por uma nova linha.

Se essa regra for quebrada e o identificador de fechamento não estiver "limpo", ele não será considerado um identificador de fechamento, e o PHP continuará procurando por um. Se um identificador de fechamento apropriado não for encontrado antes do final do arquivo atual, um erro de interpretação será lançado na última linha.

Heredocs não podem ser usados para inicializar propriedades de classes. Desde o PHP 5.3, esta limitação é válida somente para heredocs que contêm variáveis.

Exemplo #1 Exemplo inválido

<?php
class foo {
    public 
$bar = <<<EOT
bar
    EOT;
}
?>

Textos heredoc se comportam como strings 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 strings.

Exemplo #2 Exemplo de delimitação de strings heredoc

<?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 
foo()
    {
        
$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;
?>

O exemplo acima irá imprimir:

My name is "MyName". I am printing some Foo.
Now, I am printing some Bar2.
This should print a capital 'A': A

É possível também utilizar a sintaxe Heredoc para passar dados para argumentos de funções:

Exemplo #3 Exemplo de Heredoc em argumentos

<?php
var_dump
(array(<<<EOD
foobar!
EOD
));
?>

A partir do PHP 5.3.0, é possível inicializar variáveis estáticas e propriedades/constantes de classe utilizando a sintaxe heredoc:

Exemplo #4 Utilizando o Heredoc na inicialização de valores estáticos

<?php
// Static variables
function foo()
{
    static 
$bar = <<<LABEL
Nothing in here...
LABEL;
}

// Class properties/constants
class foo
{
    const 
BAR = <<<FOOBAR
Constant example
FOOBAR;

    public 
$baz = <<<FOOBAR
Property example
FOOBAR;
}
?>

A partir do PHP 5.3.0, o identificador de abertura do Heredoc pode ser opcionalmente delimitado por aspas duplas:

Exemplo #5 Usando aspas no Heredoc

<?php
echo <<<"FOOBAR"
Hello World!
FOOBAR;
?>

Nowdoc

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 nenhuma interpretação é feita 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 <![CDATA[ ]]>, assim é declarado um bloco de texto onde nada será analisado.

Um nowdoc é identificado com a mesma seqüência <<< usada para heredocs, mas o identificador precisa ficar entre aspas simples, e.g. <<<'EOT'. Todas as regras para identificadores heredoc também se aplicam para identificadores nowdoc, especialmente aquelas referentes a aparência do identificador de fechamento.

Exemplo #6 Exemplo de string em Nowdoc

<?php
$str 
= <<<'EOD'
Example of string
spanning multiple lines
using nowdoc syntax.
EOD;

/* Exemplo mais complexo, com variáveis. */
class foo
{
    public 
$foo;
    public 
$bar;

    function 
foo()
    {
        
$this->foo 'Foo';
        
$this->bar = array('Bar1''Bar2''Bar3');
    }
}

$foo = new foo();
$name 'MyName';

echo <<<'EOT'
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': \x41
EOT;
?>

O exemplo acima irá imprimir:

My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': \x41

Exemplo #7 Exemplo de dado estático

<?php
class foo {
    public 
$bar = <<<'EOT'
bar
EOT;
}
?>

Nota:

Suporte a Nowdoc foi adicionado no PHP 5.3.0.

Interpretação de variáveis

Quando uma string é especificada dentro de aspas duplas ou heredoc, as variáveis são interpretadas dentro delas.

Há dois tipos de sintaxe: uma simples e um complexa. A sintaxe simples é a mais comum e conveniente. Provê uma maneira de interpretar uma variável, o valor de um array ou uma propriedade de objeto em uma string com o mínimo de esforço.

A sintaxe complexa pode ser reconhecida pelas chaves envolvendo a expressão.

Sintaxe simples

Se um sinal de cifrão ($) for encontrado, o interpretador tentará obter tantos identificadores quantos forem possíveis para formar um nome de variável válido. Envolva o nome da variável com chaves para especificar explicitamente o fim do nome.

<?php
$juice 
"apple";

echo 
"He drank some $juice juice.".PHP_EOL;
// Invalid. "s" is a valid character for a variable name, but the variable is $juice.
echo "He drank some juice made of $juices.";
// Valid. Explicitly specify the end of the variable name by enclosing it in braces:
echo "He drank some juice made of ${juice}s."
?>

O exemplo acima irá imprimir:

He drank some apple juice.
He drank some juice made of .
He drank some juice made of apples.

Similarmente, um índice de array ou uma propriedade de um objeto podem ser interpretados. Com índices de arrays, o fechamento de colchetes (]) marca o final do índice. A mesma regra aplica-se a propriedade de objetos, assim como para variáveis simples.

Exemplo #8 Simple syntax example

<?php
$juices 
= array("apple""orange""koolaid1" => "purple");

echo 
"He drank some $juices[0] juice.".PHP_EOL;
echo 
"He drank some $juices[1] juice.".PHP_EOL;
echo 
"He drank some $juices[koolaid1] juice.".PHP_EOL;

class 
people {
    public 
$john "John Smith";
    public 
$jane "Jane Smith";
    public 
$robert "Robert Paulsen";

    public 
$smith "Smith";
}

$people = new people();

echo 
"$people->john drank some $juices[0] juice.".PHP_EOL;
echo 
"$people->john then said hello to $people->jane.".PHP_EOL;
echo 
"$people->john's wife greeted $people->robert.".PHP_EOL;
echo 
"$people->robert greeted the two $people->smiths."// Won't work
?>

O exemplo acima irá imprimir:

He drank some apple juice.
He drank some orange juice.
He drank some purple juice.
John Smith drank some apple juice.
John Smith then said hello to Jane Smith.
John Smith's wife greeted Robert Paulsen.
Robert Paulsen greeted the two .

Para qualquer coisa mais complexa, você deve utilizar a sintaxe complexa.

Sintaxe complexa (chaves)

Isto não é chamado sintaxe complexa porque a sintaxe é complexa, mas sim para utilização de expressões complexas.

Qualquer variável escalar, elemento de um array ou propriedade de um objeto com uma representação de uma string pode ser incluída com essa sintaxe. Simplesmente escreva a expressão da mesma forma como apareceria fora da string e então coloque-o entre { e }. Já que que { não pode escapado, esta sintaxe será somente reconhecida quando o $ seguir, imediatamente, o {. Use {\$ para obter um literal {$. Alguns exemplos para torná-lo claro:

<?php
// Show all errors
error_reporting(E_ALL);

$great 'fantastic';

// Won't work, outputs: This is { fantastic}
echo "This is { $great}";

// Works, outputs: This is fantastic
echo "This is {$great}";

// Works
echo "This square is {$square->width}00 centimeters broad.";


// Works, quoted keys only work using the curly brace syntax
echo "This works: {$arr['key']}";


// Works
echo "This works: {$arr[4][3]}";

// This is wrong for the same reason as $foo[bar] is wrong  outside a string.
// In other words, it will still work, but only because PHP first looks for a
// constant named foo; an error of level E_NOTICE (undefined constant) will be
// thrown.
echo "This is wrong: {$arr[foo][3]}";

// Works. When using multi-dimensional arrays, always use braces around arrays
// when inside of strings
echo "This works: {$arr['foo'][3]}";

// Works.
echo "This works: " $arr['foo'][3];

echo 
"This works too: {$obj->values[3]->name}";

echo 
"This is the value of the var named $name{${$name}}";

echo 
"This is the value of the var named by the return value of getName(): {${getName()}}";

echo 
"This is the value of the var named by the return value of \$object->getName(): {${$object->getName()}}";

// Won't work, outputs: This is the return value of getName(): {getName()}
echo "This is the return value of getName(): {getName()}";
?>

Também é possível acessar propriedades de classes usando variáveis que contêm strings utilizando esta sintaxe.

<?php
class foo {
    var 
$bar 'I am bar.';
}

$foo = new foo();
$bar 'bar';
$baz = array('foo''bar''baz''quux');
echo 
"{$foo->$bar}\n";
echo 
"{$foo->{$baz[1]}}\n";
?>

O exemplo acima irá imprimir:

I am bar.
I am bar.

Nota:

Funções, chamadas a métodos, variáveis estáticas de classe e constantes de classe dentro de {$} funcionam desde o PHP 5. Entretanto, o valor acessado deverá ser interpretado como o nome de uma variável no escopo em que a string está definida. Utilizar somente chaves ({}) não funcionará para acessar os valores de retorno de funções ou métodos nem os valores de constantes da classe ou variáveis estáticas da classe.

<?php
// Show all errors.
error_reporting(E_ALL);

class 
beers {
    const 
softdrink 'rootbeer';
    public static 
$ale 'ipa';
}

$rootbeer 'A & W';
$ipa 'Alexander Keith\'s';

// This works; outputs: I'd like an A & W
echo "I'd like an {${beers::softdrink}}\n";

// This works too; outputs: I'd like an Alexander Keith's
echo "I'd like an {${beers::$ale}}\n";
?>

Acesso e modificação da string por caractere

É possível acessar e modificar caracteres dentro de strings especificando a posição, baseada em zero, do caractere desejado na string usando de colchetes, parecido com arrays, por exemplo $str[42]. Imagine uma string como um array de caracteres. As funções substr() e substr_replace(), podem ser utilizadas quando se deseja extrair ou substituir mais que 1 caractere.

Nota: Strings também podem ser acessadas usando colchetes, como em $str{42}, com o mesmo propósito.

Aviso

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 E_NOTICE. Deslocamento negativo emite E_NOTICE na escrita e uma uma string vazia na leitura. Somente o primeiro caractere de uma string atribuída é usada. Atribuir uma string vazia atribui o byte NULL.

Aviso

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.

Exemplo #9 Alguns exemplos com strings

<?php
// Get the first character of a string
$str 'This is a test.';
$first $str[0];

// Get the third character of a string
$third $str[2];

// Get the last character of a string.
$str 'This is still a test.';
$last $str[strlen($str)-1];

// Modify the last character of a string
$str 'Look at the sea';
$str[strlen($str)-1] = 'e';

?>

A partir do PHP 5.4 o deslocamento de strings devem ser inteiros ou strings equivalentes a inteiros, caso contrário um erro do tipo warning será disparado. Anteriormente um deslocamento como "foo" era silenciosamente convertido em 0.

Exemplo #10 Diferenças entre o PHP 5.3 e PHP 5.4

<?php
$str 
'abc';

var_dump($str['1']);
var_dump(isset($str['1']));

var_dump($str['1.0']);
var_dump(isset($str['1.0']));

var_dump($str['x']);
var_dump(isset($str['x']));

var_dump($str['1x']);
var_dump(isset($str['1x']));
?>

O exemplo acima irá imprimir no PHP 5.3:

string(1) "b"
bool(true)
string(1) "b"
bool(true)
string(1) "a"
bool(true)
string(1) "b"
bool(true)

O exemplo acima irá imprimir no PHP 5.4:

string(1) "b"
bool(true)

Warning: Illegal string offset '1.0' in /tmp/t.php on line 7
string(1) "b"
bool(false)

Warning: Illegal string offset 'x' in /tmp/t.php on line 9
string(1) "a"
bool(false)
string(1) "b"
bool(false)

Nota:

Acessar variáveis de outros tipos (excluindo-se arrays ou objetos que implementem certas interfaces) usando [] ou {} silenciosamente retornará NULL.

Nota:

O PHP 5.5 adicionou o suporte ao acesso de caracteres dentro de strings literais utilizando [] or {}.

Funções e operadores úteis

Strings podem ser concatenadas utilizando o operador '.' (ponto). Note que o operador '+' (adição) não funciona para isso. Veja operadores de string para mais informações.

Há bastantes funções úteis para manipulação de strings.

Veja a seção de funções de string para funções gerais e as funções de expressões regulares ou as funções de expressões regulares compatíveis com Perl para funcionalidades avançadas de localização & e substituição.

Há também funções para strings URL e funções para criptografia/descriptografia de strings (mcrypt e mhash).

Finalmente, veja também as funções de tipos de caracteres.

˜Conversão em strings

Um valor pode ser convertido em uma string utilizando o modificador (string) ou a função strval(). A conversão em string é automaticamente realizada no escopo de uma expressão onde uma string é necessária. Isto acontece no uso das funções echo ou print ou quando o valor de uma variável é comparado com uma string. As seções Tipos e Conversão de Tipos tornarão um pouco mais claro o assunto. Veja também a função settype().

O valor boolean TRUE é convertido para a string "1". O boolean FALSE é convertido para "" (uma string vazia). Isso permite converter nos dois sentidos entre os valores booleano e string.

Um integer ou um float é convertido para uma string representando o número textualmente (incluindo a parte do expoente nos floats). Números de ponto flutuante podem ser convertidos usando a notação exponencial (4.1E+6).

Nota:

O caractere de ponto decimal é definido no código de idioma (locale) do script (categoria LC_NUMERIC). Veja a função setlocale().

Arrays são sempre convertidos para uma string "Array"; por isso echo e print não podem, por si só, mostrar o conteúdo de um array. Para visualizar um único elemento, use uma construção como echo $arr['foo']. Veja abaixo dicas de como visualizar todo seu conteúdo.

Objetos, no PHP 4, são sempre convertidos para a string "Object". Para imprimir os valores das propriedades do objeto para depuração, leia os parágrafos a seguir. Para obter o nome da classe utilize a função get_class(). A partir do PHP 5, o método __toString é usado quando aplicável.

Resources são sempre convertidos para strings na estrutura "Resource id #1" onde 1 é o número único do resource 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 numa requisição Web ou em um processo CLI) e não será reutilizada. Para obter o tipo de um recurso, utilize a função get_resource_type().

NULL é sempre convertido para uma string vazia.

Como declarado acima, converter diretamente um array, objeto ou recurso para uma string não fornece nenhuma informação útil sobre o valor, a não ser seu tipo. Veja as funções print_r() e var_dump() para maneiras mais efetivas de inspecionar o conteúdo destes tipos.

A maioria dos valores no PHP também podem ser convertidos em strings para armazenamento permanente. Este método é chamado de serialização e pode ser feito com a função serialize(). Se o PHP engine tiver sido compilado com suporte ao WDDX, os valores no PHP também poderão ser serializados como XML.

Conversão de strings para números

Quando uma string é interpretada como um valor numérico, o valor resultante e seu tipo é determinado como segue.

Se a string não conter nenhum dos caracteres '.', 'e', ou 'E' e o valor numérico encaixa-se dentro dos limites do tipo inteiro (definido pela constante PHP_INT_MAX), a string será avaliada como um inteiro. Em todos os outros casos será interpretada como um float.

O valor é obtido da porção inicial da string. Se a string começar com dados numéricos válidos, esse será o valor utilizado. Caso contrário, o valor será 0 (zero). Dados numéricos válidos são um sinal opcional, seguido de um ou mais dígitos (opcionalmente contendo um ponto decimal), seguido de um expoente, também opcional. O expoente é um 'e' ou 'E' seguido de um ou mais dígitos.

<?php
$foo 
"10.5";                // $foo is float (11.5)
$foo "-1.3e3";              // $foo is float (-1299)
$foo "bob-1.3e3";           // $foo is integer (1)
$foo "bob3";                // $foo is integer (1)
$foo "10 Small Pigs";       // $foo is integer (11)
$foo "10.2 Little Piggies"// $foo is float (14.2)
$foo "10.0 pigs " 1;          // $foo is float (11)
$foo "10.0 pigs " 1.0;        // $foo is float (11)
?>

Para mais informações sobre esta conversão, veja a página sobre strtod(3) no manual UNIX.

Para testar qualquer exemplo desta seção, copie-os e cole-os inserindo a linha a seguir para ver o que está acontecendo:

<?php
echo "\$foo==$foo; tipo " gettype ($foo) . "<br />\n";
?>

Não espere obter o código de um caractere na conversão para inteiro, como é feito em C. Use as funções ord() e chr() para converter entre código ASCII e os próprios caracteres.

Detalhes do tipo string

A string 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 0 (“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.)

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.

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 "á" é equivalente a "\xE1" (ISO-8859-1), "\xC3\xA1" (UTF-8, C form), "\x61\xCC\x81" (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.

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:

  • 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 substr(), strpos(), strlen() ou strcmp(). 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.
  • 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 htmlentities() e da maioria das funções da extensão mbstring.
  • Outras utilizam o idioma atual (veja setlocale()), mas elas operam byte-a-byte. Este é o caso das funções strcasecmp(), strtoupper() e ucfirst(). Isso significa que podem ser utilizadas somente em codificações de byte único, desde que a codificação corresponda com a definida pelo idioma. Por exemplo, strtoupper("á") pode retornar "Á" se o idioma estiver definido corretamente e á, se codificado como byte único. Se a string estiver codificada em UTF-8, o resultado correto não será retornado e a string resultante pode ou não ser corrompida, dependendo do idioma atual.
  • 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 intl e PCRE (na segunda, somente quando o modificador u é utilizado). Devido a seu propósito especial, as funções utf8_decode() assume a codificação UTF-8 e utf8_encode() assume a codificação ISO-8859-1.

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 intl e mbstring. Entretanto, usar funções que manipulam codificações 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 maiúsculas e mínusculas está fazendo uma suposição errada.

add a note add a note

User Contributed Notes 24 notes

up
249
John
2 years ago
I've been a PHP programmer for a decade, and I've always been using the "single-quoted literal" and "period-concatenation" method of string creation. But I wanted to answer the performance question once and for all, using sufficient numbers of iterations and a modern PHP version. For my test, I used:

php -v
PHP 7.0.12 (cli) (built: Oct 14 2016 09:56:59) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies

------ Results: -------

* 100 million iterations:

$outstr = 'literal' . $n . $data . $int . $data . $float . $n;
63608ms (34.7% slower)

$outstr = "literal$n$data$int$data$float$n";
47218ms (fastest)

$outstr =<<<EOS
literal$n$data$int$data$float$n
EOS;
47992ms (1.64% slower)

$outstr = sprintf('literal%s%s%d%s%f%s', $n, $data, $int, $data, $float, $n);
76629ms (62.3% slower)

$outstr = sprintf('literal%s%5$s%2$d%3$s%4$f%s', $n, $int, $data, $float, $data, $n);
96260ms (103.9% slower)

* 10 million iterations (test adapted to see which of the two fastest methods were faster at adding a newline; either the PHP_EOL literal, or the \n string expansion):

$outstr = 'literal' . $n . $data . $int . $data . $float . $n;
6228ms (reference for single-quoted without newline)

$outstr = "literal$n$data$int$data$float$n";
4653ms (reference for double-quoted without newline)

$outstr = 'literal' . $n . $data . $int . $data . $float . $n . PHP_EOL;
6630ms (35.3% slower than double-quoted with \n newline)

$outstr = "literal$n$data$int$data$float$n\n";
4899ms (fastest at newlines)

* 100 million iterations (a test intended to see which one of the two ${var} and {$var} double-quote styles is faster):

$outstr = 'literal' . $n . $data . $int . $data . $float . $n;
67048ms (38.2% slower)

$outstr = "literal$n$data$int$data$float$n";
49058ms (1.15% slower)

$outstr = "literal{$n}{$data}{$int}{$data}{$float}{$n}"
49221ms (1.49% slower)

$outstr = "literal${n}${data}${int}${data}${float}${n}"
48500ms (fastest; the differences are small but this held true across multiple runs of the test, and this was always the fastest variable encapsulation style)

* 1 BILLION iterations (testing a completely literal string with nothing to parse in it):

$outstr = 'literal string testing';
23852ms (fastest)

$outstr = "literal string testing";
24222ms (1.55% slower)

It blows my mind. The double-quoted strings "which look so $slow since they have to parse everything for \n backslashes and $dollar signs to do variable expansion", turned out to be the FASTEST string concatenation method in PHP - PERIOD!

Single-quotes are only faster if your string is completely literal (with nothing to parse in it and nothing to concatenate), but the margin is very tiny and doesn't matter.

So the "highest code performance" style rules are:

1. Always use double-quoted strings for concatenation.

2. Put your variables in "This is a {$variable} notation", because it's the fastest method which still allows complex expansions like "This {$var['foo']} is {$obj->awesome()}!". You cannot do that with the "${var}" style.

3. Feel free to use single-quoted strings for TOTALLY literal strings such as array keys/values, variable values, etc, since they are a TINY bit faster when you want literal non-parsed strings. But I had to do 1 billion iterations to find a 1.55% measurable difference. So the only real reason I'd consider using single-quoted strings for my literals is for code cleanliness, to make it super clear that the string is literal.

4. If you think another method such as sprintf() or 'this'.$var.'style' is more readable, and you don't care about maximizing performance, then feel free to use whatever concatenation method you prefer!
up
6
vseokdog at gmail dot com
2 months ago
Don't forget about new E_WARNING and E_NOTICE errors from PHP 7.1.x: they have been introduced when invalid strings are coerced using operators expecting numbers (+ - * / ** % << >> | & ^) or their assignment equivalents. An E_NOTICE is emitted when the string begins with a numeric value but contains trailing non-numeric characters, and an E_WARNING is emitted when the string does not contain a numeric value.

Example:
$foo = 1 + "bob-1.3e3"; 
$foo = "10.2 pigs " + 1.0;
Will produce: Warning: A non-numeric value encountered

Read more: https://www.php.net/manual/en/migration71.other-changes.php
up
87
gtisza at gmail dot com
7 years ago
The documentation does not mention, but a closing semicolon at the end of the heredoc is actually interpreted as a real semicolon, and as such, sometimes leads to syntax errors.

This works:

<?php
$foo
= <<<END
abcd
END;
?>

This does not:

<?php
foo
(<<<END
abcd
END;
);
// syntax error, unexpected ';'
?>

Without semicolon, it works fine:

<?php
foo
(<<<END
abcd
END
);
?>
up
7
Ray.Paseur sometimes uses Gmail
8 months ago
md5('240610708') == md5('QNKCDZO')

This comparison is true because both md5() hashes start '0e' so PHP type juggling understands these strings to be scientific notation.  By definition, zero raised to any power is zero.
up
20
garbage at iglou dot eu
3 years ago
You can use string like array of char (like C)

$a = "String array test";

var_dump($a);
// Return string(17) "String array test"

var_dump($a[0]);
// Return string(1) "S"

// -- With array cast --
var_dump((array) $a);
// Return array(1) { [0]=> string(17) "String array test"}

var_dump((array) $a[0]);
// Return string(17) "S"

- Norihiori
up
3
Hayley Watson
1 year ago
Any single expression, however complex, that starts with $ (i.e., a variable) can be {}-embedded in a double-quoted string:

<?php

echo "The expression {$h->q()["x}"]->p(9 == 0 ? 17 : 42)} gets parsed just as well as " . $h->q()["x}"]->p(9 == 0 ? 17 : 42) . " does.";

?>
up
4
jonijnm at example dot com
1 year ago
Both should work :(

<?php

class Testing {
    public static
$VAR = 'static';
    public const VAR =
'const';
   
    public function
sayHelloStatic() {
        echo
"hello: {$this::$VAR}";
    }
   
    public function
sayHelloConst() {
        echo
"hello: {$this::VAR}"; //Parse error:  syntax error, unexpected '}', expecting '['
   
}
}

$obj = new Testing();
$obj->sayHelloStatic();
$obj->sayHelloConst();
up
18
lelon at lelon dot net
14 years ago
You can use the complex syntax to put the value of both object properties AND object methods inside a string.  For example...
<?php
class Test {
    public
$one = 1;
    public function
two() {
        return
2;
    }
}
$test = new Test();
echo
"foo {$test->one} bar {$test->two()}";
?>
Will output "foo 1 bar 2".

However, you cannot do this for all values in your namespace.  Class constants and static properties/methods will not work because the complex syntax looks for the '$'.
<?php
class Test {
    const
ONE = 1;
}
echo
"foo {Test::ONE} bar";
?>
This will output "foo {Test::one} bar".  Constants and static properties require you to break up the string.
up
13
php at richardneill dot org
6 years ago
Leading zeroes in strings are (least-surprise) not treated as octal.
Consider:
  $x = "0123"  + 0;  
  $y = 0123 + 0;
  echo "x is $x, y is $y";    //prints  "x is 123, y is 83"
in other words:
* leading zeros in numeric literals in the source-code are interpreted as "octal", c.f. strtol().
* leading zeros in strings (eg user-submitted data), when cast (implicitly or explicitly) to integer are ignored, and considered as decimal, c.f. strtod().
up
14
og at gams dot at
12 years ago
easy transparent solution for using constants in the heredoc format:
DEFINE('TEST','TEST STRING');

$const = get_defined_constants();

echo <<<END
{$const['TEST']}
END;

Result:
TEST STRING
up
4
nospam at nospam dot com
2 years ago
Beware that consistent with "String conversion to numbers":

<?php

if ('123abc' == 123) echo '(intstr == int) incorrectly tests as true.';

// Because one side is a number, the string is incorrectly converted from intstr to int, which then matches the test number.

// True for all conditionals such as if and switch statements (probably also while loops)!

// This could be a huge security risk when testing/using/saving user input, while expecting and testing for only an integer.

// It seems the only fix is for 123 to be a string as '123' so no conversion happens.

?>
up
13
headden at karelia dot ru
10 years ago
Here is an easy hack to allow double-quoted strings and heredocs to contain arbitrary expressions in curly braces syntax, including constants and other function calls:

<?php

// Hack declaration
function _expr($v) { return $v; }
$_expr = '_expr';

// Our playground
define('qwe', 'asd');
define('zxc', 5);

$a=3;
$b=4;

function
c($a, $b) { return $a+$b; }

// Usage
echo "pre {$_expr(1+2)} post\n"; // outputs 'pre 3 post'
echo "pre {$_expr(qwe)} post\n"; // outputs 'pre asd post'
echo "pre {$_expr(c($a, $b)+zxc*2)} post\n"; // outputs 'pre 17 post'

// General syntax is {$_expr(...)}
?>
up
13
chAlx at findme dot if dot u dot need
10 years ago
To save Your mind don't read previous comments about dates  ;)

When both strings can be converted to the numerics (in ("$a" > "$b") test) then resulted numerics are used, else FULL strings are compared char-by-char:

<?php
var_dump
('1.22' > '01.23'); // bool(false)
var_dump('1.22.00' > '01.23.00'); // bool(true)
var_dump('1-22-00' > '01-23-00'); // bool(true)
var_dump((float)'1.22.00' > (float)'01.23.00'); // bool(false)
?>
up
4
mark at manngo dot net
2 years ago
I though that it would be helpful to add this comment so that the information at least appears on the right page on the PHP site.

Note that if you intend to use a double-quoted string with an associative key, you may run into the T_ENCAPSED_AND_WHITESPACE error. Some regard this as one of the less obvious error messages.

An expression such as:

<?php
    $fruit
=array(
       
'a'=>'apple',
       
'b'=>'banana',
       
//    etc
   
);

    print
"This is a $fruit['a']";    //    T_ENCAPSED_AND_WHITESPACE
?>

will definitely fall to pieces.

You can resolve it as follows:

<?php
   
print "This is a $fruit[a]";    //    unquote the key
   
print "This is a ${fruit['a']}";    //    Complex Syntax
   
print "This is a {$fruit['a']}";    //    Complex Syntax variation
?>

I have a personal preference for the last variation as it is more natural and closer to what the expression would be like outside the string.

It’s not clear (to me, at least) why PHP misinterprets the single quote inside the expression but I imagine that it has something to do with the fact quotes are not part of the value string — once the string is already being parsed the quotes just get in the way … ?
up
5
sideshowAnthony at googlemail dot com
3 years ago
Something I experienced which no doubt will help someone . . .
In my editor, this will syntax highlight HTML and the $comment:

$html = <<<"EOD"
<b>$comment</b>
EOD;

Using this shows all the same colour:

$html = <<<EOD
<b>$comment</b>
EOD;

making it a lot easier to work with
up
10
Richard Neill
12 years ago
Unlike bash, we can't do
  echo "\a"       #beep!

Of course, that would be rather meaningless for PHP/web, but it's useful for PHP-CLI. The solution is simple:  echo "\x07"
up
7
steve at mrclay dot org
10 years ago
Simple function to create human-readably escaped double-quoted strings for use in source code or when debugging strings with newlines/tabs/etc.

<?php
function doubleQuote($str) {
   
$ret = '"';
    for (
$i = 0, $l = strlen($str); $i < $l; ++$i) {
       
$o = ord($str[$i]);
        if (
$o < 31 || $o > 126) {
            switch (
$o) {
                case
9: $ret .= '\t'; break;
                case
10: $ret .= '\n'; break;
                case
11: $ret .= '\v'; break;
                case
12: $ret .= '\f'; break;
                case
13: $ret .= '\r'; break;
                default:
$ret .= '\x' . str_pad(dechex($o), 2, '0', STR_PAD_LEFT);
            }
        } else {
            switch (
$o) {
                case
36: $ret .= '\$'; break;
                case
34: $ret .= '\"'; break;
                case
92: $ret .= '\\\\'; break;
                default:
$ret .= $str[$i];
            }
        }
    }
    return
$ret . '"';
}
?>
up
3
necrodust44 at gmail dot com
5 years ago
String conversion to numbers.

Unfortunately, the documentation is not correct.

«The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero).»

It is not said and is not shown in examples throughout the documentation that, while converting strings to numbers, leading space characters are ignored, like with the strtod function.

<?php
   
echo "     \v\f    \r   1234" + 1;    // 1235
   
var_export ("\v\f    \r   1234" == "1234");    // true
?>

However, PHP's behaviour differs even from the strtod's. The documentation says that if the string contains a "e" or "E" character, it will be parsed as a float, and suggests to see the manual for strtod for more information. The manual says

«A hexadecimal number consists of a "0x" or "0X" followed by a nonempty sequence of hexadecimal digits possibly containing a radix character, optionally followed by a binary exponent.  A binary exponent consists of a 'P' or 'p', followed by an optional plus or minus sign, followed by a nonempty sequence of decimal digits, and indicates multiplication by a power of 2.»

But it seems that PHP does not recognise the exponent or the radix character.

<?php
   
echo "0xEp4" + 1;     // 15
?>

strtod also uses the current locale to choose the radix character, but PHP ignores the locale, and the radix character is always 2E. However, PHP uses the locale while converting numbers to strings.

With strtod, the current locale is also used to choose the space characters, I don't know about PHP.
up
2
cvolny at gmail dot com
10 years ago
I commented on a php bug feature request for a string expansion function and figured I should post somewhere it might be useful:

using regex, pretty straightforward:
<?php
function stringExpand($subject, array $vars) {
   
// loop over $vars map
   
foreach ($vars as $name => $value) {
       
// use preg_replace to match ${`$name`} or $`$name`
       
$subject = preg_replace(sprintf('/\$\{?%s\}?/', $name), $value,
$subject);
    }
   
// return variable expanded string
   
return $subject;
}
?>

using eval() and not limiting access to only certain variables (entire current symbol table including [super]globals):

<?php
function stringExpandDangerous($subject, array $vars = array(), $random = true) {
   
       
// extract $vars into current symbol table
       
extract($vars);
       
       
$delim;
       
// if requested to be random (default), generate delim, otherwise use predefined (trivially faster)
       
if ($random)
           
$delim = '___' . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . '___';
        else
           
$delim = '__ASDFZXCV1324ZXCV__'// button mashing...
       
        // built the eval code
       
$statement = "return <<<$delim\n\n" . $subject . "\n$delim;\n";
       
       
// execute statement, saving output to $result variable
       
$result = eval($statement);
       
       
// if eval() returned FALSE, throw a custom exception
       
if ($result === false)
            throw new
EvalException($statement);
       
       
// return variable expanded string
       
return $result;
    }
?>

I hope that helps someone, but I do caution against using the eval() route even if it is tempting.  I don't know if there's ever a truely safe way to use eval() on the web, I'd rather not use it.
up
3
atnak at chejz dot com
15 years ago
Here is a possible gotcha related to oddness involved with accessing strings by character past the end of the string:

$string = 'a';

var_dump($string[2]);  // string(0) ""
var_dump($string[7]);  // string(0) ""
$string[7] === '';  // TRUE

It appears that anything past the end of the string gives an empty string..  However, when E_NOTICE is on, the above examples will throw the message:

Notice:  Uninitialized string offset:  N in FILE on line LINE

This message cannot be specifically masked with @$string[7], as is possible when $string itself is unset.

isset($string[7]);  // FALSE
$string[7] === NULL;  // FALSE

Even though it seems like a not-NULL value of type string, it is still considered unset.
up
1
webmaster at rephunter dot net
13 years ago
Use caution when you need white space at the end of a heredoc. Not only is the mandatory final newline before the terminating symbol stripped, but an immediately preceding newline or space character is also stripped.

For example, in the following, the final space character (indicated by \s -- that is, the "\s" is not literally in the text, but is only used to indicate the space character) is stripped:

$string = <<<EOT
this is a string with a terminating space\s
EOT;

In the following, there will only be a single newline at the end of the string, even though two are shown in the text:

$string = <<<EOT
this is a string that must be
followed by a single newline

EOT;
up
-1
shd at earthling dot net
9 years ago
If you want a parsed variable surrounded by curly braces, just double the curly braces:

<?php
  $foo
= "bar";
  echo
"{{$foo}}";
?>

will just show {bar}. The { is special only if followed by the $ sign and matches one }. In this case, that applies only to the inner braces. The outer ones are not escaped and pass through directly.
up
0
bishop
13 years ago
You may use heredoc syntax to comment out large blocks of code, as follows:
<?php
<<<_EOC
    // end-of-line comment will be masked... so will regular PHP:
    echo (
$test == 'foo' ? 'bar' : 'baz');
    /* c-style comment will be masked, as will other heredocs (not using the same marker) */
    echo <<<EOHTML
This is text you'll never see!       
EOHTML;
    function defintion(
$params) {
        echo 'foo';
    }
    class definition extends nothing     {
       function definition(
$param) {
          echo 'do nothing';
       }      
    }

    how about syntax errors?; = gone, I bet.
_EOC;
?>

Useful for debugging when C-style just won't do.  Also useful if you wish to embed Perl-like Plain Old Documentation; extraction between POD markers is left as an exercise for the reader.

Note there is a performance penalty for this method, as PHP must still parse and variable substitute the string.
up
-4
rkfranklin+php at gmail dot com
11 years ago
If you want to use a variable in an array index within a double quoted string you have to realize that when you put the curly braces around the array, everything inside the curly braces gets evaluated as if it were outside a string.  Here are some examples:

<?php
$i
= 0;
$myArray[Person0] = Bob;
$myArray[Person1] = George;

// prints Bob (the ++ is used to emphasize that the expression inside the {} is really being evaluated.)
echo "{$myArray['Person'.$i++]}<br>";

// these print George
echo "{$myArray['Person'.$i]}<br>";
echo
"{$myArray["Person{$i}"]}<br>";

// These don't work
echo "{$myArray['Person$i']}<br>";
echo
"{$myArray['Person'$i]}<br>";

// These both throw fatal errors
// echo "$myArray[Person$i]<br>";
//echo "$myArray[Person{$i}]<br>";
?>
To Top