Crear una clase para conectar a la base de datos (IV)

Este va a ser el último tip para ir mejorando nuestra clase. Durante todo el recorrido hemos podido ver una evolución de nuestra clase, ganando abstracción, ganando flexibilidad y ahora vamos a ganar capacidad gestión de errores.

Un problema que podemos tener al trabajar con nuestra base de datos, es que ésta no esté disponible en un momento determinado por que esté sobrecargada o por que no hay posibilidad de conexión. Por ello, debemos controlar que si no tenemos conexión a la base de datos, la ejecución de nuestra aplicación sea detenida inmediatamente (en el caso de que el uso de la base de datos sea crítico y nuestra aplicación sea 100% dependiente de la conexión a la base de datos.

Existen multitud de formas de controlar y gestionar los errores. PHP nos da ciertas herramientas para intentar capturar estas situaciones. En el ejemplo vamos a utilizar la función exit, que permite detener inmediatamente la ejecución de nuestro script, y también la función error_log que permite registrar en el log de errores de nuestro servidor web un evento, en nuestro caso, una frase identificadora para que podamos saber cúando ha pasado el problema. Si tenemos un hosting contratado (no un servidor dedicado), es prácticamente seguro que no tendremos acceso al fichero de logs del servidor web, pero lo bueno de esta función es que también es capaz de guardar el registro que nosotros queramos en un derminado fichero o incluso mandar un e-mail a una determinada cuenta. Recomiendo mirar la documentación por que además de las capacidades citadas, permite más opciones, las cuales puedes ser muy útiles para nuestra aplicación.

Lo que vamos a hacer es modificar la función pública conectar() de la clase Db. En dicha función vamos a detectar si nuestra conexión ha fallado, y si se da el caso, registrar dicho error para luego diagnosticar el problema, además de mostrar un error por pantalla avisando al visitante de existe un problema con nuestra aplicación.

/*Realiza la conexión a la base de datos.*/
private function conectar(){
   switch ($this->tipo){
      case 'mysql':       $link=mysql_connect($this->servidor, $this->usuario, $this->password);
                          if ($link){
                             mysql_select_db($this->base_datos,$this->link);
                             @mysql_query("SET NAMES 'utf8'");
                          }
                          break;

      case 'postgress':   $this->link=pg_connect("host=".$this->servidor." dbname=".$this->base_datos." user=".$this->usuario." password=".$this->password)
                          break;
      break;
   }
   if (!$link){
      error_log(0,'Problema de conexión a la base de datos.');
      exit('Perdonen las molestias. Tenemos un problema técnico. Esperamos resolverlo en los próximos minutos');
   }else{
      $this->link=$link;
   }
}

Descargar fichero Db.class.php actualizado (en formato UTF8)

Con esto ponemos fin a una pequeña colección de tips. Espero que esto les haya servidor para ir aprendiendo como poder crear y desarrollar una clase, utilizar un patrón de diseño y crear niveles de abastracción.

Temas relacionados:

Crear una clase para conectar a la base de datos

Crear una clase para conectar a la base de datos (II)

Crear una clase para conectar a la base de datos (III)

19 Comentarios

  • Jose Manuel
    27 noviembre 2008 - 17:00 pm | Enlace permanente

    Hola el enlace a la clase no funciona. Podrías revisarlo.

    Un saludo, y gracias.

  • Jose Manuel
    27 noviembre 2008 - 17:03 pm | Enlace permanente

    http://www.marcosdev.com/ejemplos/clase-base-de-datos-iv/archivos.zip

    Ahi esta el correcto, por si alguien lo busca. Saludos.

  • 27 noviembre 2008 - 20:40 pm | Enlace permanente

    Muchas gracias por tu notificación. Ya está arreglado.

  • Henry Lankhaar
    20 mayo 2009 - 18:57 pm | Enlace permanente

    Marco necesito ayuda: el problema que tengo es necesito pasar la informacion contenida en 6, 7 campos de una base en sql/asp.net a otra base hecha en mysql/php ambas bases se encuentran en lugares remotos y la idea de esto es que cada vez que agregue un registro a mi sistema en asp.net exista una funcion automatica o incluso puede ser manual que me permita copiar datos de esos registros insertados a la otra base de datos; en fin muchos saludos desde Mexico; no he tenido la oportunidad de estar en Mallorca pero se que es un lugar muy bonito; mi hermana esta casada con una persona que sus abuelos emigraron de las Islas Canarias a Mexico hace muchos años y uno de sus abuelos era un famosisimo luchador de las Islas Canarias.

    saludos

  • 21 mayo 2009 - 21:00 pm | Enlace permanente

    Buenas, si la base de datos MySQL tienes posibilidad de acceder a ella desde ASP.NET, lo tienes todo solucionado. Deberás realizar una doble conexión y dobles inserciones. Si no es el caso por que no tengas los puertos abiertos a conexiones externas, entonces puedes provocar un POST desde ASP.NET hacia un fichero una url PHP que reciba la información que tu quieras. Si no recuerdo mal, y además de ASP.NET ando flojillo, con el Ajax Tool Kit del VS2005, o ya integrado en el VS2008, podrías realizar dicha funcionalidad. Lo único que deberías tener cuidado, es que en lado del PHP, primero, prepares los SQL de forma correcta para eviar cualquier tipo de injección SQL, y lo segundo y si fuera posible, que dicha URL únicamente permitiese conexiones desde el servidor ASP.NET. Cómo supongo que son servidores de Internet, y por lo tanto tienes IP fija, pues algo de camino adelantado. Desde PHP puedes recoger la ip del solicitante, pero esta información no es totalmente fiable ya que puede ser alterada. Dentro de la información que envíes al servidor, deberías enviar varios campos cuya combinación de contenidos y nombre de campos, puedan verificar que tu servidor ASP.NET es quien está realizando la petición. Esto sería una primera medida, aunque deberías ir implementando más, como protección a través de .htpasswd, conexiones a través de SSL (evitar escuchas de la información transmitida), tokens cambiantes, …

    No se si te habré ayudado o te habré liado más. Estoy contento de que te haya sido útil mi página. Para las conexiones de MySQL, deberías actualizar la librería que utilizo yo en el manual por la MySQLi, que ya integra la preparación de SQL, lo cual minimiza mucho más los problemas de ataques. Recuerda siempre verificar uno a uno todos los campos que vayas recibiendo desde PHP. A ver si tengo algo de tiempo, y algo algún tutorial de medidas básicas de seguridad en programación PHP, aunque son extrapolables a prácticamente cualquier entorno web.

    Un saludo

  • 9 julio 2009 - 16:14 pm | Enlace permanente

    Gracias Marcos por la explicación de cómo crear una clase para conectar con BBDD.

    Comentarte que le añadido algo de mi propia cosecha para ampliar la funcionalidad.

    En db.class.php :

    /*Método para obtener el valor de una celda del resultados de la sentencia sql*/
    public function obtener_celda($stmt,$celda)
    {
    switch ($this->tipo){
    case ‘mysql’:
    $this->var = mysql_result($stmt, $celda);
    break;
    }
    return $this->var; //devuelve el valor en forma de variable no de array
    }

    S@lu2,
    Jose Miguel

  • 9 julio 2009 - 18:27 pm | Enlace permanente

    Gracias por el comentario. La clase se puede extener y adaptar a las necesidades de cada uno. Actualmente utilizo la librería mysqli, en vez de la mysql antigua, lo cual te obliga a adaptar un poco más la clase. También otra cosa que utilizo en mis proyectos la jerarquía de objetos DAO (Data Access Objects) y VO (Value Objects) para mis proyectos.

    Un saludo

  • Gilberto
    5 septiembre 2009 - 0:50 am | Enlace permanente

    Muchas gracias por tus excelentes aportes, estare a la espera de nuevos tutoriales.

  • Eduardo Villavicencio
    19 octubre 2009 - 16:53 pm | Enlace permanente

    Hola amigo espero estes bien, me estoy iniciando en PHP y me parecio interesante el ejemplo de conexion PHP+MYSQL por medio de una clase la baje pero no me funciona me da un error en la linea 57 (syntax error, unexpected T_BREAK in C:\AppServ\www\chacao\Db.class.php on line 57
    ) por favor me puedes ayudar a resolver esto

    gracias

  • 19 octubre 2009 - 17:33 pm | Enlace permanente

    En esta línea: case ‘postgress’: $link=pg_connect(“host=”.$this->servidor.” dbname=”.$this->base_datos.” user=”.$this->usuario.” password=”.$this->password) pon un ; al final que en la versión que hay subida al servidor, se me pasó, lo siento.

    Un saludo

  • marcelo
    1 diciembre 2009 - 2:14 am | Enlace permanente

    pienso que tendrian que revisar un poco la clase para poder hacer mas optima y general, usar un poco de polimorfismo y dividir en clases los difierentes tipos de base de datos, en ves de usar tanto case que no es una buena para un programador objeto.

    recomiendo revisar algunos framework como synfony que tienen exentes clases de base de datos, muy bien armadas y utilizando eficientemente OOP.

    saludos

  • marcelo
    1 diciembre 2009 - 2:26 am | Enlace permanente

    ?¿

  • 5 diciembre 2009 - 9:41 am | Enlace permanente

    Buenas marcelo. Por supuesto que se puede mejorar esta clase o utilizar cualquier clase utilizada o incluso algún ORM similar a Hibernate de Java. Esto sólo pretende ser una introducción de cómo confeccionar una clase a modo de ejemplo.

    Un saludo

  • Evelyn
    19 diciembre 2009 - 13:31 pm | Enlace permanente

    Gracias, la conexion salio perfecta, pero si podrías ayudarm en crear una funcion insertar, modificar, eliminar, actualizar, por favor lo necesito.

  • dhamaso
    5 octubre 2010 - 23:05 pm | Enlace permanente

    Oye tu no tienes una clase mas o menos como la que hiciste pero con PDO para php?

    es que busco y busco y nada bueno.
    bueno pues espero tu respuesta haber si tienes auquesea un poquito de codigo.

  • 9 octubre 2010 - 8:19 am | Enlace permanente

    Buenas, no tengo nada hecho en PDO ya que normalmente trabajo con clases que utilizan el patrón de DAOs (Data Access Object) y VO (Value Object).

    Un saludo

  • dhamaso
    8 noviembre 2010 - 21:51 pm | Enlace permanente

    hola marcos, primeramente un saludo, oye con tu clase de conexion, como podria hacer para “cambiar” de base de datos “al vuelo”, por ejemplo:
    en el archivo config.php tengo lo siguiente:

    $host=’localhost’;
    $user=’root’;
    $password=”;
    $db=’pagina_web’;
    entonces cuando creo la instancia de la clase se crea con los datos leidos en el archivo config.php:

    $db=Db::GetInstance();

    y en Db.php he modificado un poco tu clase:


    public static function GetInstance($server="",$userdb="",$passdb="",$data_base="",$manejador=""){
    if (!(self::$_instance instanceof self)){
    self::$_instance=new self($server,$userdb,$passdb,$data_base,$manejador);
    }else{
    return self::$_instance;
    }
    }

    y luego en el constructor me conecto. para tratar de hacer lo siguiente:
    $db=Db::GetInstance('localhost','root','',otra_base');

    pero como te habras dado cuenta la base de datos nunca va a cambiar por que si el objeto ya esta creado lo unico que hace es regresar dicha instancia.

    so, hay alguna manera de hacer eso sin tener que crear un nuevo objeto.

  • dhamaso
    8 noviembre 2010 - 21:52 pm | Enlace permanente

    de antemano gracias y espero tu respuesta, saludos desme México.

  • 9 noviembre 2010 - 0:21 am | Enlace permanente

    Buenas dhamaso,

    deberías crearte una clase padre que se encargue de todo el proceso de conexión y todas diferentes operaciones con la base de datos. Por otro lado, deberías crearte una clase para cada una de las diferentes conexiones a las bases de datos distintas a la que te vayas a conectar. Estas clases heredarán de la clase padre y únicamente se encargarán de pasar los datos de conexión, de esta forma, tendrás los datos de conexión a la base de datos controlados en clases fácilmente modificables y ampliables.

    No se si me he explicado bien, pero en España es algo tarde y tengo bastante sueño.

    Gracias por visitar mi página, que por cierto, por motivos laborales y personales la tengo basante abandonada.

    Un saludo

  • Deja un comentario

    Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

    *

    Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>