Login   Register  
PHP Classes
elePHPant
Icontem

File: class.littledb.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Cody Roodaka  >  Little DB  >  class.littledb.php  >  Download  
File: class.littledb.php
Role: Class source
Content type: text/plain
Description: Clase (utilizando MySQLi)
Class: Little DB
Prepare and execute MySQL query results
Author: By
Last change: -Bug fixes
-Error & Log Handling
-Select Function
-Magic Methods
Date: 10 months ago
Size: 16,530 bytes
 

Contents

Class file image Download
<?php
/**
 * Clase de Abstracción de bases de datos Sencilla y de fácil uso.
 * @package class.littledb.php
 * @author Cody Roodaka <roodakazo@hotmail.com>
 * @author Ignacio Daniel Rostagno <ignaciorostagno@vijona.com.ar>
 * @version  $Revision: 0.2.9
 * @access public
 * @see https://github.com/roodaka/littledb
 */

class LittleDB
 {
  // Instancia de LittleDB
  protected static $instance = null;

  /**
   * Recurso MySQL
   * @var resource
   */
  public $conn = null;

  /**
   * Arreglo con los datos de conexión al servidor MySQL
   * @var array
   */
  protected $data = array(
   'host' => null,
   'port' => null,
   'user' => null,
   'pass' => null,
   'name' => null
   );

  /**
   * Función de registro
   * @var array|string
   */
  protected $logger = null;

  /**
   * Función de manejo de errores
   * @var array|string
   */
  protected $errors = null;

  /**
   * Prefijo de la base de datos
   * @var string
   */
  public $prefix = '';

  /**
   * Cantidad de consultas realizadas
   * @var integer
   */
  public $count = 0;



  /**
   * Constructor de la clase
   * @param string $host Url o DNS del Servidor MySQL
   * @param string $user Usuario del servidor
   * @param string &pass Contraseña del servidor
   * @param string $db Nombre de la base de datos
   * @param mixed $logger Función para el registro de datos
   * @param mixed $errors Función para el manejo de errores
   * @return nothing
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  private function __construct($host, $user, $pass, $db, $prefix = null, $logger = null, $errors = null)
   {
    $this->data['host'] = $host;
    $this->data['user'] = $user;
    $this->data['pass'] = $pass;
    $this->data['name'] = $db;
    $this->prefix = $prefix;
    $this->errors = $errors;
    $this->logger = $logger;

    // Conectamos a la base de datos.
    $this->connect();
   } // private function __construct();



  /**
   * Desconectar & Destruir la clase
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function __destruct()
   {
    return $this->disconect();
   } // public function __destruct();



  /**
   * No permitimos la clonación de LittleDB
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function __clone()
   {
    return $this->error('', 'La clonación de este objeto LittleDB no está permitida.');
   }  // public function __clone();



  /**
   * Si por alguna razón alguien necesita esta clase como un texto, retornamos
   * texto.
   * @return string
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function __toString()
   {
    $cfg = array();
    foreach($this->data as $field => $value)
     {
      $cfg[] = $field.'='.$value;
     }
    return __CLASS__.'['.implode(';', $cfg).']';
   } // public function __toString();



  /**
   * Si se invoca esta clase será con el fin de generar una consulta a la base
   * de datos a modo de Alias a la función $this->select.
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function __invoke($table, $fields, $condition = null)
   {
    return $this->select($query, $values, $ret);
   }  // public function __invoke();



  /**
   * Retornamos la configuración de la clase cuando ésta es serializada.
   * @return array
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function __sleep()
   {
    return array(
     'data' => $this->data,
     'logger' => $this->logger,
     'errors' => $this->errors,
     'prefix' => $this->prefix
     );
   } // public function __sleep();



  /**
   * Conectamos a la base de datos cuando ésta es deserializada
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function __wakeup()
   {
    $this->connect();
   }  // public function __wakeup();



  /**
   * Obtenemos una instancia de la clase, la primera vez pasamos los parámetros
   * para conectar.
   * @return object $instance Instancia de la base de datos.
   * @author Ignacio Daniel Rostagno <ignaciorostagno@vijona.com.ar>
   */
  public static function get_instance($host = null, $user = null, $pass = null, $db = null, $prefix = null, $logger = null, $errors = null)
   {
    if(self::$instance === null)
     {
      self::$instance = new LittleDB($host, $user, $pass, $db, $prefix, $logger, $errors);
     }
    return self::$instance;
   } // public static function get_instance();



  /**
   * Conectar al servidor MySQL
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  private function connect()
   {
    $this->conn = mysqli_connect($this->data['host'], $this->data['user'], $this->data['pass'], $this->data['name']) or $this->error('', 'No se pudo conectar al servidor MySQL');
   } // private function connect();



  /**
   * Desconectar del servidor MySQL
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  private function disconect()
   {
    return ($this->conn !== null) ? mysqli_close($this->conn) : true;
   } // private function connect();



  /**
   * Procesar una consulta compleja en la base de datos
   * @param string $cons Consulta SQL
   * @param miexed $values Arreglo con los valores a reemplazar por Parse_vars
   * @param boolean $ret retornar Array de datos o no.
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function query($cons, $values = null, $ret = false)
   {
    $query = ($values != null) ? $this->parse_vars($cons, $values) : $cons;
    if($ret == true)
     {
      $res = $this->_query($query);
      if($res !== false)
       {
        $return = $res->fetch_assoc();
        $res->free();
       }
      else
       {
        $return = false;
        $this->error($query);
       }
     }
    else
     {
      $return = new Query($query, $this->errors, $this->conn);
      ++$this->count;
     }
    return $return;
   } // public function query();



  /**
   * Seleccionamos campos de una tabla
   * @param string $table Nombre de la tabla objetivo
   * @param array|string $fields
   * @param array $condition Condicionante para la selección
   * @param array|integer $limit Límite de filas
   * @author Cody Roodaka <roodakazo@gmail.com>
   * @return array
   */
  public function select($table, $fields, $condition = null, $limit = null)
   {
    if($condition !== null)
     {
      $where = array();
      foreach($condition as $key => $value)
       {
        $where[] = $key.' = '.$this->parse_input($value);
       }
      $string = ' WHERE '.implode(' && ', $where);
     }
    else
     {
      $string = '';
     }
    $limits = ($limit !== null) ? ((is_array($limit)) ? $limit[0].', '.$limit[1] : '0, '.$limit) : '0, 1';

    $cons = 'SELECT '.(is_array($fields) ? implode(', ', $fields) : $fields).' FROM '.$this->data['name'].$this->prefix.$table.$string.' LIMIT '.$limits);
    $query = $this->_query($cons)
    if(!$query || $query == false)
     {
      $this->error($cons);
      return false;
     }
    else
     {
      if($limits !== null)
       {
        return new Query($query, $this->errors, $this->conn);
        ++$this->count;
       }
      else
       {
        return $query->fetch_assoc();
       }
     }
   } // public function select();



  /**
   * Insertar Datos en una tabla
   * @param string $table Nombre de la tabla
   * @param array $data Arreglo asosiativo con los datos
   * @return integer|boolean Número de filas afectadas o False.
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function insert($table, $data)
   {
    if(is_array($data) === true)
     {
      $cons = 'INSERT INTO '.$this->data['name'].'.'.$this->prefix.$table.' ( '.implode(', ', array_keys($data)).' ) VALUES ( '.$this->parse_input($data).' )';
      $query = $this->_query($cons);
      // Seteamos el resultado,
      return (!$query || $query == false) ? $this->error($cons) : $this->conn->insert_id;
     }
    else { return false; }
   } // public function insert();




  /**
   * Borrar una fila
   * @param string $table nombre de la tabla
   * @param array $cond Condicionantes
   * @return integer|boolean Número de filas afectadas o False.
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function delete($table, $cond = array())
   {
    if(is_array($cond) == true)
     {
      $where = array();
      foreach($cond as $key => $value)
       {
        $where[] = $key.' = '.$this->parse_input($value);
       }
      $cons = 'DELETE FROM '.$this->data['name'].'.'.$this->prefix.$table.' WHERE '.implode(' && ', $where);
      $query = $this->_query($cons);
      return (!$query || $query == false) ? $this->error($cons) : $this->conn->affected_rows;
     } else { return false; }
   } // public function delete();



  /**
   * Actualizar una fila
   * @param string $table nombre de la tabla
   * @param array $array Arreglo asosiativo con los datos
   * @param array $cond Condicionantes
   * @return integer|boolean Número de filas afectadas o False.
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function update($table, $array = array(), $cond = array())
   {
    if(is_array($cond) == true && $table != null)
     {
      $fiel = array();
      foreach($array as $field => $value)
       {
        $fiel[] = $field.' = '.$this->parse_input($value);
       }
      $wher = array();
      foreach($cond as $field => $value)
       {
        $wher[] = $field.' = '.$this->parse_input($value);
       }
      $cons = 'UPDATE '.$this->data['name'].'.'.$this->prefix.$table.' SET '.implode(', ', $fiel).' WHERE '.implode(' && ', $wher);
      $query = $this->_query($cons);
      return (!$query || $query == false) ? $this->error($cons) : $this->conn->affected_rows;
     } else { return false; }
   } // public function update();



  /**
   * Ejecutamos una consulta
   * @param string $query Cosulta SQL
   * @return resource
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  private function _query($query)
   {
    ++$this->count;
    if($this->logger !== null)
     {
      call_user_func_array($this->logger, array($query));
     }
    return mysqli_query($this->conn, $query);
   } // private function _query();



  /**
   * Retornamos un error grave del servidor
   * @param string $query Consulta que origina el error
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function error($query, $error = null)
   {
    if($this->errors !== null)
     {
      call_user_func_array($this->errors, array($query, (($error !== null) ? $error : mysqli_error($this->conn)) ));
     }
   } // function error();


  /**
   * Funcion encargada de realizar el parseo de la consulta SQL agregando las
   * variables de forma segura mediante la validacion de los datos.
   * En la consulta se reemplazan los ? por la variable en $params
   * manteniendo el orden correspondiente.
   * @param string $q Consulta SQL
   * @param array $params Arreglo con los parametros a insertar.
   * @author Ignacio Daniel Rostagno <ignaciorostagno@vijona.com.ar>
   */
  protected function parse_vars($q, $params)
   {
    // Si no es un arreglo lo convertimos
    if(!is_array($params)) { $params = array($params); }
    //Validamos que tengamos igual numero de parametros que de los necesarios.
    if(count($params) != preg_match_all("/\?/", $q, $aux))
     {
      throw new Exception('No coinciden la cantidad de parametros necesarios con los provistos en '.$q);
      return $q;
     }
    //Reemplazamos las etiquetas.
    foreach($params as $param)
     {
      $q = preg_replace("/\?/", $this->parse_input($param), $q, 1);
     }
    return $q;
   } // protected function parse_vars();


  /**
   * Función que se encarga de determinar el tipo de datos para ver si debe
   * aplicar la prevención de inyecciones SQL, si debe usar comillas o si es
   * un literal ( funcion SQL ).
   * @param mixed $objet Objeto a analizar.
   * @return string Cadena segura.
   * @author Ignacio Daniel Rostagno <ignaciorostagno@vijona.com.ar>
  */
  protected function parse_input($object)
   {
    if(is_object($object)) //Es un objeto?
     {
      return (string) $object;
     }
    elseif(is_int($object)) // Es un número?
     {
      return (int) $object;
     }
    elseif($object === NULL) // Es nulo?
     {
      return 'NULL';
     }
    elseif(is_array($object)) //Es un arreglo?
     {
      return implode(', ', array_map(array($this, 'parse_input'), $object));
     }
    else //Suponemos una cadena
     {
      return '\''.mysqli_real_escape_string($this->conn, $object).'\'';
     }
   } // protected function parse_input();
 } // class LittleDB();



/**
 * Clase para manipular resultados de consultas MySQL, esta clase no es
 * comunmente accesible y es creada por LittleDB
 * @author Cody Roodaka <roodakazo@gmail.com>
 * @author Ignacio Daniel Rostagno <ignaciorostagno@vijona.com.ar>
 * @access private
 */
class Query //Implements Iterator
 {
  /**
   * Recurso MySQL
   * @var resource
   */
  private $data = false;

  /**
   * Resultado de la consulta
   * @var array
   */
  private $result = array();

  /**
   * Posición
   * @var integer
   */
  private $position = 0;

  /**
   * Nro de filas
   * @var integer
   */
  public $rows = 0;



  /**
   * Inicializar los datos
   * @param string $query Consulta SQL
   * @param string $eh Nombre de la función que manipula los errores
   * @param resource $conn Recurso de conección SQL
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function __construct($query, $eh, $conn)
   {
    $cons = mysqli_query($conn, $query);
    if(is_object($cons))
     {
      $this->data = $cons;
      $this->position = 0;
      $this->rows = $this->data->num_rows;
      return true;
     }
    else
     {
      if($eh !== null)
       {
        call_user_func_array($eh, array($query, mysqli_error($conn)));
       }
     }
   } // function __construct();



  /**
   * Cuando destruimos el objeto limpiamos la consulta.
   * @author Ignacio Daniel Rostagno <ignaciorostagno@vijona.com.ar>
   */
  public function __destruct()
   {
    return $this->free();
   } // public function __destruct();



  /**
   * Limpiamos la consulta
   * @author Ignacio Daniel Rostagno <ignaciorostagno@vijona.com.ar>
   */
  private function free()
   {
    return (is_resource($this->data)) ? $this->data->free() : true;
   } // private function free();



  /**
   * Devolvemos el array con los datos de la consulta
   * @param string $field Campo objetivo.
   * @param string $default Valor a retornar si el campo no existe o está vacío.
   * @return array|string Todos los campos o sólo uno
   * @author Cody Roodaka <roodakazo@gmail.com>
   */
  public function fetch($field = null, $default = null)
   {
    $this->result = $this->data->fetch_assoc();
    if($field !== null) // Pedimos un campo en especial
     {
      return (isset($this->result[$field])) ?$this->result[$field] : $default;
     }
    else
     {
      return $this->result;
     }
   } // public function fetch();

 } // class Query



/**
 * Excepción exclusiva de LittleDB.
 * @author Cody Roodaka <roodakazo@gmail.com>
 * @access private
 */
class LDB_Exception Extends Exception { } // class LDB_Exception();




/**
 * LDB: Función improvisada para el manejo de errores
 * @param string $query Consulta que origina el error
 * @param string $error Mensaje de error provisto por el servidor MySQL
 * @return nothing
 * @author Cody Roodaka <roodakazo@gmail.com>
 */
function ldb_error($query, $error)
 {
  exit('<h2>Data Base Error</h2>'.(($query !== '') ?'<span>Error en la consulta <i>'.$query.'</i></br>' : '').'<b>'.$error.'</b></span>');
  // throw new LDB_Exception('<h2>Data Base Error</h2>'.(($query !== '') ?'<span>Error en la consulta <i>'.$query.'</i></br>' : '').'<b>'.$error.'</b></span>');
 } // function ldb_error();



/**
 * LDB: Función Improvisada para el registro de datos
 * @param string $data Datos a registrar
 * @return nothing
 * @author Cody Roodaka <roodakazo@gmail.com>
 */
function ldb_log($data)
 {
  // do something.
 } // function ldb_log();