Clase para manejar base de datos MySQL en PHP
Una de las máximas prioridades en una aplicación PHP que haga uso de una base de datos, es la organización y eficiencia del código para evitar consumo innecesario de memoria, esto es bien sabido por cualquier programador. Pero ¿qué hay de la separación del código de lógica y el de la base de datos?
El patrón Modelo-Vista-Controlador nos puede ser de gran utilidad ya que separa la lógica (controladores) de scripts que acceden y relacionan las tablas de un base de datos (modelos) y de la interfaz gráfica (vistas). Pero en ocasiones no necesitamos de tantas capas de abstracción y decidimos programar todo revuelto. Aún así, utilizar una clase para los accesos a la base de datos nos es de gran ayuda para aquello de la organización del código.
La clase que a continuación propongo utiliza un patrón llamado Singleton. Este patrón obliga a instanciar unicamente una vez la clase para evitar 2 o más conexiones simultáneas. La clase contiene métodos para ejecutar sentencias SQL, cargar resultados en forma de objetos, ver el número de consultas totales etc.
<?php
class DataBase {
private $conexion;
private $resource;
private $sql;
public static $queries;
private static $_singleton;
public static function getInstance(){
if (is_null (self::$_singleton)) {
self::$_singleton = new DataBase();
}
return self::$_singleton;
}
private function __construct(){
$this->conexion = @mysql_connect( 'localhost', 'db_user' , 'db_password' ) );
mysql_select_db( 'database_name' , $this->conexion );
$this->queries = 0;
$this->resource = null;
}
public function execute(){
if( ! ( $this->resource = mysql_query( $this->sql , $this->conexion ) ) ){
return null;
}
$this->queries++;
return $this->resource;
}
public function alter(){
if( ! ( $this->resource = mysql_query( $this->sql , $this->conexion ) ) ){
return false;
}
return true;
}
public function loadObjectList(){
if ( ! ( $cur = $this->execute() ) ){
return null;
}
$array = array();
while ( $row = @mysql_fetch_object( $cur ) ){
$array[] = $row;
}
return $array;
}
public function setQuery( $sql ){
if( empty( $sql ) ){
return false;
}
$this->sql = $sql;
return true;
}
public function freeResults(){
@mysql_free_result( $this->resource );
return true;
}
public function loadObject(){
if ( $cur = $this->execute() ){
if ( $object = mysql_fetch_object( $cur ) ){
@mysql_free_result( $cur );
return $object;
}
else {
return null;
}
}
else {
return false;
}
}
function __destruct(){
@mysql_free_result( $this->resource );
@mysql_close( $this->conexion );
}
}
?>
Si notamos, el constructor es privado. ¿Por qué? para asegurarnos de que la clase se instancie desde dentro de sí misma. Es decir, al ejecutar el método DataBase::getInstance() llamamos al constructor y creamos una única instancia de DataBase. Si volvemos a ejecutar ese método y la clase ya ha sido instanciada antes, entonces nos devolverá la instancia. Eso es el objetivo del patrón Singleton.
Veamos entonces como hacer una conexión, ejecutar una consulta y mostrar los resultados. Se asume que los parámetros de conexión como el host, el nombre de usuario y demás se especifican directamente en la clase.
// Hacemos la conexión
$db = DataBase::getInstance();
// Supongamos que tenemos una tabla de usuarios
// Hacemos la consulta:
$db->setQuery('SELECT `id`,`nombre`,`grupo` FROM `usuarios`');
// La ejecutamos y al mismo tiempo obtenemos un arreglo de objetos
// con los campos especificados en la consulta como propiedades.
$usuarios = $db->loadObjectList();
// Los imprimimos directamente en pantalla...
foreach($usuarios as $usuario){
echo 'ID: '.$usuario->id;
echo 'Nombre: '.$usuario->nombre;
echo 'Grupo: '.$usuario->grupo;
echo '<br />';
}
Y ahí tienen un pequeñísimo ejemplo de uso. Algunos métodos como el DataBase::loadObject o DataBase::loadObjectList fueron tomados de la API de Joomla. En fin, espero que les sea de utilidad.
Tags: mysql, PHP, Programacion
Siéntete libre de dejar tu comentario.
Comentarios
Dime esta bacan pero esta clase permite tambien ejecutar insert update y todo eso y si es como podria hacerlo..
Es fácil:
$db = DataBase::getInstance();
$db->setQuery("INSERT INTO tabla VALUES ('','$nombre','$edad')");
if( $db->alter() ){
// se inserto...
}
else{
// no se inserto...
}
Hola,
Soy un novato en esto de las clases con PHP, he copiado tal cual tu clase y luego copie en otro php el ejemplo de la consulta, el tema es que me esta dando un error en el foreach:
Warning: Invalid argument supplied for foreach() in C:\Servidor\Web\pruebaClases\query.php on line 24
y la linea 24 es la que dice :
foreach($usuarios as $usuario){
Hola,
Soy un novato en esto de las clases con PHP, he copiado tal cual tu clase y luego copie en otro php el ejemplo de la consulta, el tema es que me esta dando un error en el foreach:
Warning: Invalid argument supplied for foreach() in C:\Servidor\Web\pruebaClases\query.php on line 24
y la linea 24 es la que dice :
foreach($usuarios as $usuario){
Supongo que tienes creada una tabla llamada usuarios con esos 3 campos, y que tu tabla tiene más de un registro….
¿Verdad?
Abel,
te pido mil disculpas soy tan distraido que me habia olvidado de escribir el nombre de mi base de datos, lo que estoy intentando es agregar los datos de nombre de base, usuario de base, password y servidor para que lo lea de un archivo para que quede parametrizado.
Te hago una consulta: ¿se usa leer estos datos de un archivo?
desde ya muchisimas gracias por tu aporte!!!
Pablo
No, no se usa leer esos datos de un archivo, pero si asi lo quieres hacer, puedes usar un XML:
<?xml version="1.0"?> <datos> <host>localhost</host> <usuario>tu_nombre</usuario> <password>tu_password</password> <database>nombre_db</database> </datos>
Solo tendrias que hacerle un parsing, y sacar los datos y usarlos para la conexion… lo cual me parece muy descabellado…. Creo que la mejor alternativa es declarar constantes dentro de la clase y asignarle esos valores…
Respondi bien tu pregunta o me fui por otro lado?
hola utilize tu clase pero tengo un pequeño problema
Warning: Invalid argument supplied for foreach() in /var/www/html/cat/solicitudeq.php on line 37
solo que nada mas puse un campo en la consulta asi:
$db = DataBase::getInstance();
// Hacemos la consulta:
$db->setQuery(”SELECT id_equipo FROM CatalogoPrestamo WHERE disponible=’1′ and tipo=’L’ “);
$LAP= $db->loadObjectList();
foreach($x as $LAP)
{
echo ‘ID equipo: ‘.$LAP->id_equipo;
}
supongo que si sepuede utilizar con where vdd?
Hola jesus, el problema está el foreach. La sintaxis del foreach es:
foreach( $arreglo_con_valores as $variable_individual){
}
Tu pusiste: foreach($x as $LAP), y debe ser al revés:
foreach($LAP as $x){
echo 'ID equipo: '.$x->id_equipo;
}
muchas gracias abel … no cheque la sintaxis… saludos.
solo otra pregunta: si se pueden hacer multiples consultas con la misma clase vdd? un ejemplo porfa?
Claro, solo hay que estar modificando la propiedad $sql y como es privada hay que usar el método Database::setQuery($sql).
Así que antes de cada consulta hay que hacer el:
$database->setQuery( $query );
correspondiente.
otra pregunta como se podria asignar, suponiendo que solo obtenga un registro unico de la consulta a una variable que no sea un arreglo o imprimirlo? por ejemplo algo asi:
$db = DataBase::getInstance();
$db->setQuery(”SELECT id_equipo FROM CatalogoPrestamo WHERE disponible=’1′ and tipo=’L’ “);
$LAP= $db->loadObjectList();
$var=LAP
echo $var;
$db = DataBase::getInstance();
$db->setQuery(”SELECT id_equipo FROM CatalogoPrestamo
WHERE disponible=’1′ and tipo=’L’ “);
$LAP = $db->loadObjectList();
$var = $LAP[0];
echo $var->id_equipo;
Hola:
¿Y cómo sería el código para realizar un SQL tipo “Select count(*) from tabla” o “Select max(id) from tabla”?
Muchas gracias
Creo que ya he arreglado con esto:
$db = DataBase::getInstance();
$db->setQuery(”select count(id) as TOTAL from operadores where op_name=’”.$nombre.”‘ and op_key=’”.$clave.”‘”);
$LAP = $db->loadObjectList();
$var = $LAP[0];
echo $var->TOTAL;
Si hay alguna manera más eficiente, por favor, indicarla.
Muchas gracias
Hola,
gracias por la aportación, realmente útil. Me gustaría saber si tienes algo implementado para usar transacciones con esta clase.
Gracias!
hola, tengo un problema con la clase, me esta generando un error si realizo un session_start() despues de hacer el llamado de ésta clase, como si generara una salida en la clase, el problema que tengo es que me es obligatorio llamar el session_start() despues de declarar la clase. este es el erro: Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\AppServ\www\liquidador\core\database.php:82) in C:\AppServ\www\liquidador\index.php on line 3


hola me ayudo mucho tu clase de php y databases gracias