PHP para Iniciantes: Operadores de Atribuição

A finalidade de todos os operadores que veremos nesse artigo é o que diz no título: atribuir algo a alguma coisa. Seja um tipo de dado primitivo em uma variável ou constante, uma constante em uma variável, uma expressão em (...), enfim, há algumas possibilidades sobre o que pode ser atribuído e o que pode receber a atribuição.

Na verdade, o que pode receber essa atribuição é somente variável, referência, propriedade de classe e/ou constante, o que deixa a primeira preocupação bem mais suave. Já os dados, eu gosto de pensar que tudo é expressão, porque o operador de atribuição pode ser casado com outro operador. Vamos lá?

Atribuição simples

Nas aulas de matemática da escola, é comum encontrar contas similares a X = 1 + 5, que leva a X = 6, e pensarmos que esse símbolo é um simbolo de atribuição. Não é!

Na matemática, o = representa somente igualdade ou equilíbrio. É literalmente dizer que o lado esquerdo da equação precisa ter o mesmo valor que o lado direito para ser uma conta válida. Nada está sendo atribuído. Essa sensação é uma ilusão da sua mente, pois desde o início X já era igual a 6. Você apenas simplificou a equação para enxergar com mais clareza.

Entender isso é essencial para que saiba que, no PHP, o = não serve para comparar lados de uma equação ou formar quaisquer equilíbrios. Ele somente atribui.

Então se você encontra uma equação um pouco mais complexa, como A + 2B = 44C - 34D, a sensação de equilíbrio pode ficar mais evidente. Porém, como seria essa conta em PHP?

Se você pensou em $a + 2 * $b = 44 * $c - 34 * $d, está redondamente enganado. O PHP não fará disso um equilíbrio, e sim irá atribuir alguma coisa do lado direto (44 * $c - 34 * $d) ao lado esquerdo ($a + 2 *$b), trocando o valor prévio de alguma dessas variáveis. Ele não vai tentar descobrir valores baseado em equilíbrio, com seria na matemática. Esse é o ponto.

Se você deseja testar um equilíbrio, você precisa usar os operadores de comparação == ou ===. Aí sim, ambos os lados precisam ter o mesmo valor. Ainda assim, não será papel do interpretador descobrir valores, ele apenas verificará se, dado os valores existentes nas variáveis, cada lado está resultando na mesma conclusão. Se um valor for nulo, irá apenas prejudicar a conta toda.

Kiko, você falou sobre atribuição mesclada com outros operadores... O que seria isso?

Ah, sim! São formas curtas de fazer uma auto-atribuição.

Como assim?!

Sempre que você tiver uma atribuição onde a variável que vai receber o dado é utilizada na operação, sendo apenas uma operação, você pode encontrar uma forma reduzida de fazer o que está sendo feito. Ok, nem toda operação dá pra ser minimizada, é preciso checar se o operador tem sua versão com atribuição.

Enfim, vamos aos exemplos:

<?php

$a = 100;

$a = $a + 3;
// é o mesmo que
$a += 3;

$a = $a - 50;
// é o mesmo que
$a -= 50;

$a = $a * 3;
// é o mesmo que
$a *= 3;

$a = $a / 2;
// é o mesmo que
$a /= 2;

$a = $a % 10;
// é o mesmo que
$a %= 10;

Deu pra entender? Esses cenários deixam o código bem mais curto. Porém é aquele risco que sempre falo: se houver muito código próximo, esse operador conjunto pode dificultar o entendimento do que está acontecendo. Se for um método isolado não tem problema algum.

<dica-do-dia> Sempre pense no que outro desenvolvedor vai pensar ao ler o seu código, se ele vai entender de primeira sem precisar fazer perguntas ou ler comentários. Pensar nessas coisas vai te ajudar a descobrir no que você precisa melhorar, pensando na sua carreira. </dica-do-dia>

Atribuição por referência

Se você quiser criar uma nova variável cujo valor reflita em outra previamente existente, você pode atribuir uma referência. Na verdade, isso tem pouco a ver com a atribuição em si. Acho que tem mais a ver com o operador &, que quando colocado à esquerda de uma variável é identificado como operador de referência. Por exemplo:

<?php

$variavelReal = 123;
$variavelReferencia = &$variavelReal;

$variavelReferencia = 321;
var_dump($variavelReal); // int(321)

E sobre isso, eu não vejo um bom motivo para usar esse recurso dessa forma. Parece que você quer criar um alias para uma variável, o que pode significar que você não queria mais usar a primeira nomenclatura mas não consegue alterar a escrita por não ter tanto controle do escopo do código. Isso é triste, é o sinal de que uma refatoração tá gritando para ser feita.

MAS TEM UM DETALHE

Toda atribuição de objetos são por referência!

E dito isso, criar uma referência a partir da instância de um objeto resulta em erros:

<?php

$variavelReferencia = &new stdClass;
// erro

Kiko, se todo objeto é uma referência, então se você atribuir um objeto a duas variáveis e alterar o valor dele em uma delas, o valor reflete nas duas?

Exato. (pergunta cirúrgica do dia)

<?php

$a = new stdClass();
$b = $a;

$a->nome = "Teste";
var_dump($b->nome); // string(Teste)

WOOOOOOOOOOOOOOWWW

E isso vale pra todos os escopos onde o objeto for inserido:

<?php

function test($obj) {
    $obj->nome = "Kiko";
}

$a = new stdClass;
$a->nome = "Joao";
test($a);
var_dump($a->nome); // string(Kiko)

Legal? Bom, se você precisa alterar o dado de um objeto sem aplicar a atribuição fora do escopo atual, você vai precisar clonar o objeto.

<?php

function test($obj) {
    $obj2 = clone $obj;
    $obj2->nome = "Kiko";
}

$a = new stdClass;
$a->nome = "Joao";
test($a);
var_dump($a->nome); // string(Joao)

E chegamos ao fim do artigo! Curtiu? Comenta e compartilha!

No próximo artigo irei falar sobre Operadores Bit a Bit (ou Operadores Bitwise), onde mostrarei alguns exemplos de manipulação de bits. Você já ouviu falar em bitmask? Eu vou falar nesse artigo também. Pode aguardar!

Inté!!