Code d'exemple

<?php
class SQL {
    // instance de la classe
    private static $instance;
 
   /**
    * Constructeur privé ; empêche la création directe d'objet
    * @param string $db Nom de la base
    * @param string $user Utilisateur de la base
    * @param string $pass Mot de passe de la base
    * @param string $host Serveur de base de données
    *@return boolean (true)
    */
   private function __construct($db, $user, $pass, $host='localhost') {
      $con = mysql_connect($host, $user, $pass) or die(mysql_error());
      return mysql_select_db($db, $con);
   }
 
   /**
    * Création du singleton
    * @param string $db Nom de la base
    * @param string $user Utilisateur de la base
    * @param string $pass Mot de passe de la base
    * @param string $host Serveur de base de données
    * @return integer Ressource
    */
   public static function singleton($db, $user, $pass, $host='localhost') {
      if (!isset(self::$instance)) {
         $class = __CLASS__;
         self::$instance = new $class($db, $user, $pass, $host);
      }
      return self::$instance;
   }
 
   /**
    * Interdit le clônage de l'instance
    */
   public function __clone() {
      trigger_error('Le clônage n\'est pas autorisé.', E_USER_ERROR);
   }
}
?>

Explications

Variable statique

Une variable statique est très particulière: elle est globale à toutes les instances de son conteneur. Autrement dit, si vous mettez une variable statique dans une fonction, chaque appel de la fonction utilisera la même valeur. L'exemple le plus simple est:

<?php
function test() {
   static $compteur = 0;
   echo $static, '<br />';
   $compteur++;
}
for ($i=0;$i<5;$i++) test();

Dans une classe, le résultat est le même, à savoir que la variable static est la même utilisée pour toutes les instanciations. Dans notre cas, $instance est l'ID de connexion à la base. S'il n'existe pas, il est créé, sinon il est simplement retourné.

Constructeur

Le constructeur étant privé, il interdit l'instanciation de la classe avec new(). Dans notre exemple, il retourne true, mais il pourrait aussi bien afficher (ou stocker) une erreur.

Fonction __clone

Lorsque l'on veut un singleton, le clônage est illogique, nous utilisons donc la méthode magique __clone pour éviter tout appel indésirable.

Utilisation

Dès lors, pour créer une nouvelle connexion à une base de données, il faut faire:

$sql = SQL::singleton('test', 'user', 'pass');

Si cette ligne est présente dans vos divers scripts, seule la première instanciation sera fonctionnelle, les autres ne feront que renvoyer le même identifiant de ressource SQL.