2012-07-27 14 views
5

Actualmente estoy usando PHP PDO para acceder a mi base de datos. Eso está funcionando absolutamente bien y elegante. Sin embargo, voy a agregar réplicas de lectura a la configuración de mi servidor, por lo que deseo ajustar mi código en consecuencia.¿Cómo creo un "interruptor de modo" para PHP PDO?

Mi plan de acción actual es almacenar una matriz de detalles de las credenciales de la base de datos. Un conjunto de "lectura y escritura" para la base de datos maestra de MySQL y cualquier cantidad de credenciales para "réplicas de lectura".

Lo que deseo hacer es agregar un método a la clase PDO llamada "modo" donde por un modo se pasa, como "leer" o (por defecto) "escribir". Pasando esto a través (ej. $ Dbh-> mode ("read");), puede buscar los detalles de una réplica de lectura aleatoria (sin preocuparse de cuál) y usar esos detalles para la conexión. Luego, una vez que termine de leer mis réplicas, haga otro $ dbh-> mode ("predeterminado") para ponerlo nuevamente en modo de escritura, con lo cual puedo usar INSERTAR, ACTUALIZAR, etc.

¿Esto se puede hacer sin simplemente destruyendo el objeto PDO y creando uno nuevo? ¿Pueden los detalles de conexión simplemente cambiarse después de que el objeto ya exista?

Hasta ahora tengo lo siguiente (es apenas cualquier cosa, pero supongo que es un comienzo).

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) 
     } 

    } 
} 

¡Cualquier ayuda con respecto a esto sería apreciada!

+0

¿Es esto necesario? Creo que la mayoría de la gente usaría un par de usuarios de DB para hacer esto (uno que solo puede leer, y uno que tiene acceso completo), luego usaría una conexión DB separada para cada usuario. – Ozzy

+0

Sin embargo, eso no distribuiría la carga a las réplicas de lectura. Los detalles de conexión son literalmente diferentes para cada réplica de lectura. Y si tuviera que crear un nuevo objeto PDO cada vez que quisiera intercambiar para leer o escribir, todavía necesito una forma de hacerlo. De esta forma (con suerte) me permitirá tener un solo objeto/instancia de conexión de mi clase a la vez en lugar de tener que usar $ dbh_write-> query() y $ dbh_read-> query(). – Schodemeiss

Respuesta

2

yo preferiría set-up completamente diferentes objetos de conexión de base de datos que tratan de un modo. Al usar un modo, inevitablemente se encontrará con una situación en la que un fragmento de código no establece el modo y depende del modo del código anterior, y falla cuando se lo llama en un contexto diferente. Esto se conoce como sequential coupling.

Con varios objetos proporcionados por un método de fábrica, o un contenedor de inyección de dependencia, se asegura de que cada fragmento de código especifique qué conexión de base de datos necesita, como maestro o esclavo.

Como beneficio adicional, evite usar el maestro/esclavo como nombre y en su lugar use nombres que se relacionen con el tipo de tareas que se realizarán, como analíticas, que le permiten cambiar qué servidor se usará sin pasar por el código encontrar todas las piezas relacionadas de código.

1

Crea clases separadas para modo de lectura y escritura, que a su vez asignan propiedades privadas/protegidas en tu clase SwitchablePDO. Si llama al mode(), debe establecer qué propiedad usar. He aquí algunos pseudo-código:

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); 
    } 

}