Ver Mensaje Individual
  #3 (permalink)  
Antiguo 02/01/2009, 06:10
paloto
 
Fecha de Ingreso: abril-2007
Mensajes: 114
Antigüedad: 17 años
Puntos: 2
Respuesta: ORM casero creado desde cero

elemento
Esta clase contiene las funciones principales de comunicación con la base de datos: Select, Update, Insert y Delete, además de dos funciones extras de uso interno como son SacarCampos y Recursiva (esta última no tiene un nombre muy adecuado, pero bueno, no sabía como llamarla) .

Esta clase no tiene constructor así que iré explicando método a método, pero debemos tener en cuenta que todo ello se encuentra entre las etiquetas:



Código php:
Ver original
  1. class elemento{
  2.     public $tabla;
  3.     ...
  4. }



Empezaremos por una sencilla, SacarCampos($tabla), que se encarga de obtener un array con el tipo de dato de cada campo de la tabla que pasamos como parametro.


Código php:
Ver original
  1. function SacarCampos($tabla){
  2.  
  3. $consulta="SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '$tabla'";
  4. $cn=new Conexion();
  5. $res=$cn->Consulta($consulta);
  6. while($row=mysql_fetch_array($res)){
  7.     $resultado[$row['COLUMN_NAME']]=$row['DATA_TYPE'];
  8. }
  9. return $resultado;
  10. }



Del resto de métodos de la clase elemento me voy a centrar en el Update, pues utiliza la clase "CampoValor" y la clase "CondicionWhere" y a partir de él se pueden deducir el resto de métodos, pues estos serán inevitablemente, más sencillos.



Código php:
Ver original
  1. function Update($camposvalores, $condicion){ // El parametro $camposvalores es un array de CampoValor
  2.  
  3. $tabla=$this->tabla;
  4. if ($camposvalores!="" && $tabla!="") //Comprobamos que los datos sean correctos
  5. {
  6.    $bdd_campos=$this->SacarCampos($tabla); // Obtenemos el array con el tipo de dato de los campos
  7.    $consulta = "UPDATE $tabla SET "; // $consulta será la cadena que finalmente lanzaremos contra la base de datos
  8.    foreach($camposvalores as $c){ // Recorremos el array de $camposvalores
  9.    $consulta.=$c->campo."="; // Añadimos a la cadena de la consulta el campo y el operador de asignacion
  10.    switch($bdd_campos[$c->campo]) // Comprobamos el tipo de dato para dcidir si ponemos comillas ( ' ) o no
  11.    {
  12.       case "char":
  13.       case "varchar":
  14.       case "date":
  15.       case "tinytext":
  16.       case "tinyblob":
  17.       case "text":
  18.       case "blob":
  19.       case "mediumtext":
  20.       case "mediumblob":
  21.       case "longtext":
  22.       case "longtext":
  23.       case "datetime":
  24.       $consulta.="'".$c->valor."', ";
  25.       break;
  26.       default:
  27.       $consulta.=$c->valor.", ";
  28.       break;
  29.    }
  30. }
  31.  
  32. if ($condicion !=null){ // Si le pasamos condiciones...
  33.    $consulta=substr($consulta, 0, strlen($consulta)-2)." WHERE ";
  34.    $cadena=$this->Recursiva($condicion); //Llamamos a la función "Recursiva" y obtenemos el valor de retorno
  35.    $consulta.=$cadena; // Lo añadimos a la cadena de consulta y Violá!
  36. }
  37. $cn=new Conexion();
  38. return $cn->Consulta($consulta);
  39. }



Vale, una vez hemos explicado estos métodos, solo nos queda hacerlo con el método "Recursiva", que aunque no es muy extenso, a mi me parece el más complicade de implementar y de explicar, y es precisamente como su nombre indica, por tratarse de una función recursiva. No sé si es que son de lo más complicado de asumir/entender de la programación o simplemente a mi se me atraviesan especialmente, pero lo cierto es que tuve verdaderos problemas para crearla.


Código php:
Ver original
  1. function Recursiva($condicion){ // el parametro $condicion puede ser un objeto CondicionWhere o una cadena y lo comprobamos en el siguiente if
  2.  
  3. if(strlen($condicion->parametro1)>0){ // Si se trata de un objeto CondicionWhere...
  4. $cadena.="("; // Añadimos el paréntesis de apertura para establecer la prioridad
  5. $cadena.=$this->Recursiva($condicion->parametro1); //La función se llama a si misma para profundizar en el "parametro" del CondicionWhere.
  6. // Para tenerlo mas o menos claro, construimos mentalmente $cadena.
  7. // Hasta este momento $cadena vale esto: "(", si resulta que 4l "parametro1" de este CondicionWHERE
  8. // resulta ser una cadena, irá por el else y $cadena pasará a valer "(NombreDelCampo".
  9. // A continuación dejará un espacio y hará lo mismo con "operador", que irá por el else.
  10. // igual con el "parametro2" de forma que al final la $cadena nos queda así (imaginemos que el operador es "=" ): "(NombreDelCampo = Valor)".
  11. // Si se tratara de condiciones mas complejas, con unas dentro de otras, lo único que cambia es que se repetirá este proceso las veces necesarias construyendo finalmente la condición final.
  12.  
  13. $cadena.=" ";
  14. $cadena.=$this->Recursiva($condicion->operador);
  15. $cadena.=" ";
  16. //Comprobar el campo
  17. // Aquí comprobamos si hay que ponerle comillas ( ' ) al "parametro2".
  18. $bdd_campos=$this->SacarCampos($this->tabla);
  19.  
  20. switch($bdd_campos[$condicion->parametro1])
  21. {
  22. case "char":
  23. case "varchar":
  24. case "date":
  25. case "tinytext":
  26. case "tinyblob":
  27. case "text":
  28. case "blob":
  29. case "mediumtext":
  30. case "mediumblob":
  31. case "longtext":
  32. case "longtext":
  33. case "datetime":
  34.    $marca="'";
  35.    break;
  36. default:
  37.    $marca="";
  38.    break;
  39. }
  40.  
  41. $cadena.=$marca; // Si necesita comillas se las ponemos
  42. $cadena.=$this->Recursiva($condicion->parametro2);
  43. $cadena.=$marca; // Si necesita comillas se las ponemos
  44. $cadena.=")";
  45. }
  46. else{
  47.    $cadena.="$condicion";
  48. }
  49. return $cadena; // Devuelve la cadena para seguir construyéndola o para devolverla al método que llamó a este.
  50. }



Llegado a este punto, para todo quede más claro, solo me falta mostrar la forma de usar estas clases y métodos.

Creamos una clase sencilla llamada "Lugar", creamos un objeto "Lugar", creamos el objeto CondicionWhere con varios CondicionWhere anidados y el array de CampoValor de asignación y llamamos a la función Update.



Código php:
Ver original
  1. class Lugar extends elemento
  2. {
  3.    public $id;
  4.    public $nombre;
  5.    public $nombre_corto;
  6.    function Lugar(){
  7.       $this->tabla="Lugar";
  8.    }
  9. }
  10. $lug=new Lugar();
  11. $con1=new CondicionWhere("nombre", "Can%", "LIKE");
  12. $con2=new CondicionWhere("nombre_corto", "CAN");
  13. $con3=new CondicionWhere("nombre_corto", "CNT");
  14. $con4=new CondicionWhere($con2, $con3, "OR");
  15. $con5=new CondicionWhere($con1, $con4, "AND");
  16.  
  17. $campos=array(new CampoValor("nombre", "ValorNombre"),
  18.  
  19. new CampoValor("nombre_corto", "ValorNombreCorto"));
  20.  
  21. $lug->Update($campos, $con5);



El resultado es que el ORM envía a la base de datos MySql la consulta siguiente:

Cita:
UPDATE Lugar SET nombre_corto='ValorNombreCorto' WHERE ((nombre LIKE 'Can%') AND ((nombre_corto = 'CAN') OR (nombre_corto = 'CNT')))
No sé si he logrado explicarme correctamente, pero he de decir que yo mismo me pierdo al intentar seguir el camino de la aplicación cuando llega a esta función recursiva. El caso es que funciona correctamente después de muchas pruebas y modificaciones.

Si a alguien le parece interesante y quiere utilizar este código puede hacerlo y si desea tener el código completo (con los métodos Select, Insert y Delete) solo tiene que mandarme un correo electrónico o pedirlo en los comentarios y se lo enviaré con mucho gusto, igualmente si alguien tiene alguna duda o sugerencia sobre esto, puede ponerla también en los comentarios.

Un saludo

Última edición por paloto; 02/01/2009 a las 06:20