¿Como Conectar Php y Mysql a través de PDO y MySQLi?

En este artículo veremos como integrar Php y Mysql para aumentar la funcionalidad de nuestros desarrollos web. Primero veremos como abrir la conexión en el servidor Mysql. Luego ejecutaremos comandos en nuestra base de datos a través de nuestra aplicación y finalmente aprenderemos a llamar procedimientos almacenados.

Actualmente Php ha declarado obsoleta su API clásica de conexión MySQL para proyectos que usen versiones de Php superiores a la 5.5.0. No obstante existen otras dos APIs de integración, llamadas MySQLi y PDO_MySQL. En este artículo cubriremos la acción de estas tres APIs para que veas las características de codificación en cada una.

Cadenas de conexión entre Php y MySQL

Haremos exactamente lo mismo que con la conexión Mysql-Java y Sql Server-C#. Usaremos las cadenas que indiquen el servidor, el nombre de la base de datos y el usuario que vamos a emplear para abrir la conexión. Como medida de seguridad puedes crear un archivo .php que guarde estos datos en variables locales de forma externa.

<?php //Datos de conexión a la base de datos
$hostname = 'localhost';
$database = 'datos';
$username = 'usuario';
$password = 'contraseña';
?>

Luego incluiremos este archivo con la sentencia require_once en el archivo donde abriremos la conexión. Para abrir la conexión emplearemos los siguientes fragmentos de código:

//MySQL clásico
require_once 'mysql-login.php';
//Conectando
$con = mysql_connect($hostname, $username, $password);
//Manejo de errores
if (!$con)
die("Falló la conexión a MySQL: " . mysql_error());
else
echo "Conexión exitosa!";
//Seleccionar base de datos
mysql_select_db($database)
or die("Seleccion de base de datos fallida " . mysql_error());
mysql_close();


//MySQL PDO
require_once 'mysql-login.php';
try {
$con = new PDO('mysql:host='.$hostname.';dbname='.$database, $username, $password);
print "Conexión exitosa!";
}
catch (PDOException $e) {
print "¡Error!: " . $e->getMessage() . "
";
die();
}
$con =null;


//MySQLi
require_once 'mysql-login.php';
$mysqli = new mysqli($hostname, $username,$password, $database);
if ($mysqli -> connect_errno) {
die( "Fallo la conexión a MySQL: (" . $mysqli -> mysqli_connect_errno() 
. ") " . $mysqli -> mysqli_connect_error());
}
else
echo "Conexión exitosa!";
$mysqli -> mysqli_close();

En la siguiente tabla veremos las características para realizar la conexión en las tres apis:

MySQL clásica MySQLi PDO
mysql_connect(): Función para abrir la conexión new mysqli: Crear nuevo objeto de conexión con las cadenas de conexión. new PDO: Crear un nuevo objeto de conexión con las cadenas de conexión. La cadena “mysql”: al inicio es un estándar de conexión, así que incluyela siempre.
mysql_select_db(): Selecciona la base de datos La base de datos es seleccionada en el constructor PDO La base de datos es seleccionada en el constructor PDO
Usar retorno booleano de mysql_connect() Usa el atributo connect_errno para comprobar la existencia de errores Usaremos try-catch para manejar las excepciones de tipo PDOException
mysql_close(): Función que cierra la conexión mysqli_close(): Método de la clase mysqli para cerrar la conexión. Para cerrar la conexión asignas NULL al objeto de conexión creado.

Ejecutar comandos MySQL desde Php

Ya sabes que los comandos insert, update, delete solo modifican la base de datos, a diferencia de select que retorna resultados estructurados en forma de tabla. Debido a esta situación, es importante elegir correctamente la forma en tratar ambas opciones.

En el siguiente ejemplo estudiaremos como ejecutar los comandos que no retornan filas. Como ejemplo actualizaremos el  nombre de un Profesor cuyo código es 2 en la base de datos de una Universidad.

//MySQL clásico
$resultado = mysql_query("UPDATE PROFESOR SET NOMBRE ='Brenda' WHERE ID=2");
if(!$resultado)
die("Fallo el comando:".mysql_error());
else
echo mysql_affected_rows()."Filas afectadas";


//PDO
$count = $con->exec("UPDATE PROFESOR SET NOMBRE ='Brenda' WHERE ID=2");
print($count." Filas afectadas");


//MySQLi
if ($mysqli->query("UPDATE PROFESOR SET NOMBRE ='Brenda' WHERE ID=2") === TRUE) {
printf($mysqli->affected_rows." Filas afectadas");
}
else
echo "Error al ejecutar el comando:".$mysqli->error;

La siguiente tabla muestra las características de ejecución en cada API:

MySQL clásica MySQLi PDO
mysql_query(): Función que ejecuta un comando en la base de datos. query(): Método de la clase mysqli para ejecutar un comando. exec(): Método de la clase PDO para ejecutar un comando que solo afecta la base de datos.
mysql_affected_rows(): Retorna en la cantidad de filas afectadas affected_rows: Atributo de la clase mysqli que guarda la cantidad de filas afectadas. El retorno de exec() es la cantidad de filas afectadas por la sentencia.

Consultar base de datos MySQL desde Php

Para este caso el API MySQL clásico y MySQLi usan el mismo método anterior para tratar consultas. Por su parte, PDO emplea el método query() para obtener las filas. A continuación veremos como consultar la tabla AVIONES del sistema de una Aerolínea.

//MySQL clásico
$query = "SELECT * FROM AVIONES";
$resultado = mysql_query($query);
if(!$resultado)
die("Fallo el comando:".mysql_error());
else{
print("<table>");
while($rows = mysql_fetch_array($resultado,MYSQL_ASSOC)){
print("<tr>");
print("<td>".$rows["ID"]."</td>");
print("<td>".$rows["CAPACIDAD"]."</td>");
print("<td>".$rows["DESCRIPCION"]."</td>");
print("</tr>");
}
print("</table>");
}

mysql_free_result($resultado);

//PDO
$query = "SELECT * FROM AVIONES";
print("<table>");
$resultado = $con->query($query); 
foreach ( $resultado as $rows) { 
print("<tr>");
print("<td>".$rows["ID"]."</td>");
print("<td>".$rows["CAPACIDAD"]."</td>");
print("<td>".$rows["DESCRIPCION"]."</td>");
print("</tr>"); 
}
print("</table>");
$resultado =null;


//MySQLi
$query = "SELECT * FROM AVIONES";
$resultado=$mysqli->query($query);
print("<table>");
while ($rows = $resultado->fetch_assoc()) {
print("<tr>");
print("<td>".$rows["ID"]."</td>");
print("<td>".$rows["CAPACIDAD"]."</td>");
print("<td>".$rows["DESCRIPCION"]."</td>");
print("</tr>");
}
print("</table>");
$resultado->free();

Observa el resumen te las características para ejecutar consultas con las extensiones:

MySQL clásica MySQLi PDO
mysql_fetch_array(): Función que obtiene una fila de la consulta. El parámetro indica que tipo de array será retornado.
MYSQL_NUM: Array de retorno con índices numéricos.
MYSQL_ASSOC: Array de retorno con índices asociativos.
MYSQL_BOTH: Array de retorno con ambos tipos de índices.
fetch_assoc(): Método de la clase mysqli_result que obtiene una fila de la consulta en forma de array asociativo. query(): Método de la clase PDO que retorna en un objeto PDOStatement que contiene los resultados de una consulta. Recorreremos cada elemento del objeto con un bucle foreach.fetch(): Método de la clase PDO para obtener una fila de una consulta.
mysql_free_result(): Libera la memoria hacia los resultados de la consulta free(): Libera la memoria asociada Asigna NULL a la variable que recibió la referencia del resultado para liberar la memoria.

Sentencias preparadas en Php

Si recuerdas en los artículos anteriores sobre conexiones era común usar el carácter ‘?’ para indicar que un valor iba a ser variable dentro de una sentencia preparada, es decir, que tomaría distintos valores según los datos que nosotros le asociáramos para ejecutar múltiples veces la sentencia pero con diferentes valores.

Pues bien, las APIs de MySQL para Php utilizan este mismo formato para preparar un comando.

Supón que has creado un formulario que recibe el nombre, apellido, edad y el correo electrónico de un usuario. Ahora deseas que cuando el usuario de clic en el botón de confirmación estos campos sean guardados en tu tabla USUARIO.

Veamos como solucionarlo en los tres complementos.

//MySQL clásico
$query = 'PREPARE sentencia FROM "INSERT INTO usuario VALUES(NULL,?,?,?,?)"';
$resultado = mysql_query($query);
if(!$resultado)
die("Fallo el comando:".mysql_error());
else{
print("PREPARE exitoso!</br>");
$query ='SET @nombre = "'.$nombre.'"'.',@apellido ="'.$apellido.'"'
.',@edad ='.$edad.',@email='.$email;
if(!mysql_query($query))
die("Error en SET: ".mysql_error());
$query = 'EXECUTE sentencia USING @nombre,@apellido,@edad';
if(!mysql_query($query))
die("Error en EXECUTE:".mysql_error());
$query = 'DEALLOCATE PREPARE sentencia';
if(!mysql_query($query))
die("Error en DEALLOCATE:".mysql_error());
}


//MySQLi
if ($stmt = $mysqli->prepare("INSERT INTO usuario VALUES(NULL,?,?,?,?)") ){
/* ligar parámetros para marcadores */
$stmt->bind_param("ssds", $nombre,$apellido,$edad,$email); 
/* ejecutar la consulta */
$stmt->execute();
/* cerrar sentencia */
$stmt->close();
}
else{
echo "Error al ejecutar la sentencia preparada".$mysqli->error;
}


//PDO
$cmd = $con->prepare('INSERT INTO usuario VALUES(NULL,?,?,?,?)');
$cmd->execute(array($nombre,$apellido,$edad,$email));

A continuación se observan las características para crear una sentencia preparada en las apis de conexión:

MySQLi PDO
prepare(): Método de la clase mysqli_stmt para preparar una sentencia genérica.Los parámetros se representan con el carácter ‘?’ o con una etiqueta “:label”. prepare(): Método de la clase PDO para crear una sentencia preparada.
bind_param(): Liga los parámetros de la sentencia preparada mediante alguno de los siguientes indicadores de tipo:i: Tipo entero
d: Tipo float
s: Tipo string
b: Tipo blob
bindParam(): Liga los parámetros de una sentencia preparada.Parámetro 1: Índice del parámetro
Parámetro 2: La variable relacionada al parámetro
Parámetro 3: Tipo de dato
Parámetro 4: Longitud del dato
execute(): Ejecuta un comando preparado. execute(): Ejecuta un comando preparado. Es posible vincular los parámetros en forma de array a través de este método.
get_result(): Obtiene los resultados de una sentencia preparada, si es que la sentencia retorna filas. fetch(): Obtiene una fila de la consulta.Parámetro: Indica como se devuelven los datos.
PDO:FETCH_OBJ: retorna las filas en forma de objetos.
PDO:FETCH_ASSOC: en forma de array asociativo.

La API clásica no soporta crear sentencias preparadas, el ejemplo que vimos fue el uso de la sentencia interna PREPARE de MySQL, intentando simular el comportamiento genérico de un comando.

Ejecutar un Procedimiento almacenado en MySQL

Ejecutar un procedimiento con nuestras extensiones no requiere métodos nuevos ni adornos adicionales. Se hace exactamente con los mismo que hemos venido estudiando en cada complemento. Lo único que debes tener en cuenta es si el procedimiento devuelve una tabla o solo afecta la base de datos. Dependiendo de esa situación elegirás el método apropiado.

A continuación veremos la invocación de un procedimiento que devuelve las estadísticas de un Curso Online realizado por tus Estudiantes  llamado sp_estadistica_curso. Se debe considerar que este método recibe como parámetro de entrada el ID del curso:

//PDO
$proc = $con->prepare('CALL sp_clientes_edad(?)');
$proc->bindParam(1, $var, PDO::PARAM_INT);
$proc->execute();
print("<table>");
while($res=$proc->fetch(PDO::FETCH_OBJ)){
print("<tr>");
print("<td>".$res->NO_ALUMNOS."</td>");
print("<td>".$res->NOTA_MEDIA."</td>");
print("<td>".$res->NOTA_MAX."</td>");
print("<td>".$res->NOTA_MIN."</td>");
print("</tr>");
}
print("</table>");



//MySQLi
if ($stmt = $mysqli->prepare("CALL sp_estadistica_curso(?)") ){
/* ligar parámetros para marcadores */
$stmt->bind_param("d", $Id_curso); 
/* ejecutar la consulta */
$stmt->execute();
$resultado = $stmt->get_result();
print("<table>");
while($rows=$resultado->fetch_assoc()){
print("<tr>");
print("<td>".$rows["NO_ALUMNOS"]);
print("<td>".$rows["NOTA_MEDIA"]);
print("<td>".$rows["NOTA_MAX"]);
print("<td>".$rows["NOTA_MIN"]);
print("</tr>");
}
print("</table>"); 
/* cerrar sentencia */
$stmt->close();
}
else{
echo "Error al ejecutar el procedimiento".$mysqli->error;
} 

Como ves, simplemente es usar la sentencia CALL y ejecutar normalmente el procedimiento como si se tratase de un comando cualquiera.

PDO vs. MySQLi, ¿Cuál debes elegir?

Yo te diría que depende. Primero descarta el API clásica, ya que será descontinuada y seria una perdida de recursos para tus proyectos futuros. Entre MySQLi y PDO también “depende” de las necesidades de tu proyecto. Te invito a que visites este link oficial del sitio de PHP para que veas un cuadro de comparación de beneficios entre las APIs, de seguro te ayudará a sacar conclusiones.