CnnMySQL. Clase principal de la Capa de Datos

Esta clase que posteriormente heredaran el resto de las clases (subclases), se encargará de todos los procesos de comunicación con la BD, siendo el punto de unión de la capa con los datos almacenados en la BD.

19-Sep-2016

En la implementación de la capa de datos, vamos a ir definiendo clases que nos permitan realizar el trabajo con los datos de una forma más lógica y sencilla. Entre todas las clases, utilizaremos una principal que se encargará de la comunicación con la BD. Esta clase recibirá el nombre CnnMySQL.

Esta clase que posteriormente heredaran el resto de las clases (subclases), se encargará de todos los procesos de comunicación con la BD, siendo el punto de unión de la capa con los datos almacenados en la BD.

Con esta clase pretendemos minimizar y simplificar al máximo las instrucciones para ejecutar consultas sobre la BD, así como aportar una serie de métodos adicionales de trabajo que resulten útiles para el desarrollo de nuestras aplicaciones.

Cuando ejecutemos una consulta de selección, en lugar de obtener un objeto mysqli_result con la información de la consulta, siempre obtendremos un array asociativo con todas las filas seleccionadas. De esta manera optimizamos el código y los recursos utilizados durante la comunicación.

Implementar paso de argumentos por nombre

La mayoría de los métodos públicos de nuestra clase principal que iremos definiendo a lo largo del módulo, permiten el paso de un número de argumentos opcionales variable, indicando el/los que nos convengan para cada caso.

Para que el trabajo con estos métodos sea más cómodo y eficiente, vamos a implementar una manera de realizar el paso de argumentos opcionales por nombre.

En PHP el paso de parámetros opcionales se suele realizar por posición, definiendo valores por defecto para los argumentos que deseamos que sean opcionales.

Tomemos como ejemplo una función llamada ‘consulta’ que presenta 4 argumentos opcionales.

  function consulta($Tabla=””,$Campos=””,$Where=””,$Sort=””)

A la hora de realizar la llamada a la función estamos obligados a indicar los valores de los argumentos intermedios aunque sólo deseemos enviar el último; es decir, si un método tiene 4 argumentos opcionales como en el caso anterior y sólo le queremos enviar el 3, tenemos que ir indicando obligatoriamente todos los que le preceden hasta llegar al tercero.

  consulta(””, ””, ”id=101”)

En otros lenguajes de programación como es el caso de Vb.NET el paso de los parámetros opcionales a un método lo podemos hacer por nombre del parámetro, no estando obligados a indicar los anteriores y permitiendo enviarlos en cualquier posición.

  consulta(Where:=”id=101”, Campos:=”titulo, fecha”)

Nuestros métodos públicos van a implementar este tipo de paso de parámetros opcionales, utilizando un array como único argumento con valor por defecto de vacío. Será un array asociativo donde cada clave representará el nombre del parámetro y su valor el contenido del parámetro.

  function consulta(array $args=[])

A la hora de realizar la llamada al procedimiento, le tendremos que enviar los parámetros por medio de un array asociativo indicando el nombre del parámetro y el valor que deseamos asignarle, sin importar el orden en el que vayamos indicando los parámetros, o un array construido previamente.

  consulta([‘Tabla’=>’cursos’,’Where’=>’categoria=”PHP”’])
  -----------------------------------------------------------------
  $args[’Tabla’]=’cursos’;
  $args[’Where’]=’categoria=”PHP”’;
  consulta($args);

El método cuando se ejecute, simplemente irá comprobando si se ha definido un parámetro determinado para actuar en consecuencia.

function consulta(array $args=[]){
    if(isset($args['Tabla'])) $Tabla=$args['Tabla'];
    if(isset($args['Campos'])) $Campos=$args['Campos'];
    if(isset($args['Where'])) $Where=" WHERE (".$args['Where'].")";
    …
    …
    …
}

Archivo de configuraciones

Para conseguir una mayor independencia y reutilización de las clases para otros proyectos, los datos necesarios para establecer la conexión con la BD, como puedan ser el host, base de datos, usuario, clave, etc.., los almacenaremos en un archivo ini (cnn.ini) en nuestra carpeta de clases, que se cargará desde la clase principal antes de realizar la conexión a la BD.

El contenido del archivo estará formado por secciones con las propiedades y sus valores. En la sección [BaseDatos] se definirán las propiedades para realizar la conexión.

Contenido del archivo cnn.ini:

[BaseDatos]
host = dirección del host
bd = nombre de la base de datos
usuario = usuario de acceso a la bd
clave = contraseña del usuario

Si posteriormente deseamos añadir nuevas propiedades configurables a nuestra clase, sólo tendremos que ir añadiéndolas al archivo en nuevas secciones.

Para realizar la carga de la información contenida en el archivo cnn.ini, nos serviremos de la función: parse_ini_file (para almacenar el contenido en un array asociativo).

Clase CnnMySQL

Estructura de la clase

Vamos a definir la clase más importante de nuestra capa de datos; es decir, la clase principal de trabajo.

El contenido de la clase se dividirá en:

  • Propiedades de la clase, ya sean públicas, privadas o protegidas.
  • Constructor y destructor de la clase desde donde realizaremos la conexión y desconexión respectivamente.
  • Métodos privados internos de trabajo, utilizados por los métodos públicos.
  • Métodos públicos accesibles a las subclases y objetos instanciados.
Bloques clase CnnMySQL

Para empezar, creamos un archivo en nuestra carpeta de clases con el nombre class.cnnmysql.php, con la definición de la clase.

define("FILECFG","cnn.ini");

class CnnMySQL extends mysqli_sql_exception {
    ..
    ..
    ..
}

La constante FILECFG, define el nombre del archivo de configuración ‘.ini’ que almacena los valores para realizar la conexión a la BD.

Observar como en la definición de la clase, realizamos la herencia de la clase mysqli_sql_exception por medio de la palabra clave ‘extends’.

Esta clase encargada de gestionar las excepciones de mysqli la necesitamos para poder capturar los posibles avisos y/o errores que se produzcan durante el proceso de ejecución de sentencias sobre la BD, como puedan ser: conexión, ejecución de una consulta, liberación de un recurso, etc...

Definición de las propiedades de la clase

Las primeras líneas de código que vamos a introducir serán las destinadas a la definición de sus propiedades, que consisten en una serie de variables de trabajo necesarias para el funcionamiento de la clase y sus métodos.

Para establecer los niveles de visibilidad de las propiedades, las declararemos de tres tipos:

  • Públicas: se puede acceder a ellas desde cualquier sitio (clase, subclases y objetos).
  • Protegidas: se puede acceder a ellas desde la propia clase y desde las clases heredadas (subclases).
  • Privadas: sólo se puede acceder a ellas desde la clase que las declara.
class CnnMySQL extends mysqli_sql_exception {
//------------------------------------------------------------------------------------------------
//     PROPIEDADES DE LA CLASE
//------------------------------------------------------------------------------------------------

// PRIVADAS
//------------------------------------------------------------------------------------------------
//  Conexión a la BD
private $Servidor;
private $BaseDatos;
private $Usuario;
private $Clave;
// Objeto que representa la conexión actual abierta
private static $Conector;
// Indica el total de solicitudes de conexión actuales
private static $SolicitudConectar=0;
// Indicador del estado de la última consulta que se ha ejecutado
private $Estado;
// Propiedades utilizadas para construir un comando DML (select, insert, update o delete)
private $Distinct;
private $Tabla;
private $Campos;
private $GroupBy;
private $Where;
private $Ordenar;
private $Limites;
private $CampoValor=[];
// Total de columnas devueltas por la última consulta
private $TotColumnas;
// Array con el nombre de las columnas que formaban la última consulta de selección
private $Columnas=[];

// PROTEGIDAS
//------------------------------------------------------------------------------------------------
// Nombre de la tabla de la BD sobre la que se ejecutan las sentencias por defecto
protected $TablaBD;
// Total de registros seleccionados o afectados por la última consulta ejecutada
protected $TotRegistros;

NOTA: Las propiedades $Conector y $SolicitudConectar se declaran como estáticas para que puedan mantener su valor entre instancias de la clase y que todos los objetos heredados que estén en ejecución tengan la misma visión de estas propiedades.

Constructor y Destructor de la clase

La conexión a la BD se realizará desde el constructor, en el momento de crear el objeto de la clase y la desconexión desde su destructor, cuando el objeto sea destruido implícitamente con la sentencia unset(objeto) o cuando no hayan otras referencias al objeto.

Constructor

Realiza la carga de los datos del archivo de configuración cnn.json descrito al principio, para posteriormente llamar al método encargado de abrir la conexión con la BD.

Cada vez que se ejecute este método se incrementará el valor de la propiedad $SolicitudConectar, para llevar un contador de las solicitudes realizadas y que aún están vigentes.

Si en el momento de realizar una nueva solicitud de conexión, existen objetos abiertos (clases heredadas) que aún se estén ejecutando, se utilizará la conexión actual abierta ($Conector), de lo contrario se abrirá una nueva.

El constructor puede recibir opcionalmente el nombre de la tabla o vista sobre la que se ejecutarán todas las consultas. Si no se indica en este momento se puede establecer posteriormente mediante la propiedad TablaBD.

Destructor

Realizará una llamada al método encargado de realizar la desconexión de la BD.

Cada vez que se ejecute el método de solicitud de desconexión se decrementará el contador de solicitudes abiertas $SolicitudConectar, si su valor a llegado a 0 significará que no quedan más objetos abiertos y se procederá a la desconexión de la BD, de lo contrario se mantendrá la conexión abierta.


// CONSTRUCTOR DE LA CLASE
//------------------------------------------------------
function __construct($tabla_vista=NULL) { 
    // Cargamos los valores del archivo de configuración
    $this->CargarCfg();
    // Abrimos la conexión con la base de datos
    $this->AbrirConexion();
    // Establece el nombre de la tabla o vista que se utilizará por defecto para ejecutar las consultas
    $this->TablaBD=$tabla_vista;	
}

// CARGA LOS VALORES DEL FICHERO DE CONFIGURACIONES
private function CargarCfg() {
    // Construimos ruta de acceso al fichero de configuraciones
    $FichCfg = __DIR__.DIRECTORY_SEPARATOR.FILECFG;	
    // Si no existe el fichero de configuraciones cancelamos el script en ejecución
    if(!file_exists($FichCfg)) {
       printf("Fallo al cargar las configuraciones.<br />No se ha localizado el archivo: %s<br />",$FichCfg);
       exit();
    }
    // Leemos el contenido del fichero, separando las secciones
    $cfg_db=parse_ini_file($FichCfg,true);
    // Si no se localiza la sección BaseDatos, cancelamos el script en ejecución
    if(!isset($cfg_db['BaseDatos'])) {
       printf("Fallo en el fichero de configuraciones.<br />No se ha localizado la sección [BaseDatos].<br />");
       exit();
    }
    // Cargamos los datos para realizar la conexión
    $this->Servidor=$cfg_db['BaseDatos']['host'];
    $this->BaseDatos=$cfg_db['BaseDatos']['bd'];
    $this->Usuario=$cfg_db['BaseDatos']['usuario'];
    $this->Clave=$cfg_db['BaseDatos']['clave'];
}

// ABRE LA CONEXIÓN CON LA BD Y CREA EL OBJETO Conector
private function AbrirConexion() {
    // Incrementamos contador de solicitudes de conexión actuales
    self::$SolicitudConectar++;
     // Si el objeto Conector aun está inicializado lo utilizamos para la solicitud actual 
    if(!empty(self::$Conector)) { return; } // Salimos
    // Establecemos los niveles de aviso de mysqli
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    // Iniciamos bloque try catch para la conexión a la base de datos
    try {
        // Creamos objeto Conector con los datos actuales de conexión
        self::$Conector= new mysqli($this->Servidor, $this->Usuario, $this->Clave, $this->BaseDatos); 
        // Indicamos que la comunicación con la base de datos es en UTF8 que suele ser el juego de caracteres que se utiliza en los encabezados de muchas páginas web
        self::$Conector->query("SET NAMES 'UTF8'");
    } catch (mysqli_sql_exception $e) {
        // Mostramos mensaje completo en el navegador y finalizamos los scripts en ejecución
        printf("Fallo en la conexi&oacute;n: %s<br />Servidor: %s<br />Base Datos: %s",mysqli_connect_error(),$this->Servidor,$this->BaseDatos);
        exit();
    } 
}
    
// DESTRUCTOR DE LA CLASE
//------------------------------------------------------
function __destruct() {
    // Solicitamos el cierre de la conexión
    $this->CerrarConexion();
}

// CIERRA LA CONEXION CON LA BASE DE DATOS
private function CerrarConexion() {
    // Decrementamos el contador de solicitudes de conexión actuales
    self::$SolicitudConectar--;
    // Si ya no quedan solicitudes de conexión abiertas
    if(self::$SolicitudConectar==0) {
        // Realizamos desconexión de la BD
        @self::$Conector->close();
        // Limpiamos el objeto Conector
        @self::$Conector=NULL;
    }
}

Métodos privados de trabajo

Para la correcta funcionalidad de la clase es necesario definir una serie de métodos de trabajo que posteriormente serán aprovechados por los métodos públicos de la clase.

A continuación iremos describiendo los métodos privados de la clase por sus características.

Total de registros afectados

Cada vez que se ejecute una consulta, la clase obtendrá el total de registros seleccionados (SELECT) o afectados (INSERT, UPDATE y DELETE), para establecer el valor de la propiedad $TotRegistros.

  • TotRegSelect: recibe como argumento el objeto mysqli_result obtenido en la ejecución de la consulta y devuelve el total de registros que han sido seleccionados.
  • TotRegAccion: consulta el objeto $Conector después de llevar a cabo una consulta de acción y devuelve el total de registros afectados por la consulta.
// Obtiene el total de registros seleccionados por una consulta de selección
//--------------------------------------------------------------------------------------------
private function TotRegSelect(&$result) {
    if(empty($result)) return 0;
    $Total=0;
    try {
       $Total=$result->num_rows;
    } catch (mysqli_sql_exception $e) {
       printf("ERROR: %s<br/>",$e->getMessage());
    }
    return $Total;
}
    
// Obtiene el total de registros afectados por una consulta de actualización
//--------------------------------------------------------------------------------------------
private function TotRegAccion() {
    $Total=0;
    try {
       $Total=self::$Conector->affected_rows;
    } catch (mysqli_sql_exception $e) {
       printf("ERROR: %s<br/>",$e->getMessage());
    }
    return $Total;
}

Columnas

Al igual que ocurre con el total de registros, la clase cada vez que se ejecute una consulta de selección obtendrá el total y el nombre de las columnas obtenidas en la consulta. Estos valores los utiliza para establecer el valor de las propiedades: $TotColumnas y $Columnas.

  • TotalColumnas: recibe como argumento el objeto mysqli_result obtenido en la ejecución de la consulta y devuelve el total de campos (columnas) seleccionados.
  • NombreColumnas: recibe como argumento el objeto mysqli_result obtenido en la ejecución de la consulta y devuelve un array con el nombre de los campos (columnas) seleccionados.
// Obtiene el total de columnas de la consulta de selección que se ha ejecutado
//--------------------------------------------------------------------------------------------
private function TotalColumnas(&$result) {
    if(empty($result)) return 0;
    return $result->field_count;
}
// Obtiene el nombre de las columnas de la consulta de selección que se ha ejecutado
//--------------------------------------------------------------------------------------------
private function NombreColumnas(&$result) {
    if(empty($result)) return NULL;
    $Nombres=array();
    while ($finfo = $result->fetch_field()) {$Nombres[]=$finfo->name;}
    return $Nombres;
}

Liberar recursos

Cuando se ejecuta una consulta de selección con mysqli se obtiene un objeto de tipo mysqli_result que almacena la información necesaria recuperar la información de la consulta. Una vez que hemos recuperado los datos, se recomienda liberar los recursos utilizados por el objeto mysqli_result.

El método recibe un objeto  mysqli_result y libera los recursos utilizados.

// Liberar un recurso una vez ejecutado
//------------------------------------------------------------------------------------------------
private function LiberaRecurso(&$result) {
   if(!empty($result)) $result->free();
}

Ejecutar consultas

A la hora de ejecutar consultas, la clase dispone de dos métodos, el primero ‘EjecutarConsulta’ es el encargado de ejecutar cualquier consulta sobre la BD que devuelve un objeto de tipo mysqli_result y el segundo ‘ArraySelect’ utilizando el objeto devuelto por el primer método, devuelve un array asociativo con el resultado de la consulta.

EjecutarConsulta:

  • Método encargado realmente de ejecutar las consultas y devolver el objeto mysqli_result resultante si son consultas de selección o un valor booleano para el resto de consultas.
  • También se encarga de establecer el valor de algunas de las propiedades de la clase.
  • Recibe como argumento la consulta SQL que se tiene que ejecutar.
// Devuelve el objeto resulset de una consulta de selección o el valor booleano para el resto
//--------------------------------------------------------------------------------------------
private function EjecutarConsulta($SQL) {
// Inicializamos las propiedades antes de ejecutar la consulta
    $this->TotRegistros=0;
    $this->TotColumnas=0;
    $this->Columnas=[];
// Inicializamos la variable donde se almacenará el objeto mysqli_result
    $result=NULL;
    try {
    // Ejecutamos la consulta SQL
       $result=self::$Conector->query($SQL);
    // Si es una consulta de selección
       if(substr(strtoupper($SQL),0,6)==='SELECT') {
          $this->TotRegistros=$this->TotRegSelect($result);
          $this->Estado=($this->TotRegistros>0);
          $this->TotColumnas=$this->TotalColumnas($result);
          $this->Columnas=$this->NombreColumnas($result);
       } else {
          $this->Estado=$result;
          $this->TotRegistros=$this->TotRegAccion();
       }
    } catch (mysqli_sql_exception $e) {
       printf("ERROR al ejecutar la consulta: %s<br/>%s<br/> ", $SQL, $e->getMessage());
    }
    return $result;
}

Obtener las filas de la consulta

ArraySelect:

  • Realiza una llamada al método EjecutarConsulta y obtiene todas las filas de la consulta en un array asociativo que posteriormente devolverá como resultado.
  • Una vez obtenido el array, libera los recursos utilizados por el objeto mysqli_result.
  • Resulta más óptimo que el método EjecutarConsulta, ya que una vez devueltos los registros libera los recursos utilizados para evitar una carga de trabajo en la conexión a la BD.
// Ejecutar una consulta select y obtener un array asociativo con los registros seleccionados
//--------------------------------------------------------------------------------------------
private function ArraySelect($SQL) {
    $Registros=[];
    $result = $this->EjecutarConsulta($SQL);
    if($this->Estado) $Registros=$result->fetch_all(MYSQLI_ASSOC);
    $this->LiberaRecurso($result);
    return $Registros;
}

Preparar las partes del comando DML

Cuando se ejecutan los métodos públicos (select, insert, update, etc..) para la ejecución de consultas, la clase inicializa y prepara cada una de las partes que formarán el comando DML que se va a ejecutar.

ResetArgs:

  • Reinicia las partes del comando DML antes de procesar los argumentos recibidos por los métodos de ejecución de consultas.
// Reinicia los valores por defecto de los argumentos utilizados por las funciones select, insert, update y delete
//--------------------------------------------------------------------------------------------
private function ResetArgs() {
  $this->Campos='*';           // Se asumen todos los campos
  $this->Tabla=$this->TablaBD; // Se utiliza la tabla recibida en el constructor
  $this->GroupBy='';           // Sin agrupaciones
  $this->Where='';             // Sin filtrados
  $this->Ordenar='';           // Sin Ordenación
  $this->Limites=$this->Limit; // Se establecen como límites el valor de la propiedad Limit
  $this->CampoValor=NULL;      // No se establecen valores a los campos
}

GetArgs:

  • Realiza una llamada a ResetArgs, para reiniciar las propiedades que definen las partes del comando.
  • Establece el valor de cada parte del comando DML en función de los argumentos que se hayan recibido en los métodos de ejecución de consultas.
// Ejecutar una consulta select y obtener un array asociativo con los registros seleccionados
//--------------------------------------------------------------------------------------------
private function GetArgs(array $args=[]) {
	$this->ResetArgs();	
if(isset($args['Tabla'])) $this->Tabla=$args['Tabla'];
if(isset($args['Campos'])) $this->Campos=$args['Campos'];
if(isset($args['GroupBy'])) $this->GroupBy=' GROUP BY '.$args['GroupBy'];
if(isset($args['Where'])) $this->Where=' WHERE ('.$args['Where'].')';
if(isset($args['Sort'])) $this->Ordenar=' ORDER BY '.$args['Sort'];
if(isset($args['Limit'])) $this->Limites=' LIMIT '.$args['Limit'].';';
if(isset($args['CampoValor'])) $this->CampoValor=$args['CampoValor']; }

Preparar los valores utilizados para insertar o actualizar registros

Cada vez que se ejecuten los métodos públicos insert o update, tenemos que procesar los valores que se asignan a los campos en función del tipo de dato del que se trate. Si los valores son de tipo nulo, tendremos que asignar la palabra NULL al campo, si son de tipo cadena o fecha, tendremos que encerrarlos entre comillas simples, si son numéricos asignarlos tal cual y si son booleanos convertirlos a literales true o false.

Para realizar esta tarea, la clase utiliza un método que devuelve el valor según lo establecido por el tipo de dato.

GetValor:

  • Recibe el valor a procesar y lo devuelve formateado al tipo de dato que le corresponda.
//Obtiene el valor de un campo para un comando insert / update en función del tipo (nulo, numérico, booleano o cadena)
//--------------------------------------------------------------------------------------------------------------------
private function GetValor($Valor) {
    if(is_null($Valor)) return "NULL";
    elseif(is_numeric($Valor)) return "'".$Valor."'";
    elseif(is_bool($Valor)) return ($Valor)? 'true':'false';
    else return "'".str_replace("'","\'",$Valor)."'";
}

Métodos públicos de la clase

Estado de la última ejecución

Una consulta se considerará que se ha ejecutado de forma correcta si:

  • Se han obtenido registros en la última consulta de selección (SELECT).
  • No se han producido errores en la última consulta de acción, inserción o eliminación (UPDATE, INSERT, DELETE). Este valor se ha obtenido como resultado de la ejecución de la consulta.

Para consultar el estado de la última ejecución, la clase utiliza un método que devuelve el valor de la propiedad privada Estado. Esta propiedad ha sido manipula desde el método privado EjecutarConsulta().

  • get_estado: devuelve un valor booleano que indica el estado de la última consulta ejecutada.
// Indica si hay registros seleccionados o el estado de la última consulta ejecutada
//------------------------------------------------------------------------------------------------
private function get_estado() {
	return $this->Estado;
}

Activar la selección de registros únicos

Si deseamos que las consultas de selección devuelvan sólo registros únicos, activaremos el indicador Distinct de la clase por medio del método set_distinct.

set_distinct:

  • Recibe como argumento un valor booleano que activa/desactiva este indicador. Por defecto este argumento es ‘false’ para desactivar la selección de registros únicos.

get_distinct:

  • Obtiene un valor booleano del estado del indicador de consultas únicas.
// Establece selección de registros únicos en las consultas de selección
public function set_distinct($estado=false) {
    $this->Distinct=($estado)? 'DISTINCT':'';
}
// Obtiene el indicador de  selección de registros únicos en las consultas de selección
public function get_distinct() {
     return ($this->Distinct==='DISTINCT');
}

Establecer límite de registros obtenidos

A la hora de ejecutar consultas de selección, por defecto se devuelven todos los registros obtenidos por la consulta. Si deseamos establecer un límite de registros para todas las consultas que se vayan a ejecutar, podemos establecerlo utilizando el método set_limit.

set_limit:

  • Recibe como argumento el total de registros que deseamos obtener. Se puede indicar con número para limitar el total de registros, o utilizando la sintaxis ‘DesdeReg, TotalReg’ para limitar la cantidad de registros a partir de un registro concreto.
  • Si no indicamos ningún valor desactivará los límites para las consultas de selección.

get_limit:

  • Obtiene los límites actuales.
// Establece límite de registros únicos en las consultas de selección
public function set_limit($limites=NULL) {
   $this->Limites=(!is_null($limites))? "LIMIT $limites":$limites;
}
// Obtiene el límite de registros únicos en las consultas de selección
public function get_limit() { return $this->Limites; }

Obtener el total de registros

Si después de ejecutar cualquier consulta deseamos conocer el total de registros que se han seleccionado o que se han visto afectados por la consulta, podemos utilizar el método get_totregistros.

get_totregistros:

// Obtiene el total de registros seleccionados por la última consulta de selección o afectados por la última consulta de acción
public function get_totregistros() {
  return $this->TotRegistros;
}

Columnas

Después de ejecutar una consulta, podemos obtener el total y nombre de cada una de las columnas obtenidas.

get_totcolumnas:

  • Devuelve el total de columnas de la última consulta de selección.

get_columnas:

  • Devuelve un array con el nombre de las columnas de la última consulta de selección.
// Obtiene el total de columnas que forman parte de la última consulta de selección ejecutada
public function get_totcolumnas() {
    return $this->TotColumnas;
}
// Obtiene el nombre de las columnas que forman parte de la última consulta de selección ejecutada
public function get_columnas() {
    return $this->Columnas;
}

Ejecutar comandos SELECT

select:

  • Es el método encargado de ejecutar las consultas de selección.
  • Tiene 6 argumentos opcionales:
    • Tabla -> nombre de la tabla o vista sobre la que se ejecutará el comando SELECT. Si se omite utilizará el valor de la propiedad TablaBD. Es obligatorio.
    • Campos -> nombre de los campos que deseamos seleccionar. Si se omite obtendrá todos los campos.
    • GroupBy -> nombre de los campos por los que se desea realizar una agrupación.
    • Where -> expresión que se aplicará como condición o filtro a la selección. Si se omite no se aplicará ningún filtro a la selección.
    • Sort -> campos por los que deseamos ordenar el resultado. Si se omite no se realizará ordenación de filas.
    • Limit -> establece los límites de selección utilizando la sintaxis ‘DesdeReg, TotalReg’ para esta consulta. Si se omite, se asumirá el valor de la propiedad Limit establecida por el método set_limit.
  • Con el valor de los 6 argumentos crea el comando SELECT necesario para ejecutar la consulta.
  • Antes de ejecutar la consulta invoca al método GetArgs, para establecer las partes de la consulta.
  • Realiza una llamada al método ArraySelect con el comando SELECT que se ha construido y devuelve un array asociativo con las filas seleccionadas en la consulta.
  • Si posteriormente deseamos consultar el total de registros seleccionados podemos utilizar el método get_totregistros().

 

// Ejecutar consultas de selección (SELECT)
//------------------------------------------------------------------------------------------------
function select(array $args=[]) {    
   // Obtenemos los argumentos
   $this->GetArgs($args);
   // Si no se ha indicado la tabla devuelve NULL
   if(empty($this->Tabla)) return NULL;
   // Construimos la consulta
   $StrSQL=sprintf("SELECT %s %s FROM %s %s %s %s %s", $this->Distinct, 
                                                       $this->Campos, 
                                                       $this->Tabla,
                                                       $this->GroupBy,
                                                       $this->Where,
                                                       $this->Ordenar,
                                                       $this->Limites);
   // Devuelve el array asociativo con las filas obtenidas como resultado de la consulta
    return $this->ArraySelect($StrSQL);
}

selectHTML:

  • Este método es similar al método select, con la diferencia de que como resultado nos devuelve una cadena que contiene una tabla HTML utilizando los estilos del framework BootStrap, con las filas obtenidas en la consulta.
  • Admite los mismos argumentos que el método select, incluyendo uno nuevo:
    • Estilo -> número del 1 al 4 que indica el estilo que deseamos aplicar a la tabla HTML.
  • Realiza una llamada al método select con los argumentos recibidos y con el array obtenido crea la tabla HTML.
// Ejecutar consultas de selección y devuelve el resultado en una tabla html utilizando los estilos de bootstrap
//------------------------------------------------------------------------------------------------
function selectHTML(array $args=[]) {
    // Obtenemos el array con las filas de la consulta llamando al método select
    $Registros=$this->select($args);
    $Estilo=(isset($args['Estilo']))? $args['Estilo']:1;
    // Comprobamos el parámetro Estilo
    switch($Estilo) {
       case 1: $Estilo="bordered"; break;
       case 2: $Estilo="striped"; break;
       case 3: $Estilo="hover"; break;
       case 4: $Estilo="condensed"; break;
       default: $Estilo="bordered";
    }
    // Creamos div contenedor de la tabla
    $Tabla='<div class="table-responsive">';
    // Creamos la tabla y establecemos la clase bootstrap según el valor del parámetro Estilo
    $Tabla.='<table id="tab_listados" class="table table-'.$Estilo.'">';
    $Tabla.='<tbody>';
    // La fila de títulos la creamos con los nombres de las columnas obtenidas en la consulta
    $Tabla.='<tr>';
    foreach($this->Columnas as $NombreCampo) {
       $Tabla.='<th>'.$NombreCampo.'</th>';
    }
    $Tabla.='</tr>';
    // Recorremos el array para crear las filas de la tabla
    foreach($Registros as $Registro) {
       $Tabla.='<tr>';
       foreach($Registro as $Campo=>$Valor) {
          $Tabla.='<td>'.$Valor.'</td>';    
       }
       $Tabla.='</tr>';                  
    }
    $Tabla.='</tbody>';
    $Tabla.='</table>';
    $Tabla.='</div>';
    return $Tabla;
}

field_value:

  • Obtiene el valor de un campo de una tabla o vista, aplicándole una condición.
  • Admite los mismos argumentos que el método select, incluyendo uno nuevo:
    • Campo -> nombre del campo que deseamos obtener. Este argumento sustituye al argumento Campos del método select. Es obligatorio.
  • Realiza una llamada al método select con los argumentos recibidos y devuelve el valor del campo que se hubiera indicado en el argumento ‘Campo’.
// Devuelve el valor de un campo de una tabla con una condición determinada
//------------------------------------------------------------------------------------------------
function field_value(array $args=[]) {
    if(!isset($args['Campo'])) return NULL;
    $args['Campos']=$args['Campo'];
    $Registro=$this->select($args);
    if($Registro) return $Registro[0][$args['Campo']];
    else return NULL;
}

Ejecutar comandos INSERT

insert:

  • Se encarga de ejecutar las consultas para insertar registros en la tabla.
  • Admite 2 argumentos:
    • Tabla -> nombre de la tabla o vista sobre la que se ejecutará el comando INSERT. Si se omite utilizará el valor de la propiedad TablaBD. Es obligatorio.
    • CampoValor -> array asociativo con el nombre de los campos y los valores para el nuevo registro siguiendo el diseño [‘Campo1’=>Valor, ‘Campo2’=>Valor, ...].Es obligatorio.
  • Utiliza el método GetValor para asignar los valores apropiados a los campos.
  • Construye el comando INSERT necesario para insertar el registro, ejecuta la consulta y devuelve el estado de la ejecución.
  • Si posteriormente deseamos consultar el total de registros insertados podemos utilizar el método get_totregistros().
// Ejecutar consultas de inserción (INSERT)
//------------------------------------------------------------------------------------------------
public function insert(array $args=[]) {
   $this->GetArgs($args);
   if(empty($this->CampoValor) || empty($this->Tabla)) return false;
   $Campos=[];
   $Valores=[];
   foreach($this->CampoValor as $Campo => $Valor) {
      $Campos[]=$Campo;
      $Valores[]=$this->GetValor($Valor);
   }
   $CamposTabla=implode(",",$Campos);
   $ValoresCampos=implode(",",$Valores);
   $StrSQL=sprintf("INSERT INTO %s (%s) VALUES (%s)",$this->Tabla, $CamposTabla, $ValoresCampos);
   $this->EjecutarConsulta($StrSQL);
   return $this->get_estado();
}

Ejecutar comandos UPDATE

update:

  • Se encarga de ejecutar las consultas para actualizar registros de la tabla.
  • Admite 3 argumentos:
    • Tabla -> nombre de la tabla o vista sobre la que se ejecutará el comando UPDATE. Si se omite utilizará el valor de la propiedad TablaBD. Es obligatorio.
    • Where -> expresión que se aplicará como condición para realizar la actualización. Si se omite se actualizarán todas las filas de los campos indicados en el parámetro CampoValor.
    • CampoValor -> array asociativo con el nombre de los campos y los valores para actualizar el registro siguiendo el diseño [‘Campo1’=>Valor, ‘Campo2’=>Valor, ...]. Es obligatorio.
  • Construye el comando UPDATE necesario para actualizar el/los registros, ejecuta la consulta y devuelve un valor booleano que indica si se han podido actualizar registros (true) o no (false).
  • Utiliza el método GetValor para asignar los valores apropiados a los campos.
  • Si posteriormente deseamos consultar el total de registros actualizados podemos utilizar el método get_totregistros().
// Ejecutar consultas de actualización (UPDATE)
//------------------------------------------------------------------------------------------------
public function update(array $args=[]){
   $this->GetArgs($args);
   if(empty($this->CampoValor) || empty($this->Tabla)) return false;
   $CamposValores=[];
   foreach($this->CampoValor as $Campo => $Valor) {
       $CamposValores[]="$Campo=".$this->GetValor($Valor);
    }            
    $Campos=implode(",",$CamposValores);
    $StrSQL=sprintf("UPDATE %s SET %s %s",$this->Tabla, $Campos, $this->Where);
    $this->EjecutarConsulta($StrSQL);
    return $this->get_estado();
}

Ejecutar comandos DELETE

delete:

  • Se encarga de ejecutar las consultas de eliminación.
  • Admite 2 argumentos:
    • Tabla -> nombre de la tabla o vista sobre la que se ejecutará el comando DELETE. Si se omite utilizará el valor de la propiedad TablaBD. Es obligatorio.
    • Where -> expresión que se aplicará como condición para realizar la eliminación. Es obligatorio.
  • Construye el comando DELETE necesario para eliminar el/los registros, ejecuta la consulta y devuelve un valor booleano que indica si se han podido eliminar registros (true) o no (false).
  • Si posteriormente deseamos consultar el total de registros actualizados podemos utilizar el método get_totregistros().
// Ejecutar consultas de eliminación (DELETE)
//------------------------------------------------------------------------------------------------
function delete($args=NULL) {
   $this->GetArgs($args);
   if(empty($this->Where) || empty($this->Tabla)) return false;
    $StrSQL=sprintf("DELETE FROM %s %s",$this->Tabla, $this->Where);
    $this->EjecutarConsulta($StrSQL);
    return $this->get_estado();
}

Realizar cálculos de totales

count:

  • Ejecuta la típica consulta de totales (COUNT) sobre una tabla para contar los registros que cumplen una condición. Si no se especifica condición, contará todos los registros de la tabla o vista.
  • Admite los mismos argumentos que el método select. El argumento ‘Campos’ será ignorado.
  • Realiza una llamada al método field_value, utilizando como argumento ‘Campo’ el valor ‘COUNT(*)’ y devuelve el total de registros contados.
public function count(array $args=[]) {
    $args['Campo']='COUNT(*)';
    return $this->field_value($args);
    }

sum:

  • Ejecuta una consulta de totales sobre una tabla para sumar el valor de una columna de los registros que cumplen una condición. Si no se especifica condición, sumará para todos los registros de la tabla o vista.
  • Admite los mismos argumentos que el método select, añadiendo uno nuevo:
    • Campo -> nombre del campo con el que deseamos realizar el cálculo. Este argumento sustituye al argumento Campos del método select. Es obligatorio.
  • Realiza una llamada al método field_value, utilizando como argumento ‘Campo’ la expresión ‘SUM(NombreColumna)’ y devuelve el resultado.
public function sum(array $args=[]) {
    $args['Campo']='SUM('.$args['Campo'].')';
    return $this->field_value($args);
}

avg:

  • Ejecuta una consulta de totales sobre una tabla para calcular el promedio de una columna de los registros que cumplen una condición. Si no se especifica condición, sacará el promedio para todos los registros de la tabla o vista.
  • Admite los mismos argumentos que el método select, añadiendo uno nuevo:
    • Campo -> nombre del campo con el que deseamos realizar el cálculo. Este argumento sustituye al argumento Campos del método select. Es obligatorio.
  • Realiza una llamada al método field_value, utilizando como argumento ‘Campo’ la expresión ‘AVG(NombreColumna)’ y devuelve el resultado.
public function avg(array $args=[]) {
    $args['Campo']='AVG('.$args['Campo'].')';
    return $this->field_value($args);
}

Con este método damos por finalizada la primera versión de nuestra clase principal con la que poder implementar posteriormente una capa de datos para nuestras aplicaciones web.

Diagrama de la clase

En la siguiente imagen podemos observar el entramado interno de las llamadas entre los métodos privados, públicos y las propiedades de la clase. Se puede apreciar que prácticamente todos los métodos de ejecución de consultas directa o indirectamente hacen uso del método 'EjecutarConsulta' que resulta ser uno de los más importantes de nuestra capa ya que es el encargado de ejecutar las consultas y de inicializar algunas de las propiedades que posteriormente podemos consultar.

.

Esquema de llamadas clase CnnMySQL