PHP: Singleton Pattern

Con questa guida descriveremo come creare una classe che implementa il pattern singleton.

Come suggerisce il nome, il pattern singleton è un particolare pattern che permette ad una classe di essere istanziata “una sola volta”. Questa classe può venire in aiuto durante la progettazione di una applicazione PHP, ad esempio per istanziare una sola volta la connessione al DB ed utilizzare questa istanza per recuperare dati nel DB.

Ma adesso vediamo come implementarla.

Singleton.php
<?php
  class Singleton {
 
    private static $instance;
 
    private function __construct() {}
    public function __clone() {
      trigger_error('Clone is not allowed.', E_USER_ERROR);
    }
 
    public static function getInstance() {
 
      if (! self::$instance) {
        self::$instance = new self;
      }
 
      return self::$instance;
 
    }
 
  }

Come possiamo vedere il codice contiene poche righe ed è molto intuitivo.

  • Prima di tutto abbiamo reso privato il costruttore in modo che la classe venga istanziata solo attraverso il metodo statico Singleton::getInstance().
  • Abbiamo impedito di clonare la classe richiamando la funzione trigger_error in modo da retrituire un errore.
  • Nel codice abbiamo istruito PHP ad instanziare la classe solo quando la proprietà statica self::$instance non è istanziata con la sua stessa classe (Singleton), altrimenti recuperiamo l'istanza creata in precedenza.

Così come abbiamo scritto la classe non permette di fare molto ma estendendola permette di fare grandi cose.

Come esempio di utilizzo, creiamo una classe che permette di collezionare valori e di recuperarli in qualsiasi parte del nostro codice. Questa verrà chiamata Registry.

Registry.php
<?php
  include 'Singleton.php';
 
  class Registry extends Singleton {
 
    private static $registry = array();
 
    public function __get($key) {
      if (array_key_exists(self::$registry, $key)) {
        return self::$registry[$key];
      }
      return null;
    }
 
    public function __set($key, $value) {
      self::$registry[$key] = $value;
    }
 
    public function __isset($key) {
      return array_key_exists(self::$registry, $key);
    }
 
    public function __unset($key) {
      unset(self::$registry[$key]);
    }
 
  }

Abbiamo esteso la classe Singleton e grazie ai metodi “magici” che PHP ci mette a disposizione abbiamo creato una classe che permette di recuperare e salvare dei valori. Vediamola in azione:

<?php
 
include 'Registry.php';
 
$registry = Registry::getInstance();
$registry->foo = 'bar';
 
echo $registry->foo; // bar

Adesso mettete in moto la vostra immaginazione per utilizzare questo semplice ma utile pattern nel vostro codice.

Buona programmazione!