14 de abril de 2015

Apuntes PDO PHP

PDO proporciona una capa de abstracción de acceso a datos, lo que significa que, independientemente de la base de datos que se esté utilizando, se usan las mismas funciones para realizar consultas y obtener datos. Para cada base de datos existe un manejador (driver) específico, que debe estar habilitado en el archivo de configuración de PHP (el archivo php.ini). Los manejadores se administran mediante extensiones de PHP, las cuales tienen nombres finalizando con dll en Windows y con so en Unix.
extension=php_pdo.dll
extension=php_pdo_firebird.dll
extension=php_pdo_informix.dll
extension=php_pdo_mssql.dll
extension=php_pdo_mysql.dll
extension=php_pdo_oci.dll
extension=php_pdo_oci8.dll
extension=php_pdo_odbc.dll
extension=php_pdo_pgsql.dll
extension=php_pdo_sqlite.dll
Ejemplo conexiones PDO
<?php
try {
 // Conexión a MS SQL Server 
  $cnn = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass");
  
  // Conexión a Sybase
  $cnn = new PDO("sybase:host=$host;dbname=$dbname, $user, $pass");
 
  // Conexion a MySQL 
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
 
  // Conexion a SQLite
  $DBH = new PDO("sqlite:my/database/path/database.db");
}
catch(PDOException $e) {
    echo $e->getMessage();
}
?>
Conexion PDO-MySQL
<?php
try{
        $this->db = new PDO(DB_MOTOR.':host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
        $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        $this->db->setAttribute(PDO::ATTR_PERSISTENT,true);
        $this->db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
   
   }catch(PDOException $e){
         echo 'Ha surgido un error y no se puede conectar a la base de datos' .E_USER_ERROR. PHP_EOL;
         echo "";
         echo "Detalle: ".$e->getMessage();
         exit;
      }
?>
Ejemplo Excepciones PDO
$cnn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$cnn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$cnn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
es mas util la opcion ERRMODE_EXCEPTION, aqui el ejemplo
try {
  $cnn = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  $cnn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
 
  $cnn->prepare('DELECT name FROM people');
}
catch(PDOException $e) {
    echo "Error en la consulta";
    file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}
Ejemplo de sentencia SELECT
$sql= "SELECT filmID, filmName, filmDescription, filmImage, filmPrice, filmReview FROM movies WHERE filmID = :filmID"; 
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':filmID', $filmID, PDO::PARAM_INT); 
$stmt->execute();
$obj = $stmt->fetchObject();
echo $obj->filmName;
Ejemplo de Unnamed Placeholders
Es necesario mantener el orden al momento de especificar los valores de la sentencia
<?php
 ini_set('display_errors', '0');
 include_once('connect.php');
 include_once('error_handling.php');

 $team = 'Yamaha';
 $status = 'Factory';

 $sqlQuery = "SELECT * from riders where team = ? AND status = ?";

 $statement = $dbh->prepare($sqlQuery);

 $statement->bindValue('1', $team, PDO::PARAM_STR); 
 $statement->bindValue('2', $status, PDO::PARAM_STR); 

 try{
  $statement->execute();
 }
 catch(PDOException $error){
  echo errorHandling($error);
 }
 while($row = $statement->fetch(PDO::FETCH_ASSOC)) {
  echo $row['name'] . " rides a " . $row['team'] . " " . $row['status'] . " MotoGP bike!
";
 }
?>
Ejemplo de Named Placeholders
No es necesario estar pendiente del orden de los parámetros pero si de especificar adecuadamente el par clave=>valor.
<?php
 ini_set('display_errors', '0');
 include_once('connect.php');
 include_once('error_handling.php');

 $team = 'Yamaha';
 $status = 'Factory';

 $sqlQuery = "SELECT * from riders where team = :team AND status = :status";

 $statement = $dbh->prepare($sqlQuery);

 $statement->bindParam(':team', $team, PDO::PARAM_STR);
 $statement->bindParam(':status', $status, PDO::PARAM_STR);

 try{
  $statement->execute();
 }
 catch(PDOException $error){
  echo errorHandling($error);
 }
 while($row = $statement->fetch(PDO::FETCH_ASSOC)) {
  echo $row['name'] . " rides a " . $row['team'] . " " . $row['status'] . " MotoGP bike!
";
 }
?>
Ejemplo Sentencia INSERT
<?php
$nom = 'Jose';
$ape = 'Hernandez';
 
try
{
  $con = new PDO('mysql:host=localhost;dbname=personal', 'user', 'pass');
  $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
  $stmt = $con->prepare('INSERT INTO personal (nombre, apellidos) VALUES (:nombre, :apellidos)');
  $rows = $stmt->execute( array( ':nombre'   => $nom,
                                    ':apellidos' => $ape));
 
  if( $rows == 1 )
    echo 'Inserción correcta';
}
catch(PDOException $e)
{
  echo 'Error: ' . $e->getMessage();
}
?>
Ejemplo Sentencia UPDATE
<?php
$nom = 'Jose';
$ape = 'Hernandez';
 
try
{
  $con = new PDO('mysql:host=localhost;dbname=personal', 'user', 'pass');
  $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
  $stmt = $con->prepare('UPDATE personal SET apellidos = :apellidos WHERE nombre = :nombre');
  $rows = $stmt->execute( array( ':nombre'   => $nom,
                                    ':apellidos' => $ape));
  if( $rows > 0 )
    echo 'Actualización correcta';
}
catch(PDOException $e)
{
  echo 'Error: ' . $e->getMessage();
}
?>
Ejemplo Sentencia DELETE
<?php
$ape = 'Hernandez';
 
try
{
  $con = new PDO('mysql:host=localhost;dbname=personal', 'user', 'pass');
  $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
  $stmt = $con->prepare('DELETE FROM personal WHERE apellidos = :apellidos');
  $rows = $stmt->execute( array( ':apellidos' => $ape));
 
  if( $rows > 0 )
    echo 'Borrado correcto';
}
catch(PDOException $e)
{
  echo 'Error: ' . $e->getMessage();
}
?>
Mapeo de Objetos
PDO nos permite realizar consultas y mapear los resultados en objetos de nuestro modelo. Para ello primero tenemos que crearnos una clase con nuestro modelo de datos.
<?php
// la clase puede estar en una
// ubicación o folder especifico 

class Usuario{
  private $nombre;
  private $apellidos;
 
  public function nombreApellidos()
  {
    return $this->nombre . ' ' . $this->apellidos;
  }
}
?>
como ejemplo se utilizara una sentencia SELECT, Hay que tener en cuenta que para que funcione correctamente, el nombre de los atributos en nuestra clase tienen que ser iguales que los que tienen las columnas en nuestra tabla de la base de datos. Con esto claro vamos a realizar la consulta.
<?php
try
{
  $con = new PDO('mysql:host=localhost;dbname=personal', 'user', 'pass');
  $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
 $stmt= $con->prepare('SELECT nombre, apellidos FROM personal');
  $stmt->execute();
 
  $stmt->setFetchMode(PDO::FETCH_CLASS, 'Usuario');
 
  while($usuario = $stmt->fetch())
    echo $usuario->nombreApellidos() . '
';
 
}
catch(PDOException $e)
{
  echo 'Error: ' . $e->getMessage();
}
?>
Ejemplo INSERT con Object Mapping
<?php
class person {
    public $name;
    public $addr;
    public $city;
 
    function __construct($n,$a,$c) {
        $this->name = $n;
        $this->addr = $a;
        $this->city = $c;
    }
    # etc ...
}
 
$cathy = new person('Cathy','9 Dark and Twisty','Cardiff');
 
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute((array)$cathy);
?>
FETCHMODE en consultas SELECT Utilizando query() y PDO::FETCH_NUM
<?php
$sql = 'SELECT name, colour, calories FROM fruit';
try {
  $stmt = $dbh->query($sql);
  $result = $stmt->setFetchMode(PDO::FETCH_NUM);
  while ($row = $stmt->fetch()) {
    print $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n";
  }
}
catch (PDOException $e) {
  print $e->getMessage();
}
?>
Utilizando query() y PDO::FETCH_ASSOC
<?php
$stmt = $dbh->prepare("SELECT mykey, myvalue FROM mytable");
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$arrValues = $stmt->fetchAll();
foreach ($arrValues as $row){
    print $row["mykey"]." -> ".$row["myvalue"]."
\n";
}
?>
Utilizando query() y PDO::FETCH_OBJ
<?php
$STH = $DBH->query('SELECT name, addr, city from folks'); 

$STH->setFetchMode(PDO::FETCH_OBJ);
 
while($row = $STH->fetch()) {
    echo $row->name . "\n";
    echo $row->addr . "\n";
    echo $row->city . "\n";
}
?>
Utilizando Unnamed Placeholders, execute() y PDO::FETCH_ASSOC
<?php
try {
    $conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
 
    $sql = 'SELECT lastname, firstname, jobtitle 
            FROM employees
            WHERE lastname LIKE ?';
 
    $q = $conn->prepare($sql);
    $q->execute(array('%son'));
    $q->setFetchMode(PDO::FETCH_ASSOC);
 
    while ($r = $q->fetch()) {
        echo sprintf('%s 
', $r['lastname']);
    }
} catch (PDOException $pe) {
    die("Could not connect to the database $dbname :" . $pe->getMessage());
}
?>
Utilizando Named Placeholders, execute() y PDO::FETCH_ASSOC
<?php
try {
    $conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
 
    $sql = 'SELECT lastname, firstname, jobtitle 
            FROM employees
            WHERE lastname  LIKE :lname OR
                  firstname LIKE :fname';
 
    $q = $conn->prepare($sql);
    $q->execute(array(':fname' => 'Le%',
                      ':lname' => '%son'));
    $q->setFetchMode(PDO::FETCH_ASSOC);
 
    while ($r = $q->fetch()) {
        echo sprintf('%s 
', $r['lastname']);
    }
} catch (PDOException $pe) {
    die("Could not connect to the database $dbname :" . $pe->getMessage());
}
?>
Transacciones en PDO
Debido a que no todas las bases de datos soportan transacciones, PHP corre en el modo de auto-commit que ejecuta cada instrucción individual en forma implícita. Si se desea usar transacciones, y no se desea utilizar el modo de auto-commit, es necesario invocar el método PDO::beginTransaction()al inicio de la transacción. Si el manejador de la base de datos no permite el uso de transacciones se producirá una excepción (PDOException). Cuando se acabe de especificar la transacción se pueden utilizar los métodos PDO::Commit para aplicar dichas instrucciones, o bien, PDO::rollBack para abortar dicha transacción.

<?php
try {
  $stmt = $dbh->prepare("INSERT INTO countries (name, area, population, density)
                                VALUES (:name, :area, :population, :density)");
  $stmt->bindParam(':name', $name);
  $stmt->bindParam(':area', $area);
  $stmt->bindParam(':population', $population);
  $stmt->bindParam(':density', $density);

  $dbh->beginTransaction();
  $name = 'Nicaragua'; $area = 129494; $population = 602800; $density = 46.55;
  $stmt->execute();
  $name = 'Panama'; $area = 78200; $population = 3652000; $density = 46.70;
  $stmt->execute();
  $dbh->commit();

} catch (Exception $e) {
  $dbh->rollBack();
  echo "Failed: " . $e->getMessage();
}
?>
o bien este ejemplo en que se utiliza un array para especificar los valores de la consulta
<?php
try {
  $stmt = $dbh->prepare("INSERT INTO countries (name, area, population, density)
                                VALUES (?, ?, ?, ?)");

  $dbh->beginTransaction();
  $stmt->execute(array('Nicaragua', 129494, 602800, 46.55));
  $stmt->execute(array('Panama', 78200, 3652000, 46.70));
  $dbh->commit();

} catch (Exception $e) {
  $dbh->rollBack();
  echo "Failed: " . $e->getMessage();
}
?>

Related Posts:

  • Patrón Dependency InjectionRobert C. Martin afirma en el Principio de Inyección de Dependencias: A. Las clases de alto nivel no deberían depender de las clases de bajo nivel. Ambas deberían depender de las abstracciones. B. Las abstracciones no deber… Read More
  • Session Fixation PHPSession fixation Session fixation (fijación de sesión) es un método de Session hijacking (robo de sesión) un poco especial, ya que, si normalmente en el robo de sesión se intenta conseguir el identificador de sesión de un us… Read More
  • Login PHP con password_hash()Primero una aclaración…como no guardar contraseñas No guardar contraseñas en texto plano, esto debería ser obvio ya que si alguien tiene acceso a tu base de datos y a las contraseñas de tus usuarios, si un ataque externo…o in… Read More
  • ob_start PHPAl programar en PHP primero se realiza un procesamiento de la página que se muestra en el ordenador del usuario, luego se envía la petición al servidor y por último se envía al ordenador del usuario el resultado de procesar e… Read More
  • Login PHP con crypt() y BlowfishEn esta entrada se utilizara la función crypt() y Blowfish, otra opción muy aceptable es utilizar password_hash(), dejo este link con una explicación del tema en Login PHP con password_hash(), pasando a la función crypt() co… Read More