A História do PHP: de script pessoal a pilar da web

A História do PHP: de script pessoal a pilar da web

De um script para contar visitas a um currículo até a linguagem que move boa parte da web: trinta anos em que o PHP foi reescrito do zero duas vezes, perdeu uma versão inteira pelo caminho e trocou de reputação mais de uma vez. A história explica as esquisitices que você vai encontrar no código.
PHP

15 min de leitura

Poucas linguagens de programação têm uma origem tão humana quanto o PHP. Ela não nasceu em um laboratório de pesquisa nem foi projetada por um comitê. Nasceu de uma necessidade pessoal, cresceu de forma orgânica, e a cada crise de identidade — e houve várias — se reinventou. Entender essa história não é apenas curiosidade: é compreender por que a linguagem tem certas características, por que algumas decisões foram tomadas, e por que o PHP moderno é tão diferente do PHP que seus críticos conhecem.

1994 — O começo: um script para rastrear visitas

Em 1994, Rasmus Lerdorf, um programador dinamarquês-canadense, queria saber quantas pessoas estavam acessando seu currículo online. Para isso, escreveu um conjunto de scripts em Perl que registravam as visitas. Logo percebeu que seria mais prático reescrevê-los em C, criando uma camada que se encaixasse diretamente no servidor web Apache.

Esse conjunto de ferramentas ele chamou de Personal Home Page Tools — as PHP Tools. Não havia intenção de criar uma linguagem de programação. Era uma coleção utilitária, pragmática, feita para resolver um problema imediato. Em 1995, Lerdorf lançou o código publicamente, e a comunidade de desenvolvedores web da época, ávida por ferramentas que facilitassem a criação de páginas dinâmicas, adotou as PHP Tools rapidamente.

1997–1998 — PHP 3: a primeira linguagem de verdade

Dois programadores israelenses, Zeev Suraski e Andi Gutmans, encontraram as PHP Tools enquanto tentavam desenvolver um sistema de e-commerce para um projeto universitário. As ferramentas de Lerdorf não eram suficientes, então decidiram reescrever o núcleo do sistema do zero. O resultado foi uma linguagem muito mais robusta: suporte a múltiplos bancos de dados, sintaxe mais consistente e arquitetura extensível.

Em colaboração com Lerdorf, lançaram o PHP 3 em 1998. Foi nessa versão que o acrônimo ganhou seu novo significado recursivo: PHP: Hypertext Preprocessor. Ao final de 1998, estima-se que cerca de 10% de todos os servidores web da internet já rodavam PHP.

2000 — PHP 4 e a explosão do LAMP

Suraski e Gutmans não pararam. Reescreveram o motor de execução do PHP, criando o Zend Engine (o nome vem da junção de Zeev e Andi). O PHP 4, lançado em 2000, trouxe performance muito superior, suporte a sessões, bufferização de saída e melhor suporte a orientação a objetos — ainda que incompleto.

Foi durante a era do PHP 4 que a linguagem explodiu em popularidade. A facilidade de hospedar PHP em servidores compartilhados baratos, combinada com o MySQL como banco de dados gratuito, criou o famoso stack LAMP (Linux, Apache, MySQL, PHP). Milhares de sistemas foram construídos nesse período.

Foi também nessa época que práticas questionáveis se espalharam. A facilidade de uso atraiu muitos programadores sem formação formal, que criavam código sem segurança, sem estrutura e sem manutenibilidade. Essa herança manchou a reputação da linguagem por anos — e é, em grande parte, a origem das críticas que ainda circulam hoje.

2004 — PHP 5 e a maturidade orientada a objetos

O PHP 5, lançado em 2004 com o Zend Engine 2, foi uma virada de chave. Trouxe um modelo de orientação a objetos completo e bem projetado: classes, interfaces, herança, métodos abstratos, modificadores de acesso (public, protected, private), exceções com try/catch, e muito mais.

Foi no PHP 5 que frameworks sérios começaram a surgir — Zend Framework, CodeIgniter, CakePHP, Symfony. O PHP passou a ser usado em projetos corporativos de maior porte, e a comunidade começou a discutir padrões, boas práticas e arquitetura de software.

O PHP 5 teve uma vida longa, com versões menores trazendo melhorias contínuas. A versão 5.3 introduziu namespaces e closures. A 5.4 trouxe traits. A 5.5, generators. Cada versão tornava a linguagem mais expressiva e poderosa.

2015 — PHP 7: a ressurreição

Por razões históricas complexas — uma versão PHP 6 foi abandonada após anos de desenvolvimento sem conseguir implementar suporte nativo a Unicode de forma satisfatória —, a versão seguinte ao PHP 5 foi chamada de PHP 7, lançada em dezembro de 2015.

O impacto foi dramático. O PHP 7 trouxe o novo Zend Engine 3, com ganhos de performance de até 100% em relação ao PHP 5.6 em benchmarks reais. De repente, aplicações rodavam duas vezes mais rápido sem nenhuma mudança no código.

Além da performance, o PHP 7 introduziu declarações de tipo para parâmetros e retorno de funções, o operador spaceship (<=>), o operador null coalescing (??), classes anônimas e muito mais. A linguagem crescia com coerência e direção clara.

2020 em diante — PHP 8 e a linguagem moderna

O PHP 8.0, lançado em novembro de 2020, é possivelmente a versão mais importante da história da linguagem. Ele introduziu o JIT (Just-In-Time compiler), que compila partes do código em tempo de execução, trazendo ganhos de performance em workloads específicos.

Mas mais que o JIT, o PHP 8 trouxe mudanças de linguagem que transformaram a forma de escrever código:

  • Match expressions — alternativa mais segura e expressiva ao switch
  • Named arguments — passagem de argumentos pelo nome, não pela posição
  • Constructor property promotion — reduz drasticamente o boilerplate em classes
  • Union types e Nullsafe operator — sistema de tipos mais expressivo
  • Attributes — metadados nativos
  • Fibers (PHP 8.1) — programação assíncrona nativa
  • Enums (PHP 8.1) — enumerações nativas
  • Readonly properties (PHP 8.1/8.2) — imutabilidade no nível da linguagem
  • Lazy objects (PHP 8.4) — instanciação adiada para performance

Veja como o PHP evoluiu em expressividade. O mesmo conceito, escrito em PHP 5 e em PHP 8:

<?php
// ── PHP 5: muito boilerplate ──────────────────────────────────────
class Usuario {
    private $nome;
    private $email;

    // Sem tipo na assinatura: em PHP 5 a única garantia era conferir à mão
    public function __construct($nome, $email) {
        $this->nome  = $nome;
        $this->email = $email;
    }

    public function getNome()  { return $this->nome;  }
    public function getEmail() { return $this->email; }
}// ── PHP 8: constructor promotion + readonly ───────────────────────
class Usuario {
    // O PHP 8 cria, atribui e torna imutável em uma única linha
    public function __construct(
        public readonly string $nome,
        public readonly string $email,
    ) {}
}

// O resultado final é idêntico — mas o código PHP 8 é limpo e direto
$u = new Usuario('Ana', 'ana@email.com');
echo $u->nome; // Ana

A diferença não é apenas visual — é filosófica. O PHP 8 remove o ruído e deixa a intenção do código falar por si mesma.

A linha do tempo completa

Versão Ano Marco principal
PHP Tools 1994 Scripts pessoais de Rasmus Lerdorf
PHP 2 1997 Formulários, comunicação com bancos de dados
PHP 3 1998 Primeira linguagem de verdade — Suraski & Gutmans
PHP 4 2000 Zend Engine 1, explosão do stack LAMP
PHP 5 2004 OOP completa, frameworks sérios surgem
PHP 7 2015 Zend Engine 3, performance 2x, tipagem
PHP 8.0 2020 JIT, match, named args, attributes
PHP 8.1 2021 Enums, fibers, readonly, intersection types
PHP 8.2 2022 Readonly classes, DNF types, true/false/null types
PHP 8.3 2023 Typed class constants, json_validate(), melhorias em readonly
PHP 8.4 2024 Property hooks, lazy objects, melhorias em arrays

O que essa história nos ensina

A trajetória do PHP é uma lição sobre evolução pragmática. A linguagem nunca foi projetada de cima para baixo com perfeição acadêmica — ela cresceu respondendo a necessidades reais, cometeu erros, aprendeu com eles e se reinventou. Quem a critica com base no PHP de 2003 está cometendo o mesmo erro de julgar um arquiteto pelo primeiro rabisco que fez aos vinte anos.

Aprender PHP hoje significa aprender uma linguagem moderna, com décadas de lições incorporadas em seu design. E significa também entender um ecossistema enorme de sistemas existentes que precisam de profissionais qualificados.

Conhecer essa trajetória tem um uso imediato: ela explica o que você vai encontrar em código alheio. O excesso de verificação manual de tipo é herança de quando não havia tipo na assinatura; o arquivo que mistura consulta e HTML é do tempo em que isso era o que se ensinava; o mysql_query que você vai achar num sistema antigo foi a forma padrão de falar com o banco durante uma década. Nenhuma dessas escolhas foi burrice de quem escreveu — foram as ferramentas daquele momento. O que mudou não foi só a sintaxe, foi o que a linguagem passou a cobrar de quem escreve.

Fontes e leituras recomendadas

Exercícios

Exercício 1

Um sistema roda em PHP 5.6 e você quer saber o que pode usar. Para cada recurso abaixo, diga em que versão ele entrou: namespace, trait, yield, tipo escalar em parâmetro, tipo em propriedade, enum.

Ver resposta

✓ Resposta: namespace e as closures chegaram no 5.3; trait, no 5.4; yield e os geradores, no 5.5. Esses três estão disponíveis no 5.6, então um sistema dessa época já podia ser organizado com autoload PSR-4 e composição por traits — e muito código legado não usa nada disso por hábito, não por impossibilidade. Os três seguintes não: tipo escalar em parâmetro e retorno (int, string, float, bool) só veio no 7.0, junto do declare(strict_types=1); tipo em propriedade (private string $nome;) só no 7.4; e enum, no 8.1. A consequência prática é que, em 5.6, a única forma de garantir tipo é verificar à mão no começo do método e lançar exceção — o que explica o excesso de is_string() e InvalidArgumentException em código daquela época. Vale a checagem inversa também: ao copiar solução de blog ou resposta de fórum, confira a data. Código escrito para 8.x cola em 5.6 sem erro de sintaxe visível e quebra só na hora de executar.

Exercício 2

Por que não existe PHP 6? E o que a razão do fracasso revela sobre como o PHP trata texto até hoje?

Ver resposta

✓ Resposta: O PHP 6 foi desenvolvido durante anos com um objetivo central: suporte nativo a Unicode no núcleo da linguagem, com cada string carregando sua codificação. O esforço foi abandonado — a complexidade se espalhava por toda a base de código e por todas as extensões, e o ganho não compensava. Como o nome "PHP 6" já tinha circulado demais em livros e artigos, reaproveitá-lo confundiria todo mundo, e a versão seguinte pulou para PHP 7. O que isso revela é o ponto que interessa no dia a dia: em PHP, string é uma sequência de bytes, não de caracteres. strlen("ação") devolve 6, não 4, porque "ç" e "ã" ocupam dois bytes cada em UTF-8; strtoupper não acentua corretamente; e substr pode cortar um caractere ao meio e produzir lixo. Daí a existência da família mb_*mb_strlen, mb_substr, mb_strtoupper —, que precisa ser usada em qualquer texto que possa conter acento, e que exige a extensão mbstring instalada. A regra prática para código em português é simples: se a função mexe em texto do usuário, prefira a versão mb_, e defina mb_internal_encoding('UTF-8') na inicialização.

Exercício 3

Você abre um sistema de 2006 e encontra isto. O que esse código pressupõe, e por que ele não roda mais?

<?php
// login.php
if ($usuario == "admin" && $senha == "123") {
    $_SESSION['logado'] = 1;
}
$busca = $_GET['q'];
mysql_query("SELECT * FROM produtos WHERE nome LIKE '%$busca%'");
Ver resposta

✓ Resposta: Repare que $usuario e $senha aparecem do nada — nunca foram atribuídas. Esse código depende do register_globals, um ajuste que transformava automaticamente cada parâmetro de URL ou formulário em variável global: um acesso a login.php?usuario=admin&senha=123 criava as duas variáveis sozinho. Era prático e catastrófico — qualquer variável do script podia ser sobrescrita de fora, inclusive as que controlavam autenticação. O recurso foi desativado por padrão no 4.2, marcado como obsoleto no 5.3 e removido no 5.4; hoje o código simplesmente não autentica ninguém, porque as variáveis são nulas. Da mesma era vem o magic_quotes_gpc, que escapava a entrada automaticamente e criava o hábito de confiar nela — também removido no 5.4. E a extensão mysql_* foi descontinuada no 5.5 e removida no 7.0, o que derruba a última linha por função inexistente. A modernização não é cosmética: é substituir $usuario por $_POST['usuario'] validado, a comparação de senha por password_verify() contra um hash, e a consulta por prepared statement com PDO. Um sistema assim não "para de funcionar" por capricho da linguagem — ele para porque cada um desses recursos era uma falha de segurança de fábrica.

Exercício 4

O artigo cita ganhos de até 100% do PHP 7 sobre o 5.6. Você migra um sistema e mede 30% de melhora, não 100%. Isso indica que algo foi feito errado?

Ver resposta

✓ Resposta: Não indica nada de errado — indica que você mediu uma aplicação real, e não um benchmark. O ganho do PHP 7 veio da reengenharia das estruturas internas do Zend Engine: o zval (a estrutura que representa qualquer valor) encolheu e passou a ser alocado na pilha, os arrays ganharam uma tabela hash muito mais compacta, e o número de alocações de memória caiu drasticamente. Isso acelera o que o interpretador faz sozinho: criar variáveis, percorrer arrays, chamar funções. Não acelera nada que dependa de terceiros — e é aí que uma aplicação web passa a maior parte do tempo, esperando consulta ao banco, leitura de disco e resposta de API. Um script que só manipula arrays em memória chega perto do dobro; um que passa 70% do tempo esperando o MySQL melhora no máximo naquele terço restante, o que dá exatamente uma casa de 30%. A lição vale para qualquer promessa de desempenho: o ganho anunciado se aplica à parte que a mudança toca, e o efeito total depende de quanto essa parte pesava. Antes de migrar para ganhar velocidade, meça onde o tempo é gasto — se for no banco, a versão do PHP não é o assunto.

Exercício 5

Desafio: você precisa migrar um sistema em produção de PHP 5.6 para 8.4. Monte o plano — na ordem em que você faria, e dizendo o que mediria antes de cada passo.

Ver resposta

✓ Resposta: O primeiro movimento não é técnico, é de medição: ter como saber se quebrou. Sem nenhum teste, o resto do plano é apostar. Escreva ao menos testes de fumaça nos fluxos que geram receita — login, busca, finalizar pedido — porque eles vão ser rodados dezenas de vezes. Em seguida, levante o terreno: php -m na máquina atual para listar as extensões em uso, e composer why-not php 8.4 para descobrir qual dependência trava a subida. É comum que a barreira não seja o seu código, e sim uma biblioteca abandonada — decidir entre substituí-la ou assumir a manutenção dela é a decisão mais cara do projeto, e é melhor tomá-la no começo. Depois, migre por etapas, não de uma vez: 5.6 → 7.4 → 8.4. O salto para o 7 é o que expõe as quebras clássicas (mysql_* removido, ereg removido, mudanças no tratamento de erro), e o 7.4 é uma parada confortável porque aceita quase tudo do 7.x e já prepara o 8. Em cada etapa, rode o PHPStan no nível mais baixo que passar e o Rector com o conjunto de regras da versão-alvo, que faz a parte mecânica sozinho. Ligue error_reporting(E_ALL) em homologação e trate deprecation como erro: no 8.0 muitos avisos viraram Error, e um Notice ignorado hoje é uma tela branca amanhã. Suba em homologação com dados reais de produção anonimizados, deixe rodar alguns dias, e só então troque a produção — com o caminho de volta pronto, porque plano de migração sem plano de retorno é torcida.

Comentários

Mais em PHP

O que é PHP e por que ele ainda importa
O que é PHP e por que ele ainda importa

PHP roda no servidor, e é essa única característica que explica quase tudo…

Strings em Profundidade
Strings em Profundidade

Texto em PHP é sequência de bytes, e é dessa decisão que vêm quase todas as…

Namespaces, Autoloading, PSR-4 e Composer
Namespaces, Autoloading, PSR-4 e Composer

Sem namespace, dois arquivos com a mesma classe brigam pelo mesmo nome. O…