2012-07-27 17 views
5

Attualmente sto usando PHP PDO per accedere al mio database. Tutto funziona perfettamente e dandy. Tuttavia, aggiungerò read-replicas alla configurazione del mio server, quindi desidero modificare il mio codice di conseguenza.Come posso creare un "cambio modalità" per PHP PDO?

Il mio piano di azione corrente è quello di memorizzare una serie di dettagli delle credenziali del database. Un set di "lettura e scrittura" per il database master MySQL e qualsiasi numero di credenziali per "repliche di lettura".

Ciò che desidero fare è aggiungere un metodo alla classe PDO denominata "modalità" in cui passa una modalità, ad esempio "lettura" o (predefinito) "scrittura". Passando attraverso questo (ad es. $ Dbh-> mode ("read");), può cercare i dettagli di una replica di lettura casuale (non complicata quale) e usare quei dettagli per la connessione. Poi, una volta finita la lettura dalle mie repliche, fai un'altra $ dbh-> mode ("default") per rimetterla in modalità scrittura, per cui posso usare INSERT, UPDATE ecc.

Questo può essere fatto senza distruggere l'oggetto PDO e crearne uno nuovo? È possibile modificare i dettagli della connessione solo dopo che l'oggetto esiste già?

Finora ho il seguente (il suo a malapena qualsiasi cosa, ma figurato è un inizio).

Class SwitchablePDO extends PDO 
{ 
    public function mode($mode = "default") 
    { 
     // Use the credentials for my master read and write server by default 

     if($mode == "read") 
     { 
      // Use one the credentials for my read replicas (randomly choose) 
     } 

    } 
} 

Qualsiasi aiuto in merito sarebbe apprezzato!

+0

È necessario? Penso che la maggior parte delle persone utilizzerebbe un paio di utenti DB per fare ciò (uno che può solo leggere e uno che ha accesso completo), quindi utilizzare una connessione DB separata per ciascun utente. – Ozzy

+0

Tuttavia, non distribuirebbe il carico alle repliche di lettura. I dettagli della connessione sono letteralmente diversi per ogni replica di lettura. E se dovessi creare un nuovo oggetto PDO ogni volta che voglio scambiare per leggere o scrivere, ho ancora bisogno di un modo per farlo. In questo modo (si spera) mi permetterò di avere un solo oggetto/istanza di connessione della mia classe alla volta piuttosto che dover usare $ dbh_write-> query() e $ dbh_read-> query(). – Schodemeiss

risposta

2

avrei preferito di set-up completamente diversi oggetti di connessione al database di accordo con una modalità. Usando una modalità, ti imbatterai inevitabilmente in una situazione in cui un pezzo di codice non imposta la modalità e fa affidamento sulla modalità precedente del codice, e fallirà quando viene chiamato in un contesto diverso. Questo è noto come sequential coupling.

Con più oggetti forniti da un metodo factory o un contenitore di dipendenze injection, ci si assicura che ogni pezzo di codice specifichi quale connessione al database ha bisogno, come master o slave.

Come bonus, evitare di utilizzare master/slave come nome e utilizzare invece nomi che si riferiscono al tipo di attività da eseguire, come analitica, che consente di cambiare il server che verrà utilizzato senza passare attraverso il codice per trova tutti i pezzi di codice relativi.

1

Creare classi separate per la modalità di lettura e scrittura, che quindi assegnano a proprietà private/protette nella classe SwitchablePDO. Chiamando mode() quindi dovrebbe solo impostare quale proprietà usare. Ecco alcuni pseudo-codice:

class WriteablePDO extends PDO 
{ 
    // methods 
} 

class ReadablePDO extends PDO 
{ 
    // methods 
} 

class SwitchablePDO 
{ 
    protected $_mode = 'read'; // default 
    protected $_read; 
    protected $_write; 

    public function __construct() 
    { 
     $this->_read = new ReadablePDO(); 
     $this->_write = new WriteablePDO(); 
    } 

    public function mode($key) 
    { 
     if ($key === 'read') 
     { 
      $this->_mode = '_read'; 
     } 
     elseif ($key === 'write') 
     { 
      $this->_mode = '_write'; 
     } 
    } 

    public function __call($method, $arguments) 
    { 
     return call_user_func_array(array($this->{$this->_mode}, $method), $arguments); 
    } 

}