PHP para Iniciantes: Variáveis - O básico

Antes de nos aprofundarmos no abismo que são as possibilidades de coisas que dá pra fazer com variáveis em PHP, precisamos falar do básico. E sobre isso, se você está acompanhando todos os artigos desta série, há muita coisa que você já deve ter notado mas não perguntou porque estava aguardando esse momento. Afinal, eu sempre avisei que chegaria, não é mesmo? Então vamos começar do começo.

Como declarar uma variável?

Em outras linguagens, para declarar a existência de uma variável é preciso usar algumas palavras reservadas, como var, let, def, etc. Esse tipo de prefixo segue um padrão e PHP não é diferente, exceto que seu prefixo é permanente.

Como assim, Kiko?

Por exemplo, em Javascript, se quisermos criar uma variável de nome teste com valor 1, nós podemos fazer var teste = 1; ou let teste = 1;. Eu usaria o let, mas esse artigo não é sobre Javascript, portanto não vou nem explicar a diferença. Porém incentivo a pesquisa, pois é conhecimento sempre é benéfico.

Já em PHP, no lugar de var(espaço) ou let(espaço), nós usamos o cifrão como prefixo, sendo, no fim: $teste = 1;. Encurta um pouco? Sim, mas apenas na declaração.

Por quê, Kiko?

Como o PHP não tem uma palavra reservada para declarar variáveis de modo a diferenciar o que é variável e o que é constante (veremos muito mais a frente, paciência), toda vez que precisarmos definir um novo valor ou recuperar o valor de uma variável, precisaremos usar o prefixo $ imediatamente antes de seu nome.

Então, sem cerimônias, você pode criar uma variável DO NADA.

<?php

$variavelDoNada = 123;
if (($outraVariavelDoNada = 321) > $variavelDoNada) {
    echo "A outra variavel do nada é maior que a variavel do nada" . PHP_EOL;
}
var_dump($outraVariavelDoNada); // int(321)

E com isso, fica evidente que também é possível consultar uma variável que nunca existiu. Afinal, não existe sintaxe para declarar variável alguma, certo? Ao acionar o cifrão, se a variável não existir, o interpretador irá criá-la para você. E se você não atribuir nenhum valor, seu dado inicial será null.

Dito isso, qualquer manipulação que fizer com uma variável que não existe será uma manipulação com null:

  • booleanos tratam o null como false;
  • inteiros tratam o null como 0;
  • pontos flutuantes tratam o null como 0.0;
  • textos tratam o null como '' (string vazia);
  • arrays tratam o null como array() (array vazio).
<?php

$bool = "nao";
if ($boolImaginario) {
    $bool = "sim";
}
var_dump($bool); // string(nao);
var_dump($intImaginario + 1); // int(1)
var_dump($floatImaginario + 1.0); // float(1)
var_dump($stringImaginaria . "abc"); // string(abc)

$arrayImaginario["hello"] = "from the other side";
var_dump($arrayImaginario); // array("hello" => "from the other side");

var_dump($varImaginaria); // NULL

Se você rodar esse código sem supressão das mensagens do interpretador, irá ocorrer:

  • no PHP 8+, um Warning em cada criação forçada de variável;
  • no PHP 7 pra baixo, um Notice (...).

Mesmo com o Warning/Notice, a variável será criada com o valor null. E se o interpretador está te dando esse aviso, é melhor considerar NÃO FAZER ISSO. #fikdik

Kiko, percebemos que quando você chama uma variável de um objeto, ela não usa cifrão antes...

Mais ou menos... Acontece que, nesses casos, não chamamos de variáveis e sim atributos do objeto. Por isso, independente de ser uma "variável" ou uma "função" (leia-se método), os nomes são restringidos.

Por exemplo:

<?php
// você pode ter uma variável e uma função com mesmo nome
$calcular = 123;
function calcular() {
    return 123;
}

var_dump($calcular === calcular());

Isso é aceitável pois você é obrigado a colocar o cifrão para recuperar o valor da variável e não para acionar a função. Já em objeto, isso acaba ficando complicado, pois se você criar um atributo e um método com mesmo nome vai ser difícil de entender o que você quer acessar. E, apesar de ser possível, isso não é recomendado. Mas vamos voltar ao assunto que é sobre variáveis.

Eu posso escrever qualquer nome nas variáveis, Kiko?

Não. Tem apenas uma palavra que é completamente bloqueada: this. É especial pois em métodos de objetos representa a própria instância. É uma palavra reservada para contextos, sabe?

Além disso, tem toda uma série de regras sobre como uma variável pode ser escrita:

  1. o primeiro caractere tem de ser uma letra ou underline (_);
  2. os demais podem ser letras, números ou underlines (_).

Com isso, fica óbvio que é impossível começar o nome de uma variável com um número. $007agent não existe, as $agent_007 sim.

É preciso lembrar que esses nomes são case-sensitive, isto é, a menor variação de maiúsculo/minúsculo importa. Por exemplo:

<?php
$Agent = "007";
$agent = "001";

echo $Agent + $agent; // 8

$_alou = 123; // válido

Referências (ponteiro?)

Também é possível criar uma variável que referencia uma outra já existente. Isso serve pra você poder dar "apelidos" às variáveis e manter o comportamento de alterar os seus valores sem precisar alterar um monte de coisa ao mesmo tempo. Além disso, você pode usar a referência para alterar algo inacessível de dentro de um escopo. As utilidades são amplas, mas não recomendamos o uso disso pois você perde o controle sobre a informação, de fato.

Para declarar uma referência, basta usar o símbolo do E comercial (&) antes do nome da variável que deseja usar como referência. Por exemplo:

<?php

$minhaCarteira = 0; // :kkkrying:
$hack = &$minhaCarteira; // fiz o hack ser uma referência da minha carteira
$hack = 10000000000; // coloquei "grana" no hack
var_dump($minhaCarteira); // e o hack, por ser apenas referência, direcionou a "grana" pra "minhaCarteira"

// meramente ilustrativo, claro. eu nunca faria uma coisa dessas shuahsuahsuh

É possível criar referência de referências, mas não de coisas que não sejam variáveis.

<?php

// tudo isso é possível:
$valorReal = "Esse dado é uma string";
$referenciaDoValor = &$valorReal;
$referenciaDaReferencia = &$referenciaDoValor;
var_dump($referenciaDaReferencia); // string(Esse dado é uma string)
$referenciaDaReferencia = 123;
var_dump($valorReal); // int(123)

// tudo isso não:
$referenciaImpossivel = &123;
$referenciaImpossivel = &(2 + 1);
$referenciaImpossivel = &nomeDaFuncao();
$referenciaImpossivel = &NOME_DA_CONSTANTE;

Isso é muito utilizado em funções com acúmulo de responsabilidades, coisa que você deve evitar sempre. Exemplo:

<?php
declare(strict_types=1);

function porFavorNaoFacaIsso(int &$referencia): void
{
    $referencia = "Créu: virou string!";
}

$numero = 123;
var_dump($numero); // int(123)
porFavorNaoFacaIsso($numero);
var_dump($numero); // string(Créu: virou string!)

Ué, Kiko?! A função não obriga a tipagem a ser int???

Pois é! E mesmo declarando strict_types=1, isso é possível. Simplesmente porque a tipagem rígida apenas verifica o tipo do dado que está entrando. Ele não impede a mudança da tipagem pois, como eu sempre falo, PHP não é linguagem de tipagem forçada. Logo, toda variável pode mudar de tipo!

Então, quando você recebe uma referência e muda seu valor, há um risco enorme de quebrar o código fora do escopo da sua função. Essa é uma prática que deve ser evitada a todo custo... Mas está aí caso queira se aventurar nos paradigmas.

Curtiu? Comenta e compartilha! Gostaria de ver quem já teve péssimas experiências com referências argumentando aí pra galera nova não cometer os mesmos erros, rs. Eu mesmo já sofri bastante. Podemos deixar isso pra um papo de café, que tal? Enfim...

Inté!