PHP Operadores de Atribuição
Você já usa um operador de atribuição desde a primeira aula: o =, que guarda um valor numa variável. Mas um programa vive atualizando variáveis: o total do carrinho cresce a cada produto, o estoque diminui a cada venda, a mensagem ganha mais uma linha. Para isso, o PHP tem atalhos como += ("some a isto") e .= ("acrescente este texto"). Nesta aula você aprende todos eles, o ??= para valores padrão e a ideia das referências (&).
- Como o
=funciona por dentro (e por que$a = $b = 0funciona). - Os atalhos
+=,-=,*=,/=,%=e**=. - O
.=, para ir montando um texto aos pedaços. - O
??=, que só atribui se a variável fornullou não existir. - As armadilhas do
=+e do=dentro doif. - A ideia da atribuição por referência,
$b = &$a.
Os programas desta aula rodaram com o PHP 8.5 na máquina fictícia da Ana, na pasta ~/site. Os operadores das contas (+, *, %…) estão em Operadores Aritméticos.
A ideia: abreviações
Numa mensagem de celular, muita gente escreve "vc" em vez de "você": é a mesma palavra, só mais curta. Os operadores de atribuição combinados são abreviações. Em vez de escrever $total = $total + 5; (repetindo $total), você escreve $total += 5;. O resultado é idêntico.
1. O =, de novo, com mais detalhes
Lembre da aula de Variáveis: o = se lê "recebe". O PHP calcula tudo do lado direito e guarda o resultado na variável do lado esquerdo. Por isso, o lado esquerdo precisa ser uma variável:
$ cat invertido.php <?php 5 = $x; $ php invertido.php Parse error: syntax error, unexpected token "=" in /home/ana/site/invertido.php on line 2
Um detalhe que vai ser útil: a atribuição, além de guardar o valor, também devolve esse valor. É por isso que dá para escrever várias atribuições encadeadas:
<?php var_dump($x = 7); $a = $b = $c = 0; var_dump($a, $b, $c);
$ php encadeada.php int(7) « "$x = 7" guardou 7 em $x e devolveu 7 para o var_dump int(0) « $c = 0 devolveu 0, que foi para $b, que foi para $a int(0) int(0)
O encadeamento vai da direita para a esquerda: $a = ($b = ($c = 0)). É prático para zerar vários contadores de uma vez.
2. Os atalhos das contas
Cada operador aritmético tem a sua versão "com igual". A regra é sempre a mesma: $x OP= valor é o mesmo que $x = $x OP valor.
| Atalho | É o mesmo que | Leia como | Com $x = 10, fica |
|---|---|---|---|
$x += 5; | $x = $x + 5; | some 5 a $x | 15 |
$x -= 3; | $x = $x - 3; | tire 3 de $x | 7 |
$x *= 2; | $x = $x * 2; | multiplique $x por 2 | 20 |
$x /= 4; | $x = $x / 4; | divida $x por 4 | 2.5 |
$x %= 3; | $x = $x % 3; | fique com o resto de $x por 3 | 1 |
$x **= 2; | $x = $x ** 2; | eleve $x ao quadrado | 100 |
<?php $total = 10; $total += 5; echo $total, "\n"; $total -= 3; echo $total, "\n"; $total *= 2; echo $total, "\n"; $total /= 4; var_dump($total); $total **= 2; var_dump($total); $n = 17; $n %= 5; var_dump($n);
$ php atalhos.php 15 « 10 + 5 12 « 15 - 3 24 « 12 * 2 int(6) « 24 / 4: divisão exata, continua int int(36) « 6 ao quadrado int(2) « resto de 17 por 5
(Duas instruções na mesma linha, como $total += 5; echo $total, "\n";, são permitidas: o ; separa uma da outra. Aqui é só para a tabela ficar compacta.)
Esses atalhos aparecem em todo lugar onde algo "acumula": o total de um carrinho ($total += $preco;), a baixa no estoque ($estoque -= $vendidos;), um desconto ($preco *= 0.9;, que tira 10%).
Missão: monte o carrinho da Ana. Comece com $total = 0, some os três produtos (12.5, 4 e 3.5) usando += e depois dê 10% de desconto com *= 0.9. A saída deve ser Total: 18.
<?php $total = 0; // some os produtos com += // dê o desconto com *= echo "Total: $total\n";
<?php $total = 0; $total += 12.5; $total += 4; $total += 3.5; $total *= 0.9; echo "Total: $total\n";
3. .=: montar um texto aos pedaços
O ponto junta textos (aula Operadores de String), e o .= é o atalho de "acrescente no fim": $msg .= "!"; é o mesmo que $msg = $msg . "!";.
<?php $msg = "Olá"; $msg .= ", Ana"; $msg .= "!"; echo $msg, "\n";
$ php mensagem.php Olá, Ana!
É o jeito clássico de montar um e-mail, um relatório ou um pedaço de HTML linha por linha. Mais tarde, com laços (foreach), você vai usar .= para gerar uma lista inteira.
+= não junta texto
Quem vem de JavaScript costuma escrever += para acrescentar texto. Em PHP, o + é só para números:
$ cat juntar-errado.php
<?php
$nome = "Ana";
$nome += " Souza";
$ php juntar-errado.php
Fatal error: Uncaught TypeError: Unsupported operand types: string + string in /home/ana/site/juntar-errado.php:3
Stack trace:
#0 {main}
thrown in /home/ana/site/juntar-errado.php on line 3
Para texto, é sempre .=.
4. ??=: atribuir só se estiver vazio PHP 7.4+
O ??= é o atalho de "se não tiver valor, use este". Ele só atribui quando a variável é null ou nem existe; se já houver um valor, deixa como está. É o irmão do ??, explicado em ?? e ?->.
<?php $config = ["tema" => "escuro"]; $config["idioma"] ??= "pt-BR"; $config["tema"] ??= "claro"; print_r($config); $nome = null; $nome ??= "visitante"; echo $nome, "\n"; $vazio = ""; $vazio ??= "padrão"; var_dump($vazio);
$ php padrao.php
Array
(
[tema] => escuro « já tinha valor: ficou "escuro"
[idioma] => pt-BR « não existia: recebeu o padrão
)
visitante « era null: recebeu o padrão
string(0) "" « "" não é null: o ??= não mexeu
- $x ??= valor;
- É o mesmo que
$x = $x ?? valor;: "$xrecebe ele mesmo, ou o valor se for null". - Não dá Warning
- Mesmo que
$x(ou a chave do array) não exista. Por isso é tão usado para preencher configurações que faltam. - Só olha o null
"",0efalsesão valores: o??=não os troca (veja null).
5. A armadilha do = no if
Como a atribuição devolve o valor, ela "funciona" em lugares onde você queria uma comparação. O erro mais clássico da programação é escrever um igual só dentro do if:
<?php
$x = 3;
if ($x = 5) {
echo "x vale $x\n";
}
$ php armadilha.php x vale 5 « $x era 3! o "=" trocou o valor para 5, e 5 é verdadeiro
O if ($x = 5) não pergunta nada: ele guarda 5 em $x e usa o 5 como condição (5 é verdadeiro, aula Booleanos). O PHP não reclama. Para comparar, use === (três iguais): if ($x === 5). A diferença entre =, == e === está em Comparação (== e ===).
6. Atribuição por referência: & (só a ideia)
Normalmente, $b = $a; copia o valor: depois disso, mexer em uma não muda a outra. Com um & antes da variável da direita, o PHP faz outra coisa: $b = &$a; cria um segundo nome para a mesma caixa. Mexeu numa, mexeu na outra:
<?php $x = 1; $y = $x; $y = 5; echo "cópia: x=$x y=$y\n"; $a = 1; $b = &$a; $b = 5; echo "referência: a=$a b=$b\n"; $a = 9; echo "referência: a=$a b=$b\n";
$ php referencia.php cópia: x=1 y=5 « $y é uma caixa separada referência: a=5 b=5 « mudar $b mudou $a: é a mesma caixa referência: a=9 b=9 « e vice-versa
Pense numa caixa com duas etiquetas coladas: "a" e "b". Não importa por qual etiqueta você pega a caixa, o conteúdo é o mesmo. Um unset($b) arranca só a etiqueta "b"; a caixa e o $a continuam lá.
No dia a dia, você vai encontrar o & em dois lugares: no foreach que modifica os itens de um array (foreach ($precos as &$p), aula foreach) e em funções que alteram a variável recebida (aula Parâmetros). Fora disso, prefira as cópias: referências deixam o código mais difícil de acompanhar.
Quando dá errado
=+
$ cat invertido2.php <?php $total = 10; $total =+ 5; var_dump($total); $ php invertido2.php int(5) « era para ser 15!
O que significa: os sinais foram digitados na ordem errada. =+ 5 é lido como = +5: "receba mais-cinco". O PHP não reclama, porque é um código válido.
Como consertar: o sinal da conta vem antes do igual: +=, -=, *=, .=.
Warning: Undefined variable num += ou .=
$ php contador.php « $cont += 1; var_dump($cont); Warning: Undefined variable $cont in /home/ana/site/contador.php on line 2 int(1)
O que significa: $cont += 1 precisa ler o valor atual de $cont, que não existe.
Como consertar: dê um valor inicial antes: $cont = 0; (para textos, $msg = "";).
Fatal error: Uncaught TypeError: Unsupported operand types: string + string
O que significa: você usou += para juntar textos.
Como consertar: use .=.
if sempre entra (ou nunca entra)
O que significa: provavelmente há um = sozinho na condição: if ($x = 5) atribui em vez de comparar.
Como consertar: if ($x === 5).
Referência rápida
| Operador | Equivale a | Uso típico |
|---|---|---|
$x = v | — | guardar um valor |
$x += v | $x = $x + v | somar ao total |
$x -= v | $x = $x - v | baixar o estoque |
$x *= v | $x = $x * v | aplicar desconto ou juros |
$x /= v | $x = $x / v | dividir em partes |
$x %= v | $x = $x % v | "dar a volta" num contador |
$x **= v | $x = $x ** v | potência |
$x .= "t" | $x = $x . "t" | montar um texto |
$x ??= v | $x = $x ?? v | valor padrão 7.4+ |
$b = &$a | — | dois nomes para a mesma variável |
Exercícios
1. Baixa no estoque
Complete para tirar 2 unidades do estoque:
2. Acrescentar texto
Complete para acrescentar " Souza" no fim de $nome:
3. Depois de $x = 4; $x *= 3; $x -= 2;, quanto vale $x?
4. Com $tema = "";, o que $tema ??= "claro"; faz?
5. Com $a = 1; $b = &$a; $b = 7;, quanto vale $a?
Missão final: a lista de compras
Missão: monte o texto da lista de compras aos pedaços com .=, a partir de $lista = "Lista: ";, acrescentando "arroz", ", feijão" e ", café" (um .= para cada). A saída deve ser Lista: arroz, feijão, café.
<?php $lista = "Lista: "; echo $lista, "\n";
<?php $lista = "Lista: "; $lista .= "arroz"; $lista .= ", feijão"; $lista .= ", café"; echo $lista, "\n";
Resumo
=guarda o valor da direita na variável da esquerda e devolve esse valor (por isso$a = $b = 0funciona).$x OP= vé o atalho de$x = $x OP v:+=,-=,*=,/=,%=,**=..=acrescenta texto;+=com texto dáTypeError.??=atribui só se a variável for null ou não existir, sem Warning.- Cuidado com
=+(é "recebe mais-…") e com=dentro doif(use===). $b = &$adá um segundo nome à mesma variável; use pouco.