2010-04-21 4 views
2

Comment puis-je faire un singleton de l'extension PDO? L'extension ne fonctionne pas, parce que je reçois une erreur fatale quand je l'essaye ...Comment puis-je créer un wrapper singleton pour PDO?

+2

Bienvenue sur SO. S'il vous plaît montrer votre code et l'erreur exacte que vous obtenez. –

+0

liées: [Qui a besoin de Singletons] (http://stackoverflow.com/q/4595964/367456) – hakre

Répondre

10

You don't need a Singleton.

Mais pour répondre à cette néanmoins:

Vous ne pouvez pas transformer une visibilité publique à une visibilité plus stricte. Ainsi, PDO ne peut pas avoir la visibilité du constructeur modifiée à autre chose que public. Vous devez donc envelopper l'instance PDO dans un Singleton:

class MyPdo 
{ 
    /** 
    * @var MyPdo 
    */ 
    protected static $_instance; 

    /** 
    * @var Pdo 
    */ 
    protected $_pdo; 

    /** 
    * Creates instance and returns it on subsequent calls 
    * 
    * @throws InvalidArgumentException 
    * @param array $options PDO connection data 
    * @returns MyPdo 
    */ 
    public static function getInstance(array $options = NULL) 
    { 
     if(self::$_instance === NULL) { 

      if($options === NULL) { 
       throw new InvalidArgumentException(
        'You must supply connection options on first run'); 
      } 

      // call constructor with given options and assign instance 
      self::$_instance = new self(
       $options['dsn'], 
       $options['user'], 
       $options['password'], 
       $options['driver_options'] 
      ); 
     } 

     return self::$_instance; 
    } 

    /** 
    * Creates new MyPdo wrapping a PDO instance 
    * 
    * @throws PDOException 
    * @param String $dsn 
    * @param String $user 
    * @param String $password 
    * @param Array $driver_options 
    * @return void 
    */ 
    private function __construct($dsn, $user, $password, $driver_options) 
    { 
     try { 
      $this->_pdo = new PDO($dsn, $user, $password, $driver_options); 
     } catch (PDOException $e) { 
      echo 'Connection failed: ' . $e->getMessage(); 
     } 
    } 

    /** 
    * Singletons may not be cloned 
    */ 
    private function __clone() {} 

    /** 
    * Delegate every get to PDO instance 
    * 
    * @param String $name 
    * @return Mixed 
    */ 
    public function __get($name) 
    { 
     return $this->_pdo->$name; 
    } 

    /** 
    * Delegate every set to PDO instance 
    * 
    * @param String $name 
    * @param Mixed $val 
    * @return Mixed 
    */  
    public function __set($name, $val) 
    { 
     return $this->_pdo->$name = $val; 
    } 

    /** 
    * Delegate every method call to PDO instance 
    * 
    * @param String $method 
    * @param Array $args 
    * @return Mixed 
    */  
    public function __call($method, $args) { 
     return call_user_func_array(array($this->_pdo, $method), $args); 
    } 
} 

Vous utiliseriez comme ceci:

$db = MyPdo::getInstance(array(
    'dsn'=>'mysql:dbname=mysql;host=127.0.0.1', 
    'user' => 'root', 
    'password' => 'minnymickydaisydonaldplutogoofysanfrancisco', 
    'driver_options' => array(
     PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" 
    ))); 

$version = $db->query('SELECT version();'); 
echo $version->fetchColumn(); 

// remove reference to instance 
unset($db); 

// doesn't require connection data now as it returns same instance again 
$db = MyPdo::getInstance(); 
$version = $db->query('SELECT version();'); 
echo $version->fetch(); 
Questions connexes