
Imagina un edificio con un cuarto de control (cámaras, alarmas, accesos).
En ese cuarto hay un panel central que define reglas: “puerta principal abierta/cerrada”, “alarma activada”, “horario permitido”, etc.
Ahora imagina que cada guardia trae su propio panel y cada uno cambia reglas al mismo tiempo:
Resultado: caos, reglas inconsistentes y decisiones contradictorias.
Lo normal es que exista un único panel oficial y todos consulten y operen sobre esa misma fuente de verdad.
En código, ese “panel único” es un Singleton.
Cuando varias partes del sistema dependen del mismo estado (config, logging, acceso a recursos), tener múltiples instancias puede provocar:
El Singleton es un patrón creacional que asegura:
En otras palabras: no importa cuántas veces lo pidas, siempre te devuelve el mismo objeto.
En proyectos web reales, Singleton suele aparecer en:
Si tu aplicación usa inyección de dependencias (DI) o un contenedor (Laravel/Symfony), muchas veces es mejor registrar el servicio como singleton en el contenedor y evitar un Singleton “manual”, porque:
private static ?self $instance = null;new TuClase() desde afuera.getInstance() o similar)
private function __clone() {}public function __wakeup(): void { throw new ... }Supón que estás construyendo un blog (o e-commerce) y quieres una clase Config que cargue configuración una vez (por ejemplo desde .env o un array) y que el resto del sistema la use:
APP_ENVSMTP_HOSTLOG_LEVELSi cada componente crea su propia Config, podrías terminar:
<?php
declare(strict_types=1);
final class Config
{
private static ?self $instance = null;
private array $settings = [];
// 1) Constructor privado: nadie puede hacer "new Config()"
private function __construct()
{
// Simulación: en un proyecto real podrías cargar desde .env, ini, yaml, DB, etc.
$this->settings = [
'APP_NAME' => 'MiBlog',
'APP_ENV' => 'production',
'DB_HOST' => 'localhost',
'DB_NAME' => 'blog',
'LOG_LEVEL' => 'info',
];
}
// 2) Método estático: punto global de acceso
public static function getInstance(): self
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// 3) Getter de configuración
public function get(string $key, mixed $default = null): mixed
{
return $this->settings[$key] ?? $default;
}
// 4) (Opcional) Permite setear dinámicamente (cuidado con el estado global)
public function set(string $key, mixed $value): void
{
$this->settings[$key] = $value;
}
// Recomendado: evitar clonación
private function __clone()
{
}
// Recomendado: evitar unserialize
public function __wakeup(): void
{
throw new \RuntimeException("No se puede deserializar un Singleton.");
}
}Lenguaje del código: HTML, XML (xml)
<?php
// En un controlador:
$appName = Config::getInstance()->get('APP_NAME');
$env = Config::getInstance()->get('APP_ENV');
echo "Bienvenido a {$appName} (env: {$env})";
// En otro lugar del sistema:
$logLevel = Config::getInstance()->get('LOG_LEVEL', 'warning');Lenguaje del código: HTML, XML (xml)