Notice: Article only available in Spanish!
Hemos visto en publicaciones anteriores cómo conectar a una base de datos mysql desde php, y cómo usar la función mysql_query para consultar datos. También hemos visto algunas nociones de seguridad en scripts y aplicaciones php. Ahora vamos a ver cómo encapsular estas funciones en una práctica clase que nos permitirá instanciar objetos dbhandler y trabajar cómodamente con ellos.
Parto de que el lector conoce el paradigma de la Programación Orientada a Objetos. Básicamente, una clase es un molde que tiene ciertas peculiaridades como métodos y atributos, que pueden ser públicos (de libre acceso) o privados (sólo accesibles dentro de la propia clase). Con esta clase, se pueden instanciar objetos pertenecientes a dicha clase. si estuviéramos en la arena de la playa con un cubo, el cubo sería la clase, y las torres de arena serían los objetos o instancias del cubo de playa.
Las clases tienen una sintaxis especial, se trabaja con ellas de un modo distinto a como hacemos con la programación estructurada. Veamos un ejemplo:
public class dbhandler
{
//
var $user;
var $pass;
var $host;
var $database;
var $identifier;
var $results;
var $resultset;
var $query;
//
/**
* constructor. initializes the object
*/
public function dbhandler($user = "", $pass = "", $database = "" , $host="localhost")
{
if ($user == "" || $pass == "" || $database == "")
{
return(null);
}
$this->user = $user;
$this->pass = $pass;
$this->host = $host;
$this->database = $database;
}
}
Es decir, todo objeto de la clase dbhandler almacenará unos valores como clave, usuario, base de datos y host, lo que nos permitirá tener varios manejadores apuntando a distintas bases de datos, a distintos servidores en distintas máquinas, o autenticados con distintos usuarios con distintos permisos; esto nos deja la puerta abierta para usar esta clase en entornos bastante versátiles.
Ya tenemos lo que la clase debe ‘saber’. Ahora queremos que haga cosas. Queremos que se conecte, queremos que seleccione la base de datos, queremos que permita desconectar y queremos que lea una tabla concreta. Vamos con los métodos:
/**
* connect to server
*/
function connect()
{
$this->identifier= @mysql_connect ($this->host,$this->user,$this->pass)
or die("Error connecting to database with user ".$this->user . mysql_error());
}
/**
* select database
*/
function selectDB()
{
@mysql_select_db($this->database,$this->identifier)
or die("Error selecting database: ".$this->database);
}
/**
* retrieves data from the selected fields of a certain table
* @param table to read from
* @param fields to be retrieved
*/
function readTable($table,$fields)
{
//variables
$resultsArray = array();
//fields
$fieldsList = "";
foreach($fields as $key=>$value)
{
$fieldsList .= $value . ",";
}
//remove last comma
$fieldsList = substr($fieldsList,0,strlen($fieldsList)-1);
//query
$this->query = "SELECT " . $fieldsList . " FROM " . $table;
$this->resultset = @mysql_query($this->query,$this->identifier);
$this->results = @mysql_num_rows($this->resultset);
if ( $this->results > 0)
{
while ($result = mysql_fetch_array($this->resultset))
{
$resultsArray[] = $result ;
}
}
return($resultsArray);
}
/**
* close connection and free resources
*/
function disconnect()
{
mysql_close($this->identifier);
}
Como acabamos de ver, a las variables de la clase o atributos se les llama mediante $this->nombredeatributo, siendo $this el objeto actual, instanciado de la clase dbhandler. Para llamar a los métodos de la clase, igualmente usaremos $this->nombredemetodo(); por ejemplo ahora que hemos definido métodos para conectar y seleccionar la base de datos, podemos hacer esto automáticamente cada vez que se crea un objeto de la clase dbhandler. ¿Cómo? poniendo las correspondientes líneas en el constructor, por supuesto.
/**
* constructor. initializes object
*/
public function dbhandler($user = "", $pass = "", $database = "" , $host="localhost")
{
if ($user == "" || $pass == "" || $database == "")
{
return(null);
}
$this->user = $user;
$this->pass = $pass;
$this->host = $host;
$this->database = $database;
$this->connect();
$this->selectDB();
}
Esto nos da una idea de lo cómodo que va a ser trabajar con clases a partir de ahora. Puesto que los atributos $database, $host, $user, $pass, etc., son comunes para todos los métodos de la clase, no necesitan ser pasados como parámetros en las funciones, lo que agiliza mucho la programación y permite código más legible. Ya tenemos nuestra clase con atributos y métodos definida, ahora tenemos que usarla. Si guardamos todo el código de la clase en un archivo llamado class.dbhandler.php, podemos crear un script que lo use del siguiente modo:
/**
* script to connect to a database and read data from tables, with classes
* @author Jorge Albaladejo Pomares [correo@jorgealbaladejo.com]
* @license Creative Commons License http://creativecommons.org/licenses/by-sa/3.0/
*/
//main classes
include('class.dbhandler.php');
//main script
$db = new dbhandler('john_smith','h01y_GRail','pastafarian_food','localhost');
$fields = array('id', 'name', 'special_powers');
$results = $db->readTable('superheroes',$fields,$token);
foreach($results as $result)
{
echo 'id => ' . $result['id'] . '
';
echo 'title => ' . $result['title'] . '
';
}
echo '
';
$db->disconnect();
Y la clase dbhandler finalmente quedará así:
/**
* class to handle database connections and reading from tables
* @author Jorge Albaladejo Pomares [correo@jorgealbaladejo.com]
* @license Creative Commons License http://creativecommons.org/licenses/by-sa/3.0/
*/
public class dbhandler
{
//
var $user;
var $pass;
var $host;
var $database;
var $identifier;
var $results;
var $resultset;
var $query;
//
/**
* constructor. initializes object
* @param user
* @param pass
* @param database
* @param host
*/
public function dbhandler($user = "", $pass = "", $database = "" , $host="localhost")
{
if ($user == "" || $pass == "" || $database == "")
{
return(null);
}
$this->user = $user;
$this->pass = $pass;
$this->host = $host;
$this->database = $database;
$this->connect();
$this->selectDB();
}
/**
* connect to server
*/
function connect()
{
$this->identifier= @mysql_connect ($this->host,$this->user,$this->pass)
or die("Error connecting to database with user '".$this->user . "': " . mysql_error());
}
/**
* select database
*/
function selectDB()
{
@mysql_select_db($this->database,$this->identifier)
or die("Error selecting database: ".$this->database);
}
/**
* queries the selected fields from a certain table in the database
* @param table
* @param fields
*/
function readTable($table,$fields)
{
//variables
$resultsArray = array();
//fields
$fieldsList = "";
foreach($fields as $key=>$value)
{
$fieldsList .= $value . ",";
}
//remove last comma
$fieldsList = substr($fieldsList,0,strlen($fieldsList)-1);
//query
$this->query = "SELECT " . $fieldsList . " FROM " . $table;
$this->resultset = @mysql_query($this->query,$this->identifier);
$this->results = @mysql_num_rows($this->resultset);
if ( $this->results > 0)
{
while ($result = mysql_fetch_array($this->resultset))
{
$resultsArray[] = $result ;
}
}
return($resultsArray);
}
/**
* close connection and free resources
*/
function disconnect()
{
mysql_close($this->identifier);
}
}
Esta clase se puede completar añadiendo métodos para todo tipo de propósitos: búsquedas sobre la base de datos, consulta de datos según orden y paginación, se le puede implementar un método que devuelva los resultados en html o xml en lugar de devolverlos en un array, se le puede añdir un destructor que se encargue de liberar los recursos cuando se deja de utilizar el objeto…
/**
* destruct
*/
function destroy()
{
$this->disconnect();
//settype(&$this, 'null'); //may not work with php4
}
Y lo mejor de todo, podemos reutilizar fácilmente el código para cualquiera de nuestras aplicaciones. Y podemos escribir aplicaciones de una forma muchísimo más sencilla y cómoda que con programación estructurada. En general, todo son ventajas 🙂