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
-
Manual oficial do PHP — Histórico de versões e changelogs completos: https://www.php.net/ChangeLog-8.php
-
"PHP: a fractal of bad design" — O artigo crítico mais famoso sobre PHP, escrito em 2012 (baseado no PHP 5). Vale ler para entender as críticas históricas e avaliar quais ainda se aplicam: https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/
-
"PHP in 2024" — Resposta moderna às críticas, com dados atualizados: https://stitcher.io/blog/php-in-2024
-
Zeev Suraski — The Secret History of PHP — Palestra do cocriador do Zend Engine contando a história em primeira pessoa (YouTube): https://www.youtube.com/watch?v=APoz6nEJpyI
-
LERDORF, Rasmus. "PHP/FI — Personal Home Page / Forms Interpreter" — O anúncio original de 1995 na Usenet, disponível em: https://groups.google.com/g/comp.infosystems.www.authoring.cgi/c/PyJ25gZ6z7A
-
TATROE, K.; MACINTYRE, P. Programming PHP, 4ª ed. O'Reilly Media, 2020. Capítulo 1: History of PHP. Disponível em: https://www.oreilly.com/library/view/programming-php-4th/9781492054122/
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.