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: , ,

Siéntete libre de dejar tu comentario.

Comentarios

hola me ayudo mucho tu clase de php y databases gracias

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;

muchas gracias de nuevo me fue de gran utilidad….

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

Y como seria usando el metodo
loadObject

Ese no lo explicas, pero si el loadObjectList.

Pienso en voz alta, en ultimas el objeto devuelto por loadObjectList es un array y podria imprimirse con print_r ..
es para verificar que si tiene valores….

bye

Hola, estoy tratando de usar tu clase, pero no logro validar utilizando la funcion alter, siempre me indica que el valor false, puedes ayudarme?

hola que tal oye necesito una mega ayuda necesito crear un programa que me pida una contraseña y cuando la contraseña sea correcta pueda abrir otro programa, bueno ya tengo el programa dela contraseña pero el problema es que no se como hacer para que me abra el nuevo programa cuando la contraseña esta correcta por favor si alguien me puede ayudar les agradeceria su apoyo

public function _Transaction() {
mysql_disconnect($this->conexion);
}

public function begin() {
mysql_query(“BEGIN”, $this->conexion);
}

public function rollback() {
mysql_query(“ROLLBACK”, $this->conexion);
}

public function commit() {
mysql_query(“COMMIT”, $this->conexion);
}

Hola !!!
Me han mandado un trabajo de PHP con MYSQL.
Lo que me pide es que cuando me conecte a una BBDD cualquiera, que me muestre en una tabla() de html las tablas que tiene la BBDD. Cuando seleccione una tabla que me muestre los campos que tiene … y ademas que se pueda seleccionar varios campos para mostrarlos, un SUM, un MAX, un MIN, GROUP BY y ORDER BY.
Si puedes me gustaria que me ayudases !!!
Muchas gracias.

Atentamente Eduard.

Solamente quisiera agradecerte tu clase. Esto si es implementar POO con PHP!!!!

como uso el comentario de Kimi Brown ??????????????????????????????? hey admin te sabes el mail de el??

Sí, es brownkimi arroba yahoo punto com

Tambien pueden utilizar, en vez de XML para la config, un simple PHP o si lo prefieren un JSON, tengo una clase para el trabajo con JSON. La cogi de la libreria de Ext JS,creo, no recuerdo bien.
Saludos
rafa

Hola, copie esta clase pero a la hora de ejecutarla en un script en modo local me da el siguiente error:
Parse error: syntax error, unexpected T_DNUMBER in D:\AppServ\www\lib\MySQL.php on line 3

Alguien sabe porque??

Saludos y si alguien puede decirme donde encontrar mas documentacion se lo agradeceria (estoy empezando en esto de POO para php)

Excelente tu clase amigo, pero que tal si se desea hacer una consulta a dos o mas BD del mismo gestor al mismo tiempo

Que tal estoy haciendo una aplicacion necesito la conexion de MySql pero la verdad es que php no se nada estoy leyendo manueales y tutoriales solo quiero que me expliquen como puedo guardar la clase de arriba y como utilizar la de abajo en un boton para que me guarde los valores, no se si es xq estoy utilizando el IDE de NetBeams para php , la verdad es que yo programo en Java pero nunca lo e echo en php espero que alguien me pueda ayudar y gracias por la atencion..!!

ATT:

!!..CMDD..!!

Me ha impresionado tu clase, pero tengo una duda, si yo quisiera implementar la funcion addslashes(), donde la implementaría, digamos que quiero consultar el usuario y la contraseña, ¿donde colocaria esta funcion o donde colocaria el respectivo codigo para evitar sql injection?

Otra cosa, ¿Será posible parametrizar tu clase para que no se conecte solamente con mysql sino tambien con oracle, postgress, access o sqlserver inclusive?

Quiero agradecerte y me quito el sombrero ante ti por que le veo una ran utilidad a la clase que has hecho. gracias….

hola excelente clase, gracias me ha servido de mucho , tengo una duda mira porque en el metodo

public function loadObjectList(){
if (!($cur = $this->execute())){
return null;
}
$array = array();
while ($row = @mysql_fetch_object($cur)){
$array[] = $row;
}
return $array;
}

No pones la sentencia pra liberar recursos como si lo pones en

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;
}
}

OSEA ESTA LINEA – @mysql_free_result($cur); que a mi entender alli estas liberando los recurso de memoria noes asi? te agradeceria si me pudieras absolver esa duda

Alguien sabe si esta clase, permite updates, commits y roolback(transacciones)?

Hola Como estas, Como puedo hacer para que que me de un mensaje en una consulta, Me explico, quiero Validar un Usuario, si el usuario existe realizo una Acción y si no Existe Realizo otra.

algo muy parecido a lo que hiciste acá, pero para un select

$db = DataBase::getInstance();
$db->setQuery(“INSERT INTO tabla VALUES (”,’$nombre’,'$edad’)”);
if( $db->alter() ){
// se inserto…
}
else{
// no se inserto…
}

Como puedo paginar el resultado obtenido. Alguien me puede ayudar?

Un problema q se me dio cuando quise usar es:
————————-
Parse error: parse error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or ‘}’ in /home/content/p/e/r/…./mysql.class.php on line 5
—————————–
Nota: Estoy usando el PHP Version PHP Version 4.3.11, no se si tenga algo que ver… saludos

@Ruben, si tiene mucho que ver tu versión de PHP, ese código es para PHP5. El 4.x no maneja modificadores de acceso (public, private, protected) entre otras diferencias…

Soy principiante y estoy haciendo una aplicación en PHP y Mysql que es un inventario, pero se me esta dificultando relacionar registros entre tablas, podrian hacerme favor de enviarme un ejemplo resuelto.
Mi duda es por ejemplo: capturo 200 piezas cuando hago la salida se debe restar de esas 200 piezas y ademas dejar en alguna tabla el historial.

Gracias.

Abel, si pudieras ayudarm, copie tal y como esta la clase y la guarde con el nombre de database.php de igual forma el ejemplo conectar.php al momento de compilar conectar.php, no responde la consulta; tengo la base de datos dbbiblioteca y la tabla usuarios con mas de 5 registros de esta forma
create table usuarios(
id int not null,
nombre char(80) not null,
primary key (id)
)
ENGINE = InnoDB;

y la clase de esta forma:
conexion = @mysql_connect(‘localhost’, ‘root’, ‘abcd’));
mysql_select_db(‘dbBiblioteca’, $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);
}
}
?>

el ejemplo de esta forma:
setQuery(‘SELECT `id`,`nombre` 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 ”;
}
?>
PD: Uso mysql 5 y php 5 apache 2.2, no se cual es el error

Sorry, el ejemplo conectar.php esta de la siguiente forma:

setQuery(‘SELECT `id`,`nombre` 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 ”;
}
?>
Espero una respuesta pronta. Por favor, me urge. Gracias desde luego.

Disculpa un error tras otro el ejemplo conectar es:
.setQuery(‘SELECT `id`,`nombre` 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 ”;
}
?>

He estado buscando código para manejar bases de datos y al final me quedo con el tuyo. Es simple, sencillo y fácil.

Le añado el apunte para manejar transacciones que hay en uno de los comentarios.

Muchas gracias

Hola Abel, muy interesante el patrón singletón, pero veo que este es estrictamente enfocado a mysql como gestor de base de datos, se podria adaptar para oracle o sql server ??

Hola!, muy buen aporte pero quisiera saber como haria para instanciar dos base de dator para poder usar dos conexiones.

Deja el tuyo

(necesario)

(necesario)