Singleton para PHP 5.3, y parche para 5.2

Mediante esta clase abstracta de podremos crear nuestras clases simplemente extendiendo esta clase

  1. abstract class Singleton {
  2.  
  3.      protected function __construct() {
  4.      }
  5.      final public static function getInstance( $calledClassName = null ) {
  6.          static $aoInstance = array();
  7.   if ( $calledClassName == null ) {
  8.          $calledClassName = get_called_class();
  9.          
  10.          }
  11.          if (! isset ($aoInstance[$calledClassName])) {
  12.              $aoInstance[$calledClassName] = new $calledClassName();
  13.         }
  14.  
  15.          return $aoInstance[$calledClassName];
  16.      }
  17.      final private function __clone() {
  18.      }
  19.  }

Ejemplo:

  1.  
  2. class DataBase extends Singleton {
  3. []
  4. }
  5.  
  6. $db = DataBase::getInstance();

El problema que nos encontraremos en PHP 5.2.x es que no existe la función get_called_class por lo que deberemos tener esa función.

  1. if(!function_exists('get_called_class')) {
  2.     class class_tools {
  3.         static $i = 0;
  4.         static $fl = null;
  5.         static function get_called_class() {
  6.             $bt = debug_backtrace();
  7.             if(self::$fl == $bt[2]['file'].$bt[2]['line']) {
  8.                 self::$i++;
  9.             } else {
  10.                 self::$i = 0;
  11.                 self::$fl = $bt[2]['file'].$bt[2]['line'];
  12.             }
  13.  
  14.             $lines = file($bt[2]['file']);
  15.  
  16.             preg_match_all('
  17.                /([a-zA-Z0-9\_]+)::'.$bt[2]['function'].'/',
  18.                 $lines[$bt[2]['line']-1],
  19.                 $matches
  20.             );
  21.             $returnValue = $matches[1][self::$i];
  22.    // comprobamos si lo llamamos desde un call_user_func y similar
  23.             if ( empty( $returnValue ) && isset( $bt[3]['function'] ) && in_array($bt[3]['function'],array('call_user_func', 'call_user_func_array'))) {            
  24.               $returnValue = $bt[3]['args'][0][0];
  25.            
  26.             }
  27.             return $returnValue ;
  28.         }
  29.     }
  30.     function get_called_class() {
  31.         return class_tools::get_called_class();
  32.     }
  33. }

Como se puede ver utiliza la funcion debug_backtrace() para determinar a que clase estamos llamando. Con esta función ya no tendremos problemas a la hora de instanciar nuestros “Singleton” en php.

Ejemplos de uso que funcionan perfectamente en PHP 5.3, y ahora en PHP 5.2

  1. $objeto = DataBase::getInstance() ;
  2. []
  3. $miClase = 'DataBase';
  4. $objeto = call_user_func( array( $miClase, 'getInstance'));

Opina

*