Introducción: Una letra que lo cambia todo
\n\nImagina que estás desarrollando un framework PHP increíble o simplemente una librería para tu proyecto. Todo funciona perfectamente, pero al cabo de un mes notas que las clases hijas no se comportan como esperabas. Creas un objeto y ¡pum! te devuelve una instancia de la clase padre. ¿Te suena? Bienvenido al club de quienes se han topado con new self vs. new static.
\n\nEsta pregunta en Stack Overflow acumula miles de visitas, y con razón. La diferencia entre self y static en PHP no es solo azúcar sintáctico, sino un mecanismo fundamental que puede salvar tu proyecto o convertirlo en una pesadilla de mantenimiento. En 2025, mientras PHP sigue evolucionando, entender el enlace estático tardío (Late Static Binding) se ha vuelto una habilidad obligatoria para cualquier desarrollador que se precie.
En este artículo no solo repetiremos la documentación. Analizaremos casos reales, mostraremos antipatrones y te daremos mejores prácticas claras que podrás aplicar hoy mismo. ¡Vamos allá!
\n\nParte principal: self vs. static — la batalla por el contexto
\n\n1. self — el conservador del compilador
\n\nLa palabra clave self en PHP siempre hace referencia a la clase en la que está escrita. Piensa en ella como un viejo amigo que nunca cambia. Cuando escribes new self() en la clase padre, este código siempre creará un objeto de esa clase padre, incluso si lo llama una clase hija.
<?php\nclass Animal {\n public static function create() {\n return new self(); // Siempre Animal\n }\n}\n\nclass Dog extends Animal {\n // Hereda create()\n}\n\n$dog = Dog::create();\necho get_class($dog); // Muestra: Animal\n?>\n\n¿Ves? Llamamos al método desde la clase Dog, pero obtenemos un Animal. Esto suele sorprender a los principiantes. ¿Cuál es el truco? self se resuelve en tiempo de compilación. PHP «sella» la referencia a la clase donde se declaró el método, y ninguna magia de herencia podrá cambiarlo.
2. static — el revolucionario del enlace tardío
\n\nstatic es todo lo contrario. Funciona en el momento de la llamada al método y determina qué clase lo invocó. Esto es el enlace estático tardío (Late Static Binding), introducido en PHP 5.3.0.
<?php\nclass Animal {\n public static function create() {\n return new static(); // Crea una instancia de la clase que llamó al método\n }\n}\n\nclass Dog extends Animal {\n // Hereda create()\n}\n\n$dog = Dog::create();\necho get_class($dog); // Muestra: Dog\n?>\n\n¡Menudo cambio! Ahora Dog::create() devuelve un perro, no un animal abstracto. static observa quién llamó al método y crea un objeto de esa clase. Esto ofrece una flexibilidad increíble al construir jerarquías de clases.
3. ¿Cuándo usar self y cuándo static?
\n\nLa regla de oro: usa self cuando necesites un vínculo fijo a la clase actual, y static cuando quieras que las clases hijas puedan sobrescribir el comportamiento.
Aquí tienes algunos escenarios concretos:
\n\nEscenario A: Métodos fábrica (Usamos static)
\nUn ejemplo clásico es el patrón Factory Method. Quieres que cada clase hija se cree a sí misma.
\n\n<?php\nabstract class Vehicle {\n abstract public function getType(): string;\n\n public static function create(): static {\n return new static();\n }\n}\n\nclass Car extends Vehicle {\n public function getType(): string {\n return 'Automóvil';\n }\n}\n\nclass Bike extends Vehicle {\n public function getType(