Introdução: Uma letrinha que muda tudo
\n\nImagine: você está criando um framework PHP incrível ou apenas uma biblioteca para seu projeto. Tudo funciona perfeitamente, mas um mês depois você percebe que as classes filhas não se comportam como esperado. Você cria um objeto e — puf! — ele retorna uma instância da classe pai. Familiar? Bem-vindo ao clube daqueles que já enfrentaram o dilema new self vs. new static.
\n\nEssa pergunta no Stack Overflow já acumulou milhares de visualizações, e por um bom motivo. A diferença entre self e static no PHP não é apenas açúcar sintático, mas um mecanismo fundamental que pode salvar seu projeto ou transformá-lo em um pesadelo de manutenção. Em 2025, com o PHP em constante evolução, entender o Late Static Binding se tornou uma habilidade obrigatória para qualquer desenvolvedor que se preze.
Neste artigo, não vamos apenas repetir a documentação. Vamos analisar casos reais, mostrar antipadrões e dar diretrizes claras de best practices que você pode aplicar hoje mesmo. Vamos nessa!
\n\nParte principal: self vs. static — a batalha pelo contexto
\n\n1. self — o conservador do compilador
\n\nA palavra-chave self no PHP sempre se refere à classe onde ela foi escrita. Pense nela como um velho amigo que nunca muda. Quando você escreve new self() em uma classe pai, esse código sempre criará um objeto dessa classe pai — mesmo se for chamado por uma classe filha.
<?php\nclass Animal {\n public static function create() {\n return new self(); // Sempre Animal\n }\n}\n\nclass Cachorro extends Animal {\n // Herda create()\n}\n\n$dog = Cachorro::create();\necho get_class($dog); // Exibe: Animal\n?>\n\nViu? Chamamos o método na classe Cachorro, mas recebemos um Animal. Isso frequentemente pega os iniciantes de surpresa. Qual é o truque? O self é resolvido em tempo de compilação. O PHP "sela" a referência à classe onde o método foi declarado, e nenhuma mágica de herança muda isso.
2. static — o revolucionário do binding tardio
\n\nJá o static é o oposto completo. Ele funciona no momento da chamada do método e determina qual classe o invocou. Isso é o Late Static Binding, introduzido no PHP 5.3.0.
<?php\nclass Animal {\n public static function create() {\n return new static(); // Cria uma instância da classe que chamou o método\n }\n}\n\nclass Cachorro extends Animal {\n // Herda create()\n}\n\n$dog = Cachorro::create();\necho get_class($dog); // Exibe: Cachorro\n?>\n\nQue mudança! Agora Cachorro::create() retorna um cachorro, e não um animal abstrato. O static olha para quem chamou o método e cria um objeto dessa classe. Isso oferece uma flexibilidade incrível ao construir hierarquias de classes.
3. Quando usar self e quando usar static?
\n\nA regra de ouro: use self quando precisar de uma ligação rígida com a classe atual, e static quando quiser que as classes filhas possam sobrescrever o comportamento.
Aqui estão alguns cenários específicos:
\n\nCenário A: Métodos fábrica (Use static)
\nUm exemplo clássico é o padrão Factory Method. Você quer que cada classe filha crie a si mesma.
\n\n<?php\nabstract class Veiculo {\n abstract public function getTipo(): string;\n\n public static function create(): static {\n return new static();\n }\n}\n\nclass Carro extends Veiculo {\n public function getTipo(): string {\n return 'Carro';\n }\n}\n\nclass Bicicleta extends Veiculo {\n public function getTipo(