Bienvenido a la sección de Preguntas y Respuestas, donde puedes plantear tus dudas e inquietudes técnicas y recibir respuestas de otros miembros de la comunidad. Si deseas consultar el foro anterior puedes hacerlo a través del enlace: Foro Anterior (Solo Lectura)

(SOLUCIONADO) Como obtener el método correcto?

0 positivos 0 negativos
495 vistas

Buenas amigos de php Venezuela, tenía tiempo que no me paseaba por estos lares, pero heme aquí de nuevo.

Como reza en en el título, esa es mi interrogante, me explico.

 

Tengo los siguientes métodos en clases diferentes:

  • En una clase llamada Mysql tengo Mysql::crearBd ( $bd, $seguro, $charset, $collate );
  • En otra clase llamada Postgresql tengo Postgresql::crearBd ( $bd, $owner, $template, $encoding, $lc_collate, $lc_ctype, $tablespace, $connection_limit, $, $, $ );

son más, pero para los efectos es suficiente. El punto es que estos métodos los llamo desde otro método en otra clase, como sigue.

class Sql {

    public function crearBd () {

        return $motor->crearBd ();

    }

}

Donde $motor es una instancia de la clase respectiva (Mysql o Postgresql)

El detalle está, en como puedo hacer para pasarle los parámetros correctos al método Sql::crearBd, de acuerdo al motor sobre el cual se esté trabajando, pues como pueden ver los metodos de las clases concretas llevan parámetros diferentes.

Espero haberme explicado bien, si necesitan una mejor explicación, lo explicaré de otra forma.

Gracias de antemano.

preguntado por remizero (20 puntos) Sep 23, 2014 en Discusión General
editado por remizero Sep 26, 2014

4 Respuestas

1 positivo 0 negativos
pues por como esta diseñada te quedará hacer condicional segun la instancia pasas los parámetros, sino declara una interface con lo comun y los demás parámetros pasalos vía setter al driver específico
respondido por carlos-belisario (178 puntos) Sep 24, 2014
buenas amigo carlos_belisario, gracias por tu respuesta, estuve buscando información relacionada con mi tema y por más que intento no logro conseguir alguna forma de cambiar los parámetros de forma dinámica, pero aun así, he logrado llegar a una solución no tan elegante como quisiera pero no tan chaborra.
 
De hecho tengo una interfaz para los métodos comunes y una clase abstracta con el código común.
1 positivo 0 negativos
Hola.

Puedes implementar el patron de diseño Factory:

http://oscarblancarteblog.com/2014/07/18/patron-de-diseno-factory/

O puedes usar PDO o una libreria (ORM) que ya resuelva ese problema por ti como por ejemplo Doctrine, Eloquent etc.

Saludos.
respondido por oyepez003 (38 puntos) Sep 25, 2014
Esta es la opción más viable, aunque según veo esta intentando hacer un factory, el problema es que no creo en principio la interface, sino que se hicieron primero los adapters y luego se ve como se usan, con PDO pudiera resolver ese punto, pero en mi opinión lo más simple en su caso sería usar un ORM (que es lo que intenta hacer según entiendo), saludos
Exactamente Carlos.

Claro... nosotros te aconsejamos utilizar un ORM en el caso de que quieras aparte de crear la BD manejar mas cosas como las tablas (CRUD), relaciones etc.... Ahora si es solo crear la BD, con el patron Factory y PDO lo puedes lograr.

Saludos.
En efecto amigo oyepez003, estoy haciendo un ORM, para trabajar de forma exactamente igual todas las bases de datos permitidas con PDO.
 
Estoy utilizando muchos patrones de diseño en esto, justamente por la escalabilidad. La idea es que el ciclo de vida del sistema ORM que estoy desarrollando se pueda extender suficientes años hasta que salga algo "mejor" que PDO.
 
Si bien, cualquiera me dirá que estoy reinventando la rueda, pues creo que mi rueda es mejor, y por otro lado no me gusta dejarle la seguridad de mis bases de datos a terceros auque sean muy buenos y muy utilizados :P
0 positivos 0 negativos
Como dije en el comentario a carlos-belisario, pude llegar a una solución bastante interesante.
 
En esta parte donde estoy trabajando, lo que hago es generar el código SQL, que lo tengo dividido como LDD, LDM, LDC, soy bastante necio con el orden :P. El detalle con las sentencias LDD, es que varían mucho entre las distintas BDs, por eso es problema que se me presenta.
 
Lo que hago ahora es pasar como parámetro un arreglo, y en este arreglo paso los diferentes parámetros que requiere cualquiera de las BDs. Adicional, tengo que hacer una validación de los parámetros que trae el arreglo para verificar que pertenece al motor que se tenga seleccionado.
 
El código anterior queda así:
 
Mysql tengo Mysql::crearBd ( $arrayParam );
Postgresql tengo Postgresql::crearBd ( $arrayParam );
 
Y con esto como implementan una interface base que llamo Motor, pues todos los motores BD (Mysql, Postgresql, Oracle, ...) implementan el mismo método.
 
crearBd ( $arrayParam );
 
Ahora bien, al hacer el llamado en mi clase Sql, todo queda perfecto, pues todas las BDs se manejaran exactamente iguales, de la siguiente manera:
 
class Sql {
 
    public function crearBd ( $arrayParam ) {
 
        return $motor->crearBd ( $arrayParam );
    }
}
 
Donde $arrayParam sería algo así para Mysql
 
$arrayParam = array ( 'nombreBd' => 'nombreDeMiBd', 'charset' => 'utf8', 'collate' => 'utf8' );
 
Luego en el motor correspondiente haría las validaciones respectivas y generar los mensajes de error si, por ejemplo, la cantidad de parámetros no son los requeridos, o si el charset no es aceptado o cosas así por el estilo.
 
Espero le sirva a alguien más que requiera implementar alguna estrategia como la que hé presentado y doy por solucionada la pregunta :)
 
Espero nos veamos en mi proxima duda jejeje.
respondido por remizero (20 puntos) Sep 26, 2014
0 positivos 0 negativos
Yo que tu uso doctrine, te aseguro que no estas dejando en manos de ningunos noobs el trabajo con tu db XD (tenía que trollear un poco) ahora en tu tema en específico el hecho es que implementes un factory, para que esto sea posible debería de implementar una interface, y tu método crear db debería esperar una instancia de esa interface de tu driver, Aunque ya lo des como solucionado (congrats XD) el hecho es que implementes una interface, algo así
https://gist.github.com/carlosbelisario/9c4c5ea4bc4219bdc90a Según tu código, sin embargo, revisa bien las responsabilidades, ya que según creo Sql no debería ser quien instancie la db, la db debería de esperar un Objeto Sql para realizar el query, por cierto una pequeña guia

https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Connection.php

https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Driver.php

https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php

https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php

 

Saludos
respondido por carlos-belisario (178 puntos) Sep 26, 2014

Buenas amigo carlos-belisario, gracias por tu respuesta, voy a revisar mejor a doctrine, a ver que tal, aunque sigo con mi idea, soy un poco terco jejeje.

sin embargo, revisa bien las responsabilidades, ya que según creo Sql no debería ser quien instancie la db

En efecto es como tu dices, pero esto solo lo hago para generar las tiras SQL, en este punto ya tengo definido el driver y la conexion y el driver solo está esperando a que se genere la tira SQL para ejecutarla. Esto es lo más interno de la api que hago, que la estoy trabajando HMVC (más que todo por lo de la jerarquía, porque aun no tengo vista o admin para la api).

El detalle con esta estrategia que diseño, es que como termino trabajando con objetos dentro de objetos, hay un punto en el que pierdo donde estoy (que driver llama a SQL) y tengo que indicarle a la fábrica cual es el motor que está solicitando la clase SQL. Este aspecto aun no lo termino de pulir para evitar esto, pero bueeeenooo, todo a su momento, primero una cosa y luego otra jejeje.

El punto es que he realizado una abstracción del lenguaje SQL y sus variantes de las distintas BDs y lo he dividido en clases para generar las tiras SQL correspondientes a cada BD, aunque esto realmente aplica a LDD y LDC, porque para LDM las tiras SQL son siempre las mismas, por otro lado lo que busco con esto es que no tenga que introducir una sola sentencia sql, lo estoy haciendo anti-dumb jejeje.

Pero gracias por el aporte que lo tomaré en cuenta. Saludos

...