PHP Interpolação
Você já sabe juntar textos com o ponto: "Olá, " . $nome . "!". Funciona, mas cansa e é fácil esquecer um ponto ou um espaço. O PHP tem um atalho: escrever a variável dentro das aspas duplas, e ele troca pelo valor. Isso se chama interpolação.
- Por que
"Olá, $nome"funciona e'Olá, $nome'não. - Como o PHP descobre onde termina o nome da variável, e como as chaves
{$var}resolvem as dúvidas. - Arrays e objetos dentro do texto:
{$aluno['nome']}e{$aluna->nome}. - O que não é interpolado: contas, funções, constantes.
- Os erros reais e quando é melhor concatenar ou usar
sprintf.
A ideia: um formulário com lacunas
Pense num modelo de recado impresso: "Olá, ______! Sua nota foi ______." Você preenche as lacunas e entrega. Na interpolação, o texto entre aspas duplas é o modelo, e cada $variavel é uma lacuna que o PHP preenche com o valor no momento em que a linha roda.
A palavra vem do latim interpolare, "inserir no meio". Em inglês: string interpolation.
Só nas aspas duplas
<?php $nome = "Ana"; $idade = 29; echo "Olá, $nome! Você tem $idade anos.\n"; echo 'Olá, $nome!', "\n";
- "Olá, $nome! …"
- Aspas duplas: o PHP procura
$seguido de um nome e troca pelo valor da variável. O\ntambém vira uma quebra de linha. - 'Olá, $nome!'
- Aspas simples: o texto sai exatamente como está, com o cifrão e tudo. Nada é trocado.
$ php ola.php Olá, Ana! Você tem 29 anos. Olá, $nome! « aspas simples: literal
O número 29 virou texto automaticamente (veja Conversão de Tipos). As diferenças entre os dois tipos de aspas estão em Strings; aqui o foco é o que pode ir dentro das duplas.
Onde o nome da variável termina?
Quando o PHP vê um $ nas aspas duplas, ele lê o nome da variável enquanto houver letras, números ou _. O primeiro caractere diferente (espaço, ponto, vírgula, @, /, -, aspa…) encerra o nome.
<?php $nome = "Ana"; $total = 13.5; echo "Email: $nome@escola.com\n"; echo "Arquivo: $nome.txt\n"; echo "Pasta: /home/$nome/\n"; echo "$nome's notebook\n"; echo "R$ $total\n"; echo "Custa $5\n";
$ php fim-nome.php Email: Ana@escola.com « o @ encerrou o nome Arquivo: Ana.txt « o ponto também Pasta: /home/Ana/ Ana's notebook « a aspa simples também R$ 13.5 « "$ " (cifrão + espaço) não é variável: fica como está Custa $5 « nome de variável não pode começar com número: fica como está
O problema aparece quando a palavra seguinte gruda no nome. A Ana quer escrever "Anas" (o plural de brincadeira):
<?php
$nome = "Ana";
echo "Total: $nomes\n";
echo "Total: {$nome}s\n";
$ php grudado.php Warning: Undefined variable $nomes in /home/ana/php/grudado.php on line 3 Total: « $nomes não existe: vira texto vazio Total: Anas « com chaves: o nome acaba no }
O PHP leu $nomes inteiro, procurou essa variável, não achou, avisou com Warning e usou texto vazio. O programa continuou (é um aviso, não um erro fatal; veja Lendo Erros do PHP).
As chaves {$…}
Colocar a variável entre chaves marca exatamente onde ela começa e termina. É a forma "completa" da interpolação, e funciona para tudo que você vai ver nesta aula.
- {
- Abre. Precisa vir colado no
$:{$. - $nome
- A variável (ou um array, ou um objeto, como você vai ver).
- }
- Fecha. As chaves não aparecem na saída.
- s
- O texto que vem depois, grudado.
Se houver espaço entre { e $, as chaves viram texto comum:
<?php
$nome = "Ana";
echo "Com espaço: { $nome}\n";
echo "Sem dólar: {nome}\n";
$ php chaves.php
Com espaço: { Ana} « as chaves apareceram; só o $nome foi trocado
Sem dólar: {nome} « sem $, nada acontece
"${nome}": forma antiga, obsoleta PHP 8.2+
Códigos antigos usam o cifrão fora das chaves: "${nome}s". Ainda funciona, mas desde o PHP 8.2 gera um aviso:
$ php antigo.php
Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/ana/php/antigo.php on line 3
Total: Anas
"Usar ${var} em strings está obsoleto, use {$var}". Repare que o aviso aparece antes da saída: o PHP o detecta ao ler o arquivo, antes de rodar. Troque por {$nome}.
Missão: o programa deveria mostrar Comprei 3 maçãs, mas aparece um aviso e a fruta some. Rode, leia o Warning e corrija usando chaves (a variável continua sendo $fruta, no singular).
<?php $fruta = "maçã"; echo "Comprei 3 $frutas";
<?php
$fruta = "maçã";
echo "Comprei 3 {$fruta}s";
Arrays dentro do texto
Com arrays associativos (listas com "etiquetas", como "nome" e "nota"), existem duas formas que funcionam e uma que dá erro:
<?php
$aluno = ["nome" => "Bruno", "nota" => 8.5];
$frutas = ["maçã", "uva"];
echo "Aluno: {$aluno['nome']}, nota {$aluno['nota']}\n";
echo "Aluno: $aluno[nome], nota $aluno[nota]\n";
echo "Fruta: $frutas[0] e {$frutas[1]}\n";
$ php array.php Aluno: Bruno, nota 8.5 Aluno: Bruno, nota 8.5 Fruta: maçã e uva
| Forma | Funciona? | Comentário |
|---|---|---|
"{$aluno['nome']}" | Sim | A recomendada. Dentro das chaves, você escreve exatamente como escreveria fora das aspas. |
"$aluno[nome]" | Sim | Forma curta: sem aspas na chave. Só vale dentro de aspas duplas e só para um nível. |
"$aluno['nome']" | Não | Parse error (veja abaixo). |
"$frutas[0]" | Sim | Índices numéricos funcionam nas duas formas. |
A forma curta $aluno[nome] confunde, porque fora das aspas $aluno[nome] (sem aspas na chave) é um erro. Por isso, a recomendação é simples: array dentro do texto, sempre com chaves.
Arrays dentro de arrays
Para mais de um nível, só as chaves funcionam:
<?php
$turma = ["alunos" => [["nome" => "Bruno"]]];
echo "Primeiro: {$turma['alunos'][0]['nome']}\n";
echo "Primeiro: $turma[alunos][0][nome]\n";
$ php turma.php Primeiro: Bruno Warning: Array to string conversion in /home/ana/php/turma.php on line 4 Primeiro: Array[0][nome]
Na segunda linha, a forma curta só leu $turma[alunos] (que é um array) e tratou [0][nome] como texto comum. Um array inteiro não pode virar texto: o PHP avisa "conversão de array para string" e escreve a palavra Array. (Arrays dentro de arrays são o assunto de Arrays Multidimensionais.)
Missão: usando o array $aluno e a forma com chaves ({$aluno['…']}), mostre Bruno tirou 8.5 em Matemática.
<?php $aluno = ["nome" => "Bruno", "nota" => 8.5, "materia" => "Matemática"]; echo "nome tirou nota em materia";
<?php
$aluno = ["nome" => "Bruno", "nota" => 8.5, "materia" => "Matemática"];
echo "{$aluno['nome']} tirou {$aluno['nota']} em {$aluno['materia']}";
Objetos dentro do texto
Um objeto é parecido com um array associativo, mas os dados (as propriedades) são acessados com a setinha ->. Você vai criar os seus em Classes e Objetos; aqui usamos o objeto "genérico" do PHP, o stdClass, só para ver a interpolação.
<?php
$aluna = new stdClass();
$aluna->nome = "Ana";
$aluna->cidade = "Recife";
echo "Professora: $aluna->nome, de $aluna->cidade\n";
echo "Professora: {$aluna->nome}\n";
$ php objeto.php Professora: Ana, de Recife Professora: Ana
Como nos arrays, a forma sem chaves só vai um nível. Se a propriedade for outro objeto ($aluna->endereco->cidade), ou se você quiser chamar um método ($aluna->apresentar()), use chaves: "{$aluna->endereco->cidade}", "{$aluna->apresentar()}". Sem chaves, o PHP para no primeiro nível e tenta transformar o objeto inteiro em texto, o que dá erro fatal:
$ php objeto2.php
Fatal error: Uncaught Error: Object of class stdClass could not be converted to string in /home/ana/php/objeto2.php:6
Stack trace:
#0 {main}
thrown in /home/ana/php/objeto2.php on line 6
O que não é interpolado
A interpolação troca variáveis. Ela não faz contas, não chama funções soltas e não conhece constantes:
<?php
const ESCOLA = "Escola Sol";
$preco = 4.5;
$qtd = 3;
echo "Escola: ESCOLA\n";
echo "Nome: {strtoupper('ana')}\n";
echo "Total: $preco * $qtd\n";
echo "Total: " . $preco * $qtd . "\n";
$ php nao.php
Escola: ESCOLA « constante: fica o nome, literal
Nome: {strtoupper('ana')} « { sem $ logo depois: texto comum
Total: 4.5 * 3 « trocou as variáveis, mas a conta não foi feita
Total: 13.5 « fora das aspas, com concatenação, a conta funciona
E se você tentar fazer a conta dentro das chaves?
<?php
$qtd = 3;
echo "Total: {$qtd * 2}\n";
$ php conta.php Parse error: syntax error, unexpected token "*", expecting "->" or "?->" or "[" in /home/ana/php/conta.php on line 3
"Erro de sintaxe: * inesperado; esperava ->, ?-> ou [". Dentro de {$…}, o PHP só aceita uma variável seguida de […] (array) ou -> (objeto). Faça a conta antes, numa variável ($total = $qtd * 2;), ou concatene.
Valores que viram texto de um jeito estranho
<?php $nada = null; $sim = true; $nao = false; $lista = [1, 2]; echo "null:[$nada] true:[$sim] false:[$nao]\n"; echo "Lista: $lista\n";
$ php tipos.php null:[] true:[1] false:[] Warning: Array to string conversion in /home/ana/php/tipos.php on line 7 Lista: Array
null e false viram texto vazio; true vira "1". Um array inteiro vira a palavra Array, com aviso. Para mostrar uma lista, junte-a antes com implode (veja Funções de String).
Caracteres especiais nas aspas duplas
Além das variáveis, as aspas duplas entendem sequências de escape: uma barra invertida seguida de uma letra.
<?php
$nome = "Ana";
echo "Barra: \\ Aspas: \" Tab:[\t] Dólar: \$nome\n";
echo "Unicode: \u{e9} \u{1F600}\n";
$ php escapes.php Barra: \ Aspas: " Tab:[ ] Dólar: $nome Unicode: é 😀
| Escreva | Para obter |
|---|---|
\n | Quebra de linha |
\t | Tab |
\" | Aspa dupla dentro das aspas duplas |
\\ | Uma barra invertida |
\$ | Um cifrão literal (impede a interpolação) |
\u{e9} | Um caractere pelo código Unicode (é) |
Para escrever {$ literalmente, use {\$.
Interpolar, concatenar ou sprintf?
As três formas abaixo produzem a mesma frase:
<?php
$nome = "Ana";
$nota = 9.5;
echo "Aluna $nome tirou $nota.\n";
echo 'Aluna ' . $nome . ' tirou ' . $nota . ".\n";
echo sprintf("Aluna %s tirou %.1f.\n", $nome, $nota);
$ php formas.php Aluna Ana tirou 9.5. Aluna Ana tirou 9.5. Aluna Ana tirou 9.5.
| Situação | Prefira | Exemplo |
|---|---|---|
| Frase com variáveis simples | Interpolação | "Olá, $nome!" |
| Arrays, objetos ou texto grudado | Interpolação com chaves | "Nota: {$aluno['nota']}" |
| Contas ou chamadas de função | Concatenação | "Total: " . $preco * $qtd, "Nome: " . mb_strtoupper($nome) |
| Números com casas decimais fixas, zeros à esquerda, colunas | sprintf/printf | sprintf("%.2f", $preco) |
| Texto longo, várias linhas (HTML, e-mail) | Heredoc | veja Heredoc e Nowdoc |
| Texto fixo, sem variáveis | Aspas simples ou duplas | Tanto faz; muitos preferem simples para deixar claro que não há variáveis |
sprintf e printf têm uma aula só para eles: printf e sprintf.
Quando a variável vem do usuário (um formulário, por exemplo) e vai para uma página web, "<p>Olá, $nome</p>" é perigoso: se alguém digitar código HTML no nome, ele vai parar na página. Escape antes: $nome = htmlspecialchars($nome);. O porquê está em Escapar a Saída (XSS).
Quando dá errado
$ php grudado.php Warning: Undefined variable $nomes in /home/ana/php/grudado.php on line 3 Total:
O que significa: o PHP leu um nome de variável maior do que você queria, porque o texto seguinte estava grudado. A variável não existe e vira texto vazio.
Como consertar: "{$nome}s". Se o nome estava mesmo errado (um erro de digitação), corrija o nome.
<?php $aluno = ["nome" => "Bruno"]; echo "Aluno: $aluno['nome']\n";
$ php aspas-chave.php Parse error: syntax error, unexpected string content "", expecting "-" or identifier or variable or number in /home/ana/php/aspas-chave.php on line 3
O que significa: na forma curta (sem chaves), o PHP espera a chave do array sem aspas. As aspas simples confundiram a leitura. Parse error quer dizer que o PHP nem começou a rodar: o arquivo inteiro foi recusado.
Como consertar: "Aluno: {$aluno['nome']}". O mesmo vale para aspas duplas na chave ("$aluno["nome"]"), que dão unexpected double-quote mark.
$ php tipos.php null:[] true:[1] false:[] Warning: Array to string conversion in /home/ana/php/tipos.php on line 7 Lista: Array
O que significa: você colocou um array inteiro no texto (ou a forma curta parou no meio de um array dentro de array).
Como consertar: pegue um item ({$lista[0]}), junte com implode(", ", $lista) antes, ou use chaves para os vários níveis.
$nome em vez do valor
$ php ola.php Olá, Ana! Você tem 29 anos. Olá, $nome! « a segunda linha usa aspas simples
O que significa: o texto está entre aspas simples. Não é erro: o PHP fez o que foi pedido.
Como consertar: troque por aspas duplas, ou concatene: 'Olá, ' . $nome.
Referência
Dentro de "…" | Resultado | Observação |
|---|---|---|
$var | O valor | O nome vai até o primeiro caractere que não é letra, número ou _ |
{$var} | O valor | Delimita o nome: "{$nome}s" |
$arr[chave] / $arr[0] | Um item | Forma curta, um nível, chave sem aspas |
{$arr['chave']} | Um item | Recomendada; aceita vários níveis |
$obj->prop | Uma propriedade | Forma curta, um nível |
{$obj->a->b}, {$obj->metodo()} | Propriedade aninhada, método | Só com chaves |
${var} | O valor + Deprecated | Obsoleto desde o 8.2 |
CONSTANTE, funcao(), $a * $b | Não interpolados | Concatene |
\$, \", \\, \n, \t, \u{…} | Escapes | Só nas aspas duplas (e no heredoc) |
Exercícios
1. Texto grudado
Complete para mostrar Bom dia, Anas! sendo $nome = "Ana":
2. Item do array
Complete com a forma recomendada para mostrar a nota do aluno:
3. Com $fruta = "uva";, o que mostra echo 'Comprei $fruta';?
4. Com $qtd = 2;, o que mostra echo "Dobro: $qtd * 2";?
5. Qual destas linhas dá Parse error?
Missão final: na lojinha da Ana, mostre o recibo 3 x maçã = R$ 13.5 usando as variáveis (nada de escrever "maçã" ou "13.5" à mão). Lembre: a conta não é feita dentro das aspas. Calcule o total numa variável antes e use {$item['fruta']} para o nome.
<?php $item = ["fruta" => "maçã", "preco" => 4.5]; $qtd = 3; echo "$qtd x $item = R$ $qtd * $item";
<?php
$item = ["fruta" => "maçã", "preco" => 4.5];
$qtd = 3;
$total = $qtd * $item['preco'];
echo "$qtd x {$item['fruta']} = R$ $total";
Resumo
- Interpolação: nas aspas duplas,
$varé trocada pelo valor. Nas simples, não. - O nome da variável vai até o primeiro caractere que não é letra, número ou
_. Texto grudado? Use{$var}. - Arrays e objetos: prefira sempre as chaves,
{$aluno['nome']}e{$aluna->nome}. A forma curta só vai um nível e não aceita aspas na chave. "${var}"é obsoleto desde o PHP 8.2.- Contas, funções e constantes não são interpoladas: calcule antes, concatene ou use
sprintf. null/falseviram vazio,truevira1, array viraArraycom aviso.