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.

Você vai aprender
  • 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 \n també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
FormaFunciona?Comentário
"{$aluno['nome']}"SimA recomendada. Dentro das chaves, você escreve exatamente como escreveria fora das aspas.
"$aluno[nome]"SimForma curta: sem aspas na chave. Só vale dentro de aspas duplas e só para um nível.
"$aluno['nome']"NãoParse 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: é 😀
EscrevaPara obter
\nQuebra de linha
\tTab
\"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çãoPrefiraExemplo
Frase com variáveis simplesInterpolação"Olá, $nome!"
Arrays, objetos ou texto grudadoInterpolação com chaves"Nota: {$aluno['nota']}"
Contas ou chamadas de funçãoConcatenação"Total: " . $preco * $qtd, "Nome: " . mb_strtoupper($nome)
Números com casas decimais fixas, zeros à esquerda, colunassprintf/printfsprintf("%.2f", $preco)
Texto longo, várias linhas (HTML, e-mail)Heredocveja Heredoc e Nowdoc
Texto fixo, sem variáveisAspas simples ou duplasTanto 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.

Interpolação não protege contra HTML malicioso

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

Undefined variable $nomes
$ 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.

Parse error com aspas na chave do array
<?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.

Array to string conversion
$ 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.

A saída mostra $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 "…"ResultadoObservação
$varO valorO nome vai até o primeiro caractere que não é letra, número ou _
{$var}O valorDelimita o nome: "{$nome}s"
$arr[chave] / $arr[0]Um itemForma curta, um nível, chave sem aspas
{$arr['chave']}Um itemRecomendada; aceita vários níveis
$obj->propUma propriedadeForma curta, um nível
{$obj->a->b}, {$obj->metodo()}Propriedade aninhada, métodoSó com chaves
${var}O valor + DeprecatedObsoleto desde o 8.2
CONSTANTE, funcao(), $a * $bNão interpoladosConcatene
\$, \", \\, \n, \t, \u{…}EscapesSó nas aspas duplas (e no heredoc)

Exercícios

1. Texto grudado

Complete para mostrar Bom dia, Anas! sendo $nome = "Ana":

echo "Bom dia, s!";

2. Item do array

Complete com a forma recomendada para mostrar a nota do aluno:

echo "Nota: ";

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/false viram vazio, true vira 1, array vira Array com aviso.