As superglobais são variáveis nativas do PHP que estão disponíveis em todos os escopos do script, sem necessidade de declaração global. Elas fornecem informações sobre o ambiente de execução, requisições HTTP, arquivos enviados e variáveis de ambiente do servidor. Nesta aula, vamos explorar as principais superglobais: $_SERVER, $_REQUEST, $_FILES e $_ENV, além da função getenv. Compreender essas variáveis é essencial para criar aplicações web dinâmicas e seguras.

Essas superglobais são arrays associativos que contêm dados provenientes do servidor web, da requisição do cliente e do sistema operacional. Elas permitem acessar cabeçalhos HTTP, caminhos de arquivos, parâmetros de URL, dados de formulários, arquivos enviados e variáveis de ambiente. No entanto, é importante usá-las com cuidado, pois podem conter dados fornecidos pelo usuário e representar riscos de segurança se não forem tratadas adequadamente.

$_SERVER, $_REQUEST, $_FILES

$_SERVER contém informações do servidor e do ambiente de execução. Inclui cabeçalhos HTTP, caminhos de scripts, endereços IP, método de requisição, entre outros. Exemplos comuns: $_SERVER['REQUEST_METHOD'] retorna o método HTTP (GET, POST, etc.), $_SERVER['REMOTE_ADDR'] retorna o IP do cliente, $_SERVER['HTTP_USER_AGENT'] retorna o user agent do navegador. Esta superglobal é muito utilizada para roteamento, logs e personalização de respostas.

$_REQUEST combina os dados de $_GET, $_POST e $_COOKIE. É uma maneira conveniente de acessar parâmetros de requisição sem se preocupar com a origem. No entanto, seu uso é desencorajado em aplicações críticas por questões de segurança e clareza, pois pode gerar conflitos se a mesma chave existir em mais de uma fonte. Prefira usar $_GET e $_POST explicitamente.

$_FILES armazena informações sobre arquivos enviados via formulário com enctype="multipart/form-data". Cada arquivo é um array com chaves como 'name', 'type', 'tmp_name', 'error' e 'size'. Exemplo: $_FILES['arquivo']['name'] retorna o nome original do arquivo. É fundamental validar e mover o arquivo com move_uploaded_file() para evitar vulnerabilidades.

<?php
// Exemplo de uso de $_SERVER
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    echo "Requisição via POST";
}

// Exemplo de uso de $_REQUEST (não recomendado)
$nome = $_REQUEST['nome'] ?? '';

// Exemplo de uso de $_FILES
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['documento'])) {
    $arquivo = $_FILES['documento'];
    if ($arquivo['error'] === UPLOAD_ERR_OK) {
        move_uploaded_file($arquivo['tmp_name'], 'uploads/' . $arquivo['name']);
        echo "Arquivo enviado com sucesso!";
    }
}
?>

$_ENV e getenv

$_ENV é uma superglobal que contém variáveis de ambiente do sistema operacional. Ela é preenchida quando a diretiva variables_order inclui 'E' (geralmente sim). Exemplo: $_ENV['DB_HOST'] pode conter o host do banco de dados. No entanto, nem sempre está disponível, dependendo da configuração do php.ini. A função getenv() é mais confiável, pois retorna variáveis de ambiente independentemente da configuração de $_ENV. Ela pode ser usada com um parâmetro string para obter uma variável específica, ou sem parâmetros para retornar um array com todas as variáveis.

<?php
// Usando $_ENV (pode não estar disponível)
$dbHost = $_ENV['DB_HOST'] ?? 'localhost';

// Usando getenv()
$dbUser = getenv('DB_USER');
if ($dbUser === false) {
    $dbUser = 'root';
}

// Listar todas as variáveis de ambiente
$envVars = getenv();
print_r($envVars);
?>

Cuidados

As superglobais contêm dados externos que não devem ser confiados sem validação. O uso de $_REQUEST pode expor a aplicação a ataques se o usuário manipular cookies ou parâmetros. Sempre valide e sanitize os dados recebidos. Para $_FILES, nunca confie no nome original do arquivo; gere um nome único e seguro. Evite usar $_FILES['arquivo']['name'] diretamente em caminhos de sistema. Além disso, variáveis de ambiente podem conter informações sensíveis; evite exibi-las em páginas públicas.

<?php
// Exemplo de validação segura de $_FILES
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['imagem'])) {
    $file = $_FILES['imagem'];
    $allowedTypes = ['image/jpeg', 'image/png'];
    if (!in_array($file['type'], $allowedTypes)) {
        die('Tipo de arquivo não permitido.');
    }
    $newName = uniqid() . '.' . pathinfo($file['name'], PATHINFO_EXTENSION);
    move_uploaded_file($file['tmp_name'], 'uploads/' . $newName);
}
?>

Exemplos

Abaixo, um exemplo completo que utiliza $_SERVER, $_REQUEST e $_FILES em um formulário de upload com validação básica.

<!DOCTYPE html>
<html>
<body>

<h2>Formulário de Upload</h2>
<form method="post" enctype="multipart/form-data">
    Nome: <input type="text" name="nome"><br>
    Arquivo: <input type="file" name="arquivo"><br>
    <input type="submit" value="Enviar">
</form>

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $nome = $_REQUEST['nome'] ?? 'Visitante';
    echo "Olá, $nome!<br>";
    
    if (isset($_FILES['arquivo']) && $_FILES['arquivo']['error'] === UPLOAD_ERR_OK) {
        $arquivo = $_FILES['arquivo'];
        $ext = pathinfo($arquivo['name'], PATHINFO_EXTENSION);
        $novoNome = uniqid() . '.' . $ext;
        move_uploaded_file($arquivo['tmp_name'], 'uploads/' . $novoNome);
        echo "Arquivo salvo como: $novoNome";
    } else {
        echo "Nenhum arquivo enviado ou erro no upload.";
    }
}
?>

</body>
</html>

Outro exemplo usando getenv para configurar conexão com banco de dados:

<?php
$host = getenv('DB_HOST') ?: 'localhost';
$user = getenv('DB_USER') ?: 'root';
$pass = getenv('DB_PASS') ?: '';
$db = getenv('DB_NAME') ?: 'test';

$conn = new mysqli($host, $user, $pass, $db);
if ($conn->connect_error) {
    die("Falha na conexão: " . $conn->connect_error);
}
echo "Conectado com sucesso";
?>

Boas Práticas

Prefira usar $_GET e $_POST em vez de $_REQUEST para maior clareza. Sempre valide e sanitize dados de superglobais antes de usá-los. Para variáveis de ambiente, utilize getenv() em vez de $_ENV para garantir compatibilidade. Em produção, evite expor informações do servidor via $_SERVER; filtre dados sensíveis. No upload de arquivos, limite o tamanho e o tipo, e armazene os arquivos fora da raiz pública sempre que possível.

Referências

Exercícios

  1. Escreva um script PHP que exiba o método HTTP da requisição atual usando $_SERVER.

    ✓ Resposta:
    <?php
    echo $_SERVER['REQUEST_METHOD'];
    ?>
  2. Crie um formulário que envie um arquivo e, no PHP, mova-o para a pasta 'uploads' com um nome único.

    ✓ Resposta:
    <?php
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['arquivo'])) {
        $file = $_FILES['arquivo'];
        if ($file['error'] === UPLOAD_ERR_OK) {
            $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
            $newName = uniqid() . '.' . $ext;
            move_uploaded_file($file['tmp_name'], 'uploads/' . $newName);
            echo "Arquivo salvo como: $newName";
        }
    }
    ?>
    <form method="post" enctype="multipart/form-data">
        <input type="file" name="arquivo">
        <input type="submit">
    </form>
  3. Use getenv() para obter a variável de ambiente 'APP_ENV' e exibir uma mensagem diferente se for 'production' ou 'development'.

    ✓ Resposta:
    <?php
    $env = getenv('APP_ENV');
    if ($env === 'production') {
        echo "Ambiente de produção";
    } elseif ($env === 'development') {
        echo "Ambiente de desenvolvimento";
    } else {
        echo "Ambiente não definido";
    }
    ?>
  4. Explique por que o uso de $_REQUEST pode ser inseguro e dê um exemplo de como contornar isso.

    ✓ Resposta: $_REQUEST combina dados de GET, POST e COOKIE, o que pode permitir que um atacante manipule parâmetros através de cookies ou URLs, sobrescrevendo valores esperados. Para contornar, use $_GET e $_POST explicitamente. Exemplo:
    // Inseguro
    $id = $_REQUEST['id'];
    // Seguro
    $id = $_GET['id'] ?? $_POST['id'] ?? null;
  5. Crie um script que liste todas as variáveis de ambiente usando getenv() sem argumentos, mas filtre para mostrar apenas aquelas que começam com 'DB_'.

    ✓ Resposta:
    <?php
    $env = getenv();
    foreach ($env as $key => $value) {
        if (strpos($key, 'DB_') === 0) {
            echo "$key: $value<br>";
        }
    }
    ?>