Comunidad de diseño web y desarrollo en internet online

Clase para conexión a Base de Datos con PHP, Javascript y MySQL

Que tal! Ahora vengo con un nuevo aporte sobre el manejo de la conexión a la base de datos de forma segura, y sin tener que poner el "include" o "require" cada vez que lo necesitamos usar a lo largo de nuestro proyecto.

Este tutorial abarca PHP, Javascript y MySQL usando PDO.



Básicamente como introducción, los archivos que serán creados son:
  • pdo.mysql.class.php: esta será la clase que nos permitirá obtener los datos y realizar las acciones correspondientes a la interacción con la base de datos.
  • db_config.html: este será básicamente la presentación y dentro de él se incluirá un poco de CSS y sólo unas pocas líneas de javascript para leer el archivo.
  • db_config.php: este se encargará básicamente de "dirigir" la acción a realizar, dependiendo de la petición, es la acción que ejecutará.
  • db.config: este archivo se creará automáticamente al ejecutar el proceso del envío de información a la base de datos, para el logueo (es decir validar la conexión), y lo único que contiene es una cadena de caracteres usada como una llave, es decir, esta cadena de caracteres es el producto de la información de la base de datos encriptada. (Lo que nos permite obtener mayor seguridad).


Al código! Paso a Paso...

pdo.mysql.class.php


Parte 1

Código :

<?php
class DBConnector
{
   private $dbServer;
   private $dbPort;
   private $dbUser;
   private $dbPassword;
   private $dbName;
   private $dbLink;

Aquí se declaran los atributos de nuestra clase, cada uno se le asignó un nombre para obviar que se hace referencia cada uno de ellos.

Parte 2

Código :

public function get_dbLink()
   {
      return $this->dbLink;
   }

Esta función lo único que hace es asignar cualquier objeto que mande llamar el método "get_dbLink()" asignarlo como el atributo "dbLink".

Parte 3

Código :

public function set_dbLink($oDB = true)
   {
      if (! is_object($oDB)) { 
         if (is_bool($oDB)) {
            $_db_config = file_get_contents(FS_CONFIG . 'db.config');
            $_db = unserialize(base64_decode(str_rot13($_db_config)));

            $this->dbServer = $_db->DB_HOST;
            $this->dbPort = $_db->DB_PORT;
            $this->dbUser = $_db->DB_USERNAME;
            $this->dbPassword= $_db->DB_PASSWORD;
            $this->dbName = $_db->DB_DATABASE;
         }

         $dsn = 'mysql:host=' . $this->dbServer . ';'
               . 'port=' . $this->dbPort . ';'
               . 'dbname=' . $this->dbName;

         try {
            @$this->dbLink = new PDO($dsn, $this->dbUser, $this->dbPassword);
         } catch (PDOException $e) {
            printf("Connect failed: %s\n", $e->getMessage());
            exit();
         }
      } else {
         $this->dbLink = $oDB;
      }
   }
  • $oDB es el objeto creado para la interacción con la base de datos
  • FS_CONFIG Como había explicado en el tutorial anterior "Menú con XML y PHP" estas constantes las declaro con anterioridad, evitando así, poner la ruta completa cada vez que la necesito.


Profundizando un poco más


Se cargan los datos guardados en "db.config" en "$_db_config".

Código :

$_db_config = file_get_contents(FS_CONFIG . 'db.config');


$_db obtiene la información de la base de datos decodificando la cadena obtenida de "db.config".

Código :

$_db = unserialize(base64_decode(str_rot13($_db_config)));


Una vez que se "decodifica" la información, se establece cada valor en la variable que se usará.

Código :

$this->dbServer = $_db->DB_HOST;
   $this->dbPort = $_db->DB_PORT;
   $this->dbUser = $_db->DB_USERNAME;
   $this->dbPassword= $_db->DB_PASSWORD;
   $this->dbName = $_db->DB_DATABASE;


$dsn no es más que la variable que contiene la información que se proporcionará a MySQL.

Código :

$dsn = 'mysql:host=' . $this->dbServer . ';'
     . 'port=' . $this->dbPort . ';'
     . 'dbname=' . $this->dbName;

Código :

   try {
      @$this->dbLink = new PDO($dsn, $this->dbUser, $this->dbPassword);
   } catch (PDOException $e) {
      printf("Connect failed: %s\n", $e->getMessage());
      exit();
      }
} else {
   $this->dbLink = $oDB;
 }

Básicamente en esta parte es un manejo de excepciones, donde el "try" se asigna el dbLink, a partir de la instancia de un nuevo objeto del tipo PDO, y después, en caso de que no se pueda realizar la conexión, pues se despliega el mensaje junto con la excepción (esto ayudara a que sea más fácil de detectar los errores). Lo siguiente es un "else" que es el que le corresponde al "if" que se abrió anteriormente, y lo único que ejecuta es que asigna el objeto $oDB a $dbLink.

Parte 4

Código :

public function __construct($_xxx= '', $server = '', $port = '', $user = '', $password = '', $database = '')
   {
      if (strlen($server) > 0) $this->dbServer = $server;
      if (strlen($port) > 0) $this->dbPort = $port;
      if (strlen($user) > 0) $this->dbUser = $user;
      if (strlen($password) > 0) $this->dbPassword = $password;
      if (strlen($database) > 0) $this->dbName = $database;

      //if (! $this->dbLink) {
      $this->set_dbLink();
      //}
   }

Esta función básicamente establece "de lleno" o "totalmente" el enlace con la base de datos, espero se entienda bien esta función, si no cualquier duda no duden en comentarlo, y en cuanto tenga oportunidad contestaré en la medida que mi conocimiento me lo permita.

Parte 5

Código :

function query($sql, $values = array())
   {
      $_result = false;

      if (($_stmt = $this->dbLink->prepare($sql))) {
         if (preg_match_all('/(:\w+)/', $sql, $_named, PREG_PATTERN_ORDER)) {
            $_named = array_pop($_named);
            
            foreach ($_named as $_param) {
               $_stmt->bindValue($_param, $values[substr($_param, 1)]);
            }
         }

         try {
            if (! $_stmt->execute()) {
               print_r($_stmt->errorInfo());
            }
            $_result = $_stmt->fetchAll(PDO::FETCH_ASSOC);
            $_stmt->closeCursor();
         } catch(PDOException $e){
            echo "Excepcion atrapada";
                print_r($e->getMessage());
         }
      }
      
      return $_result;
   }

Esta función es totalmente adaptable (al igual que la clase), he estado explicando un poco menos ya que ya no dispongo del mismo tiempo para realizar el tutorial, de todas formas, reitero si tienes alguna duda no dudes en comentar, estoy en la mejor disposición de ayudar.

Parte 6

Código :

   public function executeSP($spName, $values = array())
   {
      $_rs = $this->query('CALL ' . $spName, $values);

      return $_rs;
   }

Esta función esta mas fácil de explicar ya que la variable "$_rs" adquirirá los datos de la ejecución del store procedure que está almacenado dentro de "$spName" y recibe los parámetros o el arreglo de parámetros en "$values" (esta función la considero por demás útil ya que ayuda a ejecutar store procedures directamente desde PHP).

El código completo:

Código :

<?php
class DBConnector
{
   private $dbServer;
   private $dbPort;
   private $dbUser;
   private $dbPassword;
   private $dbName;
   private $dbLink;

   public function get_dbLink()
   {
      return $this->dbLink;
   }

   public function set_dbLink($oDB = true)
   {
      if (! is_object($oDB)) {
         if (is_bool($oDB)) {
            $_db_config = file_get_contents(FS_CONFIG . 'db.config');
            $_db = unserialize(base64_decode(str_rot13($_db_config)));

            $this->dbServer = $_db->DB_HOST;
            $this->dbPort = $_db->DB_PORT;
            $this->dbUser = $_db->DB_USERNAME;
            $this->dbPassword= $_db->DB_PASSWORD;
            $this->dbName = $_db->DB_DATABASE;
         }

         $dsn = 'mysql:host=' . $this->dbServer . ';'
               . 'port=' . $this->dbPort . ';'
               . 'dbname=' . $this->dbName;

         try {
            @$this->dbLink = new PDO($dsn, $this->dbUser, $this->dbPassword);
         } catch (PDOException $e) {
            printf("Connect failed: %s\n", $e->getMessage());
            exit();
         }
      } else {
         $this->dbLink = $oDB;
      }
   }

   public function __construct($_xxx= '', $server = '', $port = '', $user = '', $password = '', $database = '')
   {
      if (strlen($server) > 0) $this->dbServer = $server;
      if (strlen($port) > 0) $this->dbPort = $port;
      if (strlen($user) > 0) $this->dbUser = $user;
      if (strlen($password) > 0) $this->dbPassword = $password;
      if (strlen($database) > 0) $this->dbName = $database;

      $this->set_dbLink();
   }

   function query($sql, $values = array())
   {
      $_result = false;

      if (($_stmt = $this->dbLink->prepare($sql))) {
         if (preg_match_all('/(:\w+)/', $sql, $_named, PREG_PATTERN_ORDER)) {
            $_named = array_pop($_named);
            
            foreach ($_named as $_param) {
               $_stmt->bindValue($_param, $values[substr($_param, 1)]);
            }
         }

         try {
            if (! $_stmt->execute()) {
               print_r($_stmt->errorInfo());
            }

            $_result = $_stmt->fetchAll(PDO::FETCH_ASSOC);
            $_stmt->closeCursor();
         } catch(PDOException $e){
            echo "Excepcion atrapada";
                print_r($e->getMessage());
         }
      }
      
      return $_result;
   }

   public function executeSP($spName, $values = array())
   {
      $_rs = $this->query('CALL ' . $spName, $values);

      return $_rs;
   }
}
?>


Continuando....

db_config.html


Este archivo será nuestra "cara" para poder configurar la conexión a la base de datos. Sólo lleva estilo elemental, y una vez más (al igual que el tutorial anterior) usé variables para cargar cada elemento usando arrays.

Código :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
   <title>Configuración de Conexión a Base de Datos</title>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <script type="text/javascript" src="..jquery.js"></script>
   <script>
      $(document).ready(
         function () {
            //alert('Listo');
         }
      );
   </script>
   <style type="text/css">
      .frmConfig {
         width:410px;
         font-family: verdana;
         font-size:8pt;
      }
      .frmConfig label {
         line-height: 20px;
         display:inline-block;
         width:130px;
         text-align:right;
      }
      .frmConfig .textbox {
         width:250px;
      }
      .frmConfig fieldset div {
         margin-bottom:5px;
         vertical-align: middle;
      }
      .app-title {
         font-family: Arial;
         font-size:14pt;
         font-weight:bold;
         margin-bottom:10px;
         padding-bottom:5px;
         border-bottom:2px silver solid;
      }
      .result-msg {
         font-family: Arial;
         font-size:10pt;
         margin-top:10px;
         color:blue;
      }
   </style>
</head>
<body>
   <div class="app-title">Root del Proyecto: <?= $_root ?></div>
   <form class="frmConfig" action="./db_config.php?do=saveConfig" method="POST">
      <fieldset>
         <legend>Conexi&oacute;n a Base de Datos</legend>
         <div>
            <label>Nombre o IP de Host:</label>
            <input type="text" id="db_host" class="textbox" name="cnn[DB_HOST]" value="<?= $config->DB_HOST ?>">
         </div>
         <div>
            <label>Puerto de servicio:</label>
            <input type="text" id="db_host" class="textbox" name="cnn[DB_PORT]" value="<?= $config->DB_PORT ?>">
         </div>
         <div>
            <label>Nombre del usuario:</label>
            <input type="text" id="db_username" class="textbox" name="cnn[DB_USERNAME]" value="<?= $config->DB_USERNAME ?>">
         </div>
         <div>
            <label>Contrase&ntilde;a:</label>
            <input type="text" id="db_password" class="textbox" name="cnn[DB_PASSWORD]" value="<?= $config->DB_PASSWORD ?>">
         </div>
         <div>
            <label>Base de datos:</label>
            <input type="text" id="db_database" class="textbox" name="cnn[DB_DATABASE]" value="<?= $config->DB_DATABASE ?>">
         </div>
      </fieldset>
      <div style="margin-top:10px;">
         <button id="btnSave">Guardar</button>
      </div>
      <div class="result-msg">
         <?= $result ?>
      </div>
   </form>
</body>
</html>



Aquí pueden descargar la librería de jQuery que usé.

Lo demás en cuanto al html esta más fácil de digerir.

db_config.php


Aqui es donde se establece la dirección raíz.

Código :

$_root = str_replace('\\', '/', preg_replace('/(.*[\/\x5C]src[\/\x5C]).*/', '$1', $_SERVER['SCRIPT_FILENAME']));


Ahora un par de condiciónes que se activaran dependiendo de la petición que reciban

Código :

if ($_GET['do'] == 'saveConfig') {
   $x = (object) $_POST['cnn'];
   file_put_contents($_root . 'ruta/donde/GUARDARA/el archivo/db.config', str_rot13(base64_encode(serialize($x))));
   $result = 'Configuraci&oacute;n de conexi&oacute;n guardada!';
   $_GET['do'] = 'configForm';
}

if ($_GET['do'] == 'configForm') {
   if (file_exists($_root . 'ruta/de_donde/CARGARA/el archivo/db.config')) {
      $config = unserialize(base64_decode(str_rot13(file_get_contents($_root . 'app/_config/db.config'))));
   }

Observemos la línea siguiente, aquí habría que poner la ruta donde se guardará el archivo "db.config":

Código :

file_put_contents($_root . 'ruta/donde/GUARDARA/el archivo/db.config', str_rot13(base64_encode(serialize($x))));


Y en la siguiente línea es de donde se cargará el archivo "db.config"

Código :

file_exists($_root . 'ruta/de_donde/CARGARA/el archivo/db.config')


Aqui esta el código completo:

Código :

<?
$_root = str_replace('\\', '/', preg_replace('/(.*[\/\x5C]src[\/\x5C]).*/', '$1', $_SERVER['SCRIPT_FILENAME']));

if ($_GET['do'] == 'saveConfig') {
   $x = (object) $_POST['cnn'];
   file_put_contents($_root . 'ruta/donde/guardara/el archivo/db.config', str_rot13(base64_encode(serialize($x))));
   $result = 'Configuraci&oacute;n de conexi&oacute;n guardada!';
   $_GET['do'] = 'configForm';
}

if ($_GET['do'] == 'configForm') {
   if (file_exists($_root . 'ruta/donde/guardara/el archivo/db.config')) {
      $config = unserialize(base64_decode(str_rot13(file_get_contents($_root . 'ruta/donde/guardara/el archivo/db.config'))));
   }
   
   require('./db_config.html');
}
?>

Por último, ¿Cómo voy a llamar a estos archivos para que me genere el "db.config"? Excelente pregunta! básicamente desde nuestro navegador lo que haremos será poner la siguiente dirección:

Código :

localhost/carpeta/donde_se_encuentra/el_archivo/db_config.php


Y al final de esta dirección habrá que poner la petición que es "?do=configForm" quedando de la siguiente manera:

Código :

localhost/carpeta/donde_se_encuentra/el_archivo/db_config.php?do=configForm


Archivos del tutorial

Espero les sirva! Saludos!

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate