Patrón de Diseño Singleton en PHP

febrero 28, 2026

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:

  • Uno desactiva la alarma para “hacer una prueba”
  • Otro activa el modo noche
  • Otro bloquea accesos por accidente

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:

  • valores inconsistentes,
  • comportamiento impredecible,
  • gasto innecesario de recursos,
  • errores difíciles de rastrear.

¿Qué es el patrón Singleton?

El Singleton es un patrón creacional que asegura:

  1. Que una clase tenga una sola instancia.
  2. Que exista un punto global de acceso para obtener esa instancia.

En otras palabras: no importa cuántas veces lo pidas, siempre te devuelve el mismo objeto.


¿Cuándo deberías usarlo?

En proyectos web reales, Singleton suele aparecer en:

  • Configuración global (config del sistema, flags, keys, etc.)
  • Logger centralizado (registrar errores/eventos en un archivo o servicio)
  • Cliente de cache (Redis/Memcached) cuando quieres una sola instancia por proceso
  • Cliente de API (por ejemplo, un SDK externo) si es costoso inicializarlo
  • Gestor de feature flags (activar/desactivar funcionalidades desde un lugar)

¿Cuándo NO conviene?

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:

  • complica los tests (estado global),
  • oculta dependencias,
  • puede generar acoplamiento.

Pasos para crearlo

  1. Propiedad estática privada para guardar la instancia
    • private static ?self $instance = null;
  2. Constructor privado
    • Evita que alguien haga new TuClase() desde afuera.
  3. Método público estático (getInstance() o similar)
    • Crea la instancia si no existe y luego la retorna.
  4. (Recomendado) Bloquear clonación y unserialize
    • private function __clone() {}
    • public function __wakeup(): void { throw new ... }

Ejemplo:

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:

  • Controlador necesita APP_ENV
  • Servicio de email necesita SMTP_HOST
  • Logs necesitan LOG_LEVEL

Si cada componente crea su propia Config, podrías terminar:

  • releyendo archivos muchas veces,
  • duplicando trabajo,
  • o peor: con valores distintos si alguien modifica estado por error.

Código en PHP

<?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)

Uso en un “sistema web” (controlador/servicio)

<?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)

Cuando construimos aplicaciones web, hay objetos que no tiene sentido crear muchas veces: configuraciones globales, un logger, o una conexión a un servicio compartido. Para esos casos existe Singleton.
calendar-full linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram