New self vs new static em PHP: o que escolher em 2025?
Imagine: você programa em PHP há vários anos, sente-se confiante, e de repente seu colega (ou o Stack Overflow) pergunta: «Por que no meu método da classe filha está sendo criado um objeto da classe pai, mesmo eu chamando o construtor com new self()?». Familiar? Se sim, você não está sozinho. O tópico new self vs new static é uma das perguntas mais populares no Stack Overflow, com milhares de visualizações. E em 2025, com o lançamento de novas versões do PHP, entender essa diferença se tornou ainda mais importante.
Neste artigo, vamos entender as diferenças entre self e static ao criar objetos, como funciona o Late Static Binding (Ligação Estática Tardia) e, principalmente, quando usar cada um. Vamos lá!
O problema: self sempre aponta para a classe pai
Vamos começar com um exemplo clássico. Suponha que temos uma classe pai BaseController e uma classe filha ApiController.
<?php
class BaseController { public static function create() { return new self(); // Atenção! self é BaseController }}
class ApiController extends BaseController { // Herda create()}
$api = ApiController::create();var_dump($api); // object(BaseController)#1 (0) { }?>Esperávamos obter um objeto ApiController, mas obtivemos BaseController. Por quê? Porque self no contexto da classe pai sempre se refere à classe onde foi escrito, e não à classe através da qual foi chamado. Isso é ligação estática precoce. O PHP «memoriza» a classe durante a compilação, não durante a execução.
Solução: use static
Para corrigir a situação, precisamos substituir self por static. Isso ativa o mecanismo de ligação estática tardia (LSP).
<?php
class BaseController { public static function create() { return new static(); // static é a classe que chamou o método }}
class ApiController extends BaseController { // Herda create()}
$api = ApiController::create();var_dump($api); // object(ApiController)#1 (0) { }?>Agora $api é um objeto ApiController. static é resolvido em tempo de execução e aponta para a classe através da qual o método foi chamado. Isso é ligação estática tardia.
Quando usar self e quando usar static?
Em 2025, as melhores práticas diferenciam claramente essas duas abordagens. Aqui estão as regras principais.
Use self quando:
- Você está trabalhando dentro de uma única classe e não espera herança para aquele método.
- Você precisa criar um objeto exatamente da classe onde o código foi escrito, e não da classe filha.
- Você está acessando constantes ou propriedades estáticas que não devem ser sobrescritas.
Exemplo: um método fábrica que garante retornar um objeto da classe base.
<?php
class Logger { protected static $instance;
public static function getInstance() { if (self::$instance === null) { self::$instance = new self(); // Sempre Logger } return self::$instance; }}?>Use static quando:
- Você está projetando código para extensão — por exemplo, classes abstratas ou traits.
- Você precisa que as classes filhas possam criar suas próprias instâncias.
- Você está usando o padrão Factory Method ou Builder.
Exemplo: uma classe abstrata para entidades.
<?php
abstract class Entity { public static function create(array $data): static {\