PHP para Iniciantes: Variáveis - Fontes Externas

Olá! Nesse artigo falaremos um pouco sobre as variáveis compostas por valores externos. Iremos revisar algumas das variáveis pré-definidas que citei em um artigo anterior. A ideia é entender como o PHP captura esses valores, mostrando alguns pequenos exemplos de como trazer dados para dentro da aplicação.

Pontuações e espaços

Antes de falar das possibilidades, vamos falar das impossibilidades, pode ser? Então o que é absolutamente impossível no PHP é criar uma variável com um ponto ou espaço em branco no nome. Vimos lá no artigo sobre o básico de variáveis que esses caracteres não são aceitos.

Portanto, se você tenta inserir uma informação no PHP onde ele teria de gerar uma variável com ponto/espaço, o interpretador irá automaticamente trocar isso por underline (_). Esse tipo de conflito acontece bastante em projetos onde a principal fonte de dados vem sempre em JSON (JavaScript Object Notation, recomendo leitura se nunca ouviu falar). Por exemplo:

// isso aqui é JavaScript
let pessoa = {
    nome: "Joao"
};

Nesse caso, para acessar o dado nome no objeto pessoa, consultamos pessoa.nome. Daí, programas que facilitam a construção de requisições, inventaram de transformar esses objetos em campos HTML, deixando o nome do campo pessoa.nome.

Quando essa fonte de dados chega no PHP como variável, ele precisa corrigir isso. Afinal, $pessoa.nome é o mesmo que $pessoa . 'nome', uma concatenação com a string nome. Já $pessoa_nome é um nome totalmente aceito. Da mesma forma, se fosse $pessoa nome seria um erro fatal ainda pois não teria nem operador. Conveteria da mesma forma.

Formulários HTML

Agora que você já sabe uma proibição, vamos falar sobre formulários HTML. Mais precisamente, iremos falar sobre coisas que o browser faz como client da nossa aplicação back-end.

Cada formulário prepara uma série de campos que serão enviados para o back-end. Nessas definições, o desenvolvedor pode informar o nome desses campos. Por exemplo:

<form action="index.php">
    <input name="pessoa.nome" value="Joao" placeholder="Informe seu nome" />
    <br/>
    <button type="submit">Enviar</button>
</form>

Esse formuláro irá enviar o campo pessoa.nome para o arquivo index.php. Como não foi definido o verbo HTTP a ser usado, ele enviará o verbo GET, isto é, receberemos os dados enviados pela variável pré-definida $_GET, onde cada nome informado vai ser um índice em seu array.

<?php

if ($_GET) {
    var_dump($_GET); // array("pessoa_nome" => "Joao"), percebe a correção?
}

Mas Kiko, como eu testo isso aí? Quero ver na prática, po!

Aaaaa, ok! Cria uma pasta aí no seu ambiente de desenvolvimento. Sugestão: kiko_variaveis_fontes-externas. E depois adiciona esse arquivo lá como index.php:

<?php

if ($_GET) {
    echo "GET: <br/>";
    var_dump($_GET);
    exit;
}
?>
<form action="index.php">
    <input name="pessoa.nome" value="Joao" placeholder="Informe o seu nome" />
    <br/>
    <button type="submit">Enviar</button>
</form>

Kiko, a primeira requisição que eu faço no formulário não vai ser um GET?

Sim! Mas se você não informar nenhum parâmetro, nenhum dado será populado em $_GET.

Ao salvar o arquivo, inicie o servidor PHP (php -S localhost:8080) dentro da pasta que criamos e abra a página web. Deixe esse servidor rolando até o final do artigo, ok? Ao abrir a página, você verá o formulário. Clique no botão para enviar!

O que vai acontecer é simples:

  1. O browser vai receber o evento de submit do botão e irá preparar o formulário para envio;
  2. Irá buscar as propriedades do formulário vinculado ao botão;
  3. Vai encontrar a propriedade action, então vai direcionar a requisição para o que quer que esteja ali... No caso, é o arquivo index.php;
  4. Vai ver que não há definição para a propriedade method, então vai usar a padrão, que é GET;
  5. Tem outras propriedades mas não vale mencionar nesse exemplo. Estude HTML!
  6. Então, vai consultar os campos que serão enviados, encontra o pessoa.nome e agrega à query da requisição;
  7. E por fim, irá enviar você para a requisição final: GET index.php?pessoa.nome=Joao. Você poderá ver esse link na sua barra de navegação!

Porém, mesmo que a variável de entrada seja pessoa.nome, como eu disse anteriormente, o PHP converte o ponto em underline, ficando pessoa_nome.

Mas Kiko, e se fosse um POST?

Então a variável pré-definida a ser alimentada seria a $_POST.

<?php

if ($_GET) {
    echo "GET: <br/>";
    var_dump($_GET);
    exit;
}

if ($_POST) {
    echo "POST: <br/>";
    var_dump($_POST);
    exit;
}
?>
<form name="index.php" method="post">
    <input name="pessoa.nome" value="Joao" placeholder="Informe o seu nome" />
    <br/>
    <button type="submit">Enviar</button>
</form>

Note que eu apenas adicionei uma condicional pra gente capturar o $_POST e a propriedade method="POST" na tag form. Nesse caso, se você enviar esse formulário, nada irá mudar na barra do navegador (exceto, talvez, que irá deixar o index.php explícito se você estava acessando sem escrever ele na URL).

E, tanto GET quanto POST, tem suas informações replicadas na variável $_REQUEST. Porém, recomendo FORTEMENTE não usar essa variável, pois deixa bem claro que você não tem ou não quer ter controle sobre as requisições. Afinal, da mesma forma que um usuário poderá seguir o fluxo POST do seu formulário, um hacker poderia exercer o mesmo comando mandando um GET e você aceitaria sem nem questionar se aquilo está certo, sabe? Ou até mesmo enviar um comando misturando dados. Por exemplo, se você aceita a requisição GET mas consulta a variável $_REQUEST...

<?php

if ($_REQUEST) {
    echo "REQUEST:<br/>";
    var_dump($_REQUEST); // array("pessoa_nome" => "Joao");
    echo "<br/>";
}

if ($_GET) {
    echo "GET:<br/>";
    var_dump($_GET); // array("pessoa_nome" => "Paulo");
    echo "<br/>";
}

if ($_POST) {
    echo "POST:<br/>";
    var_dump($_POST); // array("pessoa_nome" => "Joao");
    echo "<br/>";
}
?>
<form name="index.php?pessoa.nome=Paulo" method="post">
    <input name="pessoa.nome" value="Joao" placeholder="Informe o seu nome" />
    <br/>
    <button type="submit">Enviar</button>
</form>

No final, o browser vai fazer o comando POST pra URL index.php?pessoa.nome=Paulo com o dado pessoa.nome=Joao no corpo da mensagem. E o resultado é que o interpretador receberá tanto o GET do que vem na URL (pessoa.nome=Paulo) quanto o POST que vem na mensagem (pessoa.nome=Joao). O que vale pro $_REQUEST? A variável que condiz com o método utilizado, no caso, o $_POST. O $_POST['pessoa_nome'] sobreescreve o $_GET['pessoa_nome'] em $_REQUEST['pessoa_nome'].

Ah, e se eu esperar $_POST no $_REQUEST?

Então poderemos te burlar mandando um GET com os dados esperados em POST, possibilitando a criação de um phishing só pra fazer um usuário seu cair numa página falsa que coleta os dados dele e redireciona para a sua, por exemplo.

Isso é sério, evitem isso. Façam códigos rígidos e tenham controle total das origens dos dados.

É possível criar arrays nos formulários, Kiko?

Sim! É só usar a sintaxe de arrays! pessoa[nome] vira $_REQUEST['pessoa']['nome'], por exemplo. Todas essas informações são bem padronizadas nas definições de requisições HTTP e HTML (como configurar o browser corretamente via HTML para gerar a requisição HTTP que quero fazer? esse é o ponto).

Um detalhe muito importante é que nem sempre utilizam o markdown HTML para configurar o browser. Nos projetos de front-end mais robustos, todo mundo evita usar isso. Acabamos por criar as requisições no JavaScript, seja por meio do XMLHttpRequest para fazer um AJAX ou por meio de libs que facilitam essas criações (tipo a axios). Eu queria muito te falar sobre isso, mas esse artigo é sobre PHP.

Achei importante mencionar essas coisas para tentar te instigar a aprender, também, front-end. Mas tome cuidado, é preciso ter foco em uma das áreas nesse começo. A questão de tudo o que foi mencionado é apenas sobre como o interpretador converte os comandos recebidos.

Obs.: na documentação há menção ao campo HTML do tipo image, onde o browser envia na requisição os campos nomeDoCampo.x e nomeDoCampo.y e o PHP converte para nomeDoCampo_x e nomeDoCampo_y. Nesse caso, acho que não vale a pena mencionar tão claramente esse exemplo pois tem mais a ver com HTML do que o PHP propriamente dito, afinal, já expliquei sobre essa conversão.

Requisições CLI

Já nas requisições em CLI, nós recebemos os dados pelas variáveis $argc (argument count, número representando a quantidade de valores de entrada) e $argv (argument values, array representando os valores de entrada). Eu já falei sobre esses carinhas muito bem no artigo de Variáveis Pré-definidas, então acho que não precisamos de exemplos.

HTTP Cookies

Cookie é uma informação que armazenamos no client-side, isto é, no browser de quem está acessando a aplicação. Esse tipo de dado só é útil se o seu arquivo PHP foi feito para ser acionado por um browser, que nem nosso servidorzinho maroto. A implementação de Cookies no PHP segue a RFC-6265 e, se realmente pretende usar, lembre de pedir o consentimento do seu visitante para ficar de acordo com a Lei Geral de Proteção aos Dados.

Para inserir um dado nas cookies do browser, você usa a função setcookie() e para recuperar o dado, você acessa a variável pré-definida $_COOKIE, que é um array.

Basicamente, se um cookie é armazenado no browser, todas as próximas requisições irão receber aquele cookie até que ele expire ou o usuário faça uma limpeza no navegador.

Por exemplo, crie o arquivo cookie.php lá na nossa pastinha:

<?php // releitura do exemplo na documentação oficial do PHP

$visualizacoes = 0;
if (isset($_COOKIE['visualizacoes'])) {
    $visualizacoes = $_COOKIE['visualizacoes'];
}
$visualizacoes++;
setcookie('visualizacoes', $visualizacoes, time() + 10); // expira em 10 segundos

echo "Visualizações: $visualizacoes";

O link para abrir será http://localhost:8080/cookie.php. Se você acessar repetidas vezes antes de dar 10 segundos de quando cada cookie foi definido, a quantidade irá aumentar. Experimente abrir, atualizar 5 vezes para mostrar o número 6, esperar uns 15 segundos (pra garantir que não errou na conta, rs) e depois recarregar a página!

O número reiniciou porque o cookie expirou, logo, o browser não mandou mais a informação!

Validando o tipo das variáveis

Bom, eu te disse que o interpretador faz algumas correções sobre o nome das variáveis de entrada, mas e os valores? Será que tem um inteiro? Um float? Uma string? Array você já sabe que pode ter, desde que seja inserido na requisição da forma correta, mas em objeto?

Bem, independente do que você mande, o interpretador só irá tratar dois tipos: string e array. O resto... É string mesmo. Mesmo que no HTML você coloque lá um campo do tipo number, o que vai chegar pro PHP é uma string!

Isso ocorre porque toda e qualquer convesão de dados pode ter perda de informações e o interpretador não quer correr o risco de te fazer perder dados de graça. Se você precisa validar se um campo de entrada é um número, por exemplo, então tem funções mais adequadas para isso.

A essa altura você já deve conhecer algumas funções que validam os tipos de dados: is_bool, is_int, is_float, is_string, is_array, is_object, is_callable, etc. Mas, como te falei, tudo é string... Como faria para identificar se é um número?

is_numeric é a função que você procurava. Já faz um tempo que escrevi um artigo sobre Textos Numéricos e essa função valida se um dado é numérico.

Todas essas validações são bem práticas quando você não está trabalhando numa função com argumentos tipados. Ainda assim, o ideal é usar tipagem na entrada do método e confiar no que acontece com ela. Raramente você verá uma aplicação dessas funções em códigos bem restritos.

E aqui encerramos o último artigo sobre variáveis! No próximo começaremos a falar sobre constantes. Curtiu? Comenta e compartilha! Chama a galera pra estudar PHP contigo, hehe. E se você está procurando um mentor pra te ajudar na carreira como pessoa desenvolvedora PHP, entra aí no grupo do mestre @rafaelneris : PHP - Career Mentoring.

Inté!