New self vs new static en PHP: ¿qué elegir en 2025?
Imagina: llevas varios años programando en PHP, te sientes seguro, y de repente un colega (o Stack Overflow) te pregunta: «¿Por qué en mi clase hija se crea un objeto de la clase padre, aunque llamo al constructor con new self()?». ¿Te suena? Si es así, no estás solo. El tema de new self vs new static es una de las preguntas más populares en Stack Overflow con miles de visitas. Y en 2025, con el lanzamiento de nuevas versiones de PHP, entender esta diferencia se ha vuelto aún más importante.
En este artículo analizaremos en qué se diferencian self y static al crear objetos, cómo funciona el enlace estático tardío (Late Static Binding) y, sobre todo, cuándo usar cada uno. ¡Allá vamos!
El problema: self siempre apunta al padre
Comencemos con un ejemplo clásico. Supongamos que tenemos una clase padre BaseController y una clase hija ApiController.
<?php
class BaseController { public static function create() { return new self(); // ¡Atención! self es BaseController }}
class ApiController extends BaseController { // Hereda create()}
$api = ApiController::create();var_dump($api); // object(BaseController)#1 (0) { }?>Esperábamos obtener un objeto ApiController, pero obtuvimos BaseController. ¿Por qué? Porque self en el contexto de la clase padre siempre se refiere a la clase donde está escrito, no a la clase desde la que se llama. Esto es enlace estático temprano. PHP «recuerda» la clase durante la compilación, no durante la ejecución.
Solución: usamos static
Para solucionar la situación, debemos reemplazar self por static. Esto activa el mecanismo de enlace estático tardío (LSP).
<?php
class BaseController { public static function create() { return new static(); // static es la clase que llamó al método }}
class ApiController extends BaseController { // Hereda create()}
$api = ApiController::create();var_dump($api); // object(ApiController)#1 (0) { }?>Ahora $api es un objeto de ApiController. static se resuelve en tiempo de ejecución y apunta a la clase desde la que se llamó al método. Esto es enlace estático tardío.
¿Cuándo usar self y cuándo static?
En 2025, las mejores prácticas diferencian claramente estos dos enfoques. Aquí están las reglas principales.
Usa self cuando:
- Trabajas dentro de una sola clase y no esperas herencia para ese método.
- Necesitas crear un objeto exactamente de la clase donde está escrito el código, no de una clase hija.
- Accedes a constantes o propiedades estáticas que no deben ser sobrescritas.
Ejemplo: un método factory que garantiza devolver un objeto de la clase base.
<?php
class Logger { protected static $instance;
public static function getInstance() { if (self::$instance === null) { self::$instance = new self(); // Siempre Logger } return self::$instance; }}?>Usa static cuando:
- Diseñas código para extensión — por ejemplo, clases abstractas o traits.
- Necesitas que las clases hijas puedan crear sus propias instancias.
- Usas el patrón Factory Method o Builder.
Ejemplo: una clase abstracta para entidades.
<?php
abstract class Entity { public static function create(array $data): static {\