Tutorial de PDO-PHP
Tutorial de PDO-PHP
Tutorial de PDO-PHP
Indice de contenido
1. Introducción
PDO significa PHP Data Objects, Objetos de Datos de PHP, una extensión para
acceder a bases de datos. PDO permite acceder a diferentes sistemas de bases de datos
con un controlador específico (MySQL, SQLite, Oracle...) mediante el cual se conecta.
Independientemente del sistema utilizado, se emplearán siempre los mismos métodos,
lo que hace que cambiar de uno a otro resulte más sencillo.
print_r(PDO::getAvailableDrivers());
try {
$dsn = "mysql:host=localhost;dbname=$dbname";
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e){
echo $e->getMessage();
}
DBH significa Database Handle, y es el nombre de variable que se suele utilizar para
el objeto PDO.
$dbh = null;
PDO maneja los errores en forma de excepciones, por lo que la conexión siempre ha
de ir encerrada en un bloque try/catch. Se puede (y se debe) especificar el modo de error
estableciendo el atributo error mode:
$dbh->setAttribute(PDO::ATTRR_ERRMODE, PDO::ERRMODE_SILENT);
$dbh->setAttribute(PDO::ATTRR_ERRMODE, PDO::ERRMODE_WARNING);
$dbh->setAttribute(PDO::ATTRR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Prepare
$stmt = $dbh->prepare("INSERT INTO Clientes (nombre, ciudad) VALUES
(?, ?)");
// Bind
$nombre = "Peter";
$ciudad = "Madrid";
$stmt->bindParam(1, $nombre);
$stmt->bindParam(2, $ciudad);
// Excecute
$stmt->execute();
// Bind
$nombre = "Martha";
$ciudad = "Cáceres";
$stmt->bindParam(1, $nombre);
$stmt->bindParam(2, $ciudad);
// Execute
$stmt->execute();
Utilizando variables para los valores
// Prepare
$stmt = $dbh->prepare("INSERT INTO Clientes (nombre, ciudad) VALUES
(:nombre, :ciudad)");
// Bind
$nombre = "Charles";
$ciudad = "Valladolid";
$stmt->bindParam(':nombre', $nombre);
$stmt->bindParam(':ciudad', $ciudad);
// Excecute
$stmt->execute();
// Bind
$nombre = "Anne";
$ciudad = "Lugo";
$stmt->bindParam(':nombre', $nombre);
$stmt->bindParam(':ciudad', $ciudad);
// Execute
$stmt->execute();
También existe un método lazy, que es pasando los valores mediante un array
(siempre array, aunque sólo haya un valor) al método execute():
// Prepare:
$stmt = $dbh->prepare("INSERT INTO Clientes (nombre, ciudad) VALUES
(:nombre, :ciudad)");
$nombre = "Luis";
$ciudad = "Barcelona";
// Bind y execute:
if($stmt->execute(array(':nombre'=>$nombre, ':ciudad'=>$ciudad))) {
echo "Se ha creado el nuevo registro!";
}
Una característica importante cuando se utilizan variables para pasar los valores es que
se pueden insertar objetos directamente en la base de datos, suponiendo que las
propiedades coinciden con los nombres de las variables:
class Clientes
{
public $nombre;
public $ciudad;
public function __construct($nombre, $ciudad){
$this->nombre = $nombre;
$this->ciudad = $ciudad;
}
// ....Código de la clase....
}
$cliente = new Clientes("Jennifer", "Málaga");
$stmt = $dbh->prepare("INSERT INTO Clientes (nombre, ciudad) VALUES
(:nombre, :ciudad)");
if($stmt->execute((array) $cliente)){
echo "Se ha creado un nuevo registro!";
};
// Prepare:
$stmt = $dbh->prepare("INSERT INTO Clientes (nombre) VALUES
(:nombre)");
$nombre = "Morgan";
// Bind
$stmt->bindParam(':nombre', $nombre); // Se enlaza a la variable
$nombre
// Si ahora cambiamos el valor de $nombre:
$nombre = "John";
$stmt->execute(); // Se insertará el cliente con el nombre John
// Prepare:
$stmt = $dbh->prepare("INSERT INTO Clientes (nombre) VALUES
(:nombre)");
$nombre = "Morgan";
// Bind
$stmt->bindValue(':nombre', $nombre); // Se enlaza al valor Morgan
// Si ahora cambiamos el valor de $nombre:
$nombre = "John";
$stmt->execute(); // Se insertará el cliente con el nombre Morgan
En la práctica bindValue() se suele usar cuando se tienen que insertar datos sólo una
vez, y bindParam() cuando se tienen que pasar datos múltiples (desde un array por
ejemplo).
Ambas funciones aceptan un tercer parámetro, que define el tipo de dato que se
espera. Los data types más utilizados son: PDO::PARAM_BOOL (booleano),
PDO::PARAM_NULL (null), PDO::PARAM_INT (integer) y PDO::PARAM_STR
(string).
// FETCH_ASSOC
$stmt = $dbh->prepare("SELECT * FROM Clientes");
// Especificamos el fetch mode antes de llamar a fetch()
$stmt->setFetchMode(PDO::FETCH_ASSOC);
// Ejecutamos
$stmt->execute();
// Mostramos los resultados
while ($row = $stmt->fetch()){
echo "Nombre: {$row["nombre"]} <br>";
echo "Ciudad: {$row["ciudad"]} <br><br>";
}
// FETCH_OBJ
$stmt = $dbh->prepare("SELECT * FROM Clientes");
// Ejecutamos
$stmt->execute();
// Ahora vamos a indicar el fetch mode cuando llamamos a fetch:
while($row = $stmt->fetch(PDO::FETCH_OBJ)){
echo "Nombre: " . $row->nombre . "<br>";
echo "Ciudad: " . $row->ciudad . "<br>";
}
// Preparamos
$stmt = $dbh->prepare("SELECT nombre, ciudad FROM Clientes");
// Ejecutamos
$stmt->execute();
// bindColumn
$stmt->bindColumn(1, $nombre);
$stmt->bindColumn('ciudad', $ciudad);
while ($row = $stmt->fetch(PDO::FETCH_BOUND)) {
$cliente = $nombre . ": " . $ciudad;
echo $cliente . "<br>";
}
El estilo de devolver los datos FETCH_CLASS es algo más complejo: devuelve los
datos directamente a una clase. Las propiedades del objeto se establecen ANTES de
llamar al constructor. Si hay nombres de columnas que no tienen una propiedad creada
para cada una, se crean como public. Si los datos necesitan una transformación antes
de que salgan de la base de datos, se puede hacer automáticamente cada vez que se
crea un objeto:
class Clientes
{
public $nombre;
public $ciudad;
public $otros;
public function __construct($otros = ''){
$this->nombre = strtoupper($this->nombre);
$this->ciudad = mb_substr($this->ciudad, 0, 3);
$this->otros = $otros;
}
// ....Código de la clase....
}
$stmt = $dbh->prepare("SELECT * FROM Clientes");
$stmt->setFetchMode(PDO::FETCH_CLASS, 'Clientes');
$stmt->execute();
while ($objeto = $stmt->fetch()){
echo $objeto->nombre . " -> ";
echo $objeto->ciudad . "<br>";
}
Con lo anterior hemos podido modificar cómo queríamos mostrar nombre y ciudad de
cada registro. A nombre lo hemos puesto en mayúsculas y de ciudad sólo hemos
mostrado las tres primeras letras.
$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE,
'Clientes';
$i = 0;
while ($row = $stmt->fetch(PDO::FETCH_CLASS, 'Clientes', array($i))){
// Código para hacer algo
$i++;
}
execute() ejecuta una sentencia preparada lo que permite enlazar parámetros y evitar
tener que escapar los parámetros. execute() también tiene mejor rendimiento si se repite
una sentencia múltiples veces, ya que se compila en el servidor de bases de datos sólo
una vez.
Ya hemos visto como funcionan las sentencias preparadas con prepare() y execute(),
vamos a ver un ejemplo con query():
Cuando tenemos que ejecutar varias sentencias de vez, como INSERT, es preferible
utilizar transacciones ya que agrupa todas las acciones y permite revertirlas todas en
caso de que haya algún error.
try {
$dbh->beginTransaction();
$dbh->query("INSERT INTO Clientes (nombre, ciudad) VALUES ('Leila
Birdsall', 'Madrid')");
$dbh->query("INSERT INTO Clientes (nombre, ciudad) VALUES ('Brice
Osterberg', 'Teruel')");
$dbh->query("INSERT INTO Clientes (nombre, ciudad) VALUES
('Latrisha Wagar', 'Valencia')");
$dbh->query("INSERT INTO Clientes (nombre, ciudad) VALUES ('Hui
Riojas', 'Madrid')");
$dbh->query("INSERT INTO Clientes (nombre, ciudad) VALUES ('Frank
Scarpa', 'Barcelona')");
$dbh->commit();
echo "Se han introducido los nuevos clientes";
} catch (Exception $e){
echo "Ha habido algún error";
$dbh->rollback();
}