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.