PDO

RECU-0258 (Recurso Ficha Técnica)

Descripción

La extensión Objetos de Datos de PHP (PDO por sus siglás en inglés) define un interfaz ligera para poder acceder a bases de datos en PHP. Cada controlador de bases de datos que implemente la interfaz PDO puede exponer características específicas de la base de datos, como las funciones habituales de la extensión. Obsérvese que no se puede realizar ninguna de las funciones de la bases de datos utilizando la extensión PDO por sí misma; se debe utilizar un controlador de PDO específico de la base de datos para tener acceso a un servidor de bases de datos.

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. PDO no proporciona una abstracción de bases de datos; no reescribe SQL ni emula características ausentes. Se debería usar una capa de abstracción totalmente desarrollada si fuera necesaria tal capacidad.

PDO viene con PHP 5.1, y está disponible como una extensión PECL para PHP 5.0; PDO requiere las características nuevas de OO del núcleo de PHP 5, por lo que no se ejecutará con versiones anteriores de PHP.

Ejemplos

A continuación se ofrece un ejemplo de cómo se maneja PDO, conectando con una base de datos y lanzando consultas relacionadas con la misma:

<html>
<head>
<title>AdventureWorks Product Reviews</title>
</head>
<body>
<h1 align='center'>AdventureWorks Product Reviews</h1>
<h5 align='center'>This application is a demonstration of the PDO interface for the Microsoft SQL Server Driver for PHP.</h5><br/>
<?php
$serverName = "(local)\sqlexpress";

/* Conexión usando autenticacion de windows */
try
{
$conn = new PDO( "sqlsrv:server=$serverName ; Database=AdventureWorks2008", "", "");
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch(Exception $e)
{
die( print_r( $e->getMessage() ) );
}

if(isset($_REQUEST['action']))
{
switch( $_REQUEST['action'] )
{
/* Obtiene los productos haciendo una consulta con el nombre de los productos.*/
case 'getproducts':
try
{
$queryTerms = array($_POST['query']);
$tsql = "SELECT ProductID, Name, Color, Size, ListPrice
 FROM Production.Product
 WHERE Name LIKE '%' + ? + '%' AND ListPrice > 0.0";
           
$getProducts = $conn->prepare($tsql);
$getProducts->execute($queryTerms);
$products = $getProducts->fetchAll(PDO::FETCH_ASSOC);

$productCount = count($products);
if($productCount > 0)
{
BeginProductsTable($productCount);
foreach( $products as $row )
{
PopulateProductsTable( $row );
}
EndProductsTable();
}
else
{
DisplayNoProdutsMsg();
}
}
catch(Exception $e)
{
die( print_r( $e->getMessage() ) );
}
            GetSearchTerms( !null );
            break;

/* Obtiene información de un producto determinado por su identificador. */
case 'getreview':
            GetPicture( $_GET['productid'] );
            GetReviews( $conn, $_GET['productid'] );
            break;

/* Escribe información de un producto determinado por su identificador. */
case 'writereview':
            DisplayWriteReviewForm( $_POST['productid'] );
            break;

/* Envía la información a la base de datos. */
case 'submitreview':
try
{
$tsql = "INSERT INTO Production.ProductReview (ProductID, ReviewerName, ReviewDate, EmailAddress, Rating, Comments)
 VALUES (?,?,?,?,?,?)";
$params = array(&$_POST['productid'], &$_POST['name'], date("Y-m-d"), &$_POST['email'], &$_POST['rating'], $_POST['comments']);
$insertReview = $conn->prepare($tsql);
$insertReview->execute($params);
}
catch(Exception $e)
{
die( print_r( $e->getMessage() ) );
}
GetSearchTerms( true );
GetReviews( $conn, $_POST['productid'] );
break;

        /* Display form for uploading a picture.*/
        case 'displayuploadpictureform':
            try
{
$tsql = "SELECT Name FROM Production.Product WHERE ProductID = ?";
$getName = $conn->prepare($tsql);
$getName->execute(array($_GET['productid']));
$name = $getName->fetchColumn(0);
}
catch(Exception $e)
{
die( print_r( $e->getMessage() ) );
}
            DisplayUploadPictureForm( $_GET['productid'], $name );
            break;

        /* Upload a new picture for the selected product. */
        case 'uploadpicture':        
            try
{
    $tsql = "INSERT INTO Production.ProductPhoto (LargePhoto) VALUES (?)";
$uploadPic = $conn->prepare($tsql);
$fileStream = fopen($_FILES['file']['tmp_name'], "r");
$uploadPic->bindParam(1,  $fileStream, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
$uploadPic->execute();

/* Obtiene el primer campo asociándolo al identificador del producto */
$photoID = $conn->lastInsertId();
$tsql = "UPDATE Production.ProductProductPhoto SET ProductPhotoID = ? WHERE ProductID = ?";
$associateIds = $conn->prepare($tsql);
$associateIds->execute(array($photoID, $_POST['productid']));
}
catch(Exception $e)
{
die(print_r($e->getMessage()));
}

GetPicture( $_POST['productid']);
DisplayWriteReviewButton( $_POST['productid'] );
GetSearchTerms (!null);
break;
}//End Switch
}
else
{
    GetSearchTerms( !null );
}

function GetPicture( $productID )
{
    echo "<table align='center'><tr align='center'><td>";
    echo "<img src='photo_pdo.php?productId=".$productID."'
      height='150' width='150'/></td></tr>";
    echo "<tr align='center'><td><a href='?action=displayuploadpictureform&productid=".$productID."'>Upload new picture.</a></td></tr>";
    echo "</td></tr></table></br>";
}

function GetReviews( $conn, $productID )
{
try
{
$tsql = "SELECT ReviewerName, CONVERT(varchar(32), ReviewDate, 107) AS [ReviewDate], Rating, Comments
 FROM Production.ProductReview
 WHERE ProductID = ?
 ORDER BY ReviewDate DESC";
$getReviews = $conn->prepare( $tsql);
$getReviews->execute(array($productID));
$reviews = $getReviews->fetchAll(PDO::FETCH_NUM);
$reviewCount = count($reviews);
if($reviewCount > 0 )
{
foreach($reviews as $row)
{
$name = $row[0];
$date = $row[1];
$rating = $row[2];
$comments = $row[3];
DisplayReview( $productID, $name, $date, $rating, $comments );
}
}
else
{
DisplayNoReviewsMsg();
}
}
catch(Exception $e)
{
die(print_r($e->getMessage()));
}
    DisplayWriteReviewButton( $productID );
GetSearchTerms(!null);
}

/*** Presentation and Utility Functions ***/

function BeginProductsTable($rowCount)
{
    /* Display the beginning of the search results table. */
$headings = array("Product ID", "Product Name", "Color", "Size", "Price");
echo "<table align='center' cellpadding='5'>";
echo "<tr bgcolor='silver'>$rowCount Results</tr><tr>";
foreach ( $headings as $heading )
{
echo "<td>$heading</td>";
}
echo "</tr>";
}

function DisplayNoProdutsMsg()
{
    echo "<h4 align='center'>No products found.</h4>";
}

function DisplayNoReviewsMsg()
{
    echo "<h4 align='center'>There are no reviews for this product.</h4>";
}

function DisplayReview( $productID, $name, $date, $rating, $comments)
{
    /* Display a product review. */
    echo "<table style='WORD-BREAK:BREAK-ALL' width='50%' align='center' border='1' cellpadding='5'>";
    echo "<tr>
            <td>ProductID</td>
            <td>Reviewer</td>
            <td>Date</td>
            <td>Rating</td>
          </tr>";
      echo "<tr>
              <td>$productID</td>
              <td>$name</td>
              <td>$date</td>
              <td>$rating</td>
            </tr>
            <tr>
              <td width='50%' colspan='4'>$comments</td></tr></table><br/><br/>";
}

function DisplayUploadPictureForm( $productID, $name )
{
    echo "<h3 align='center'>Upload Picture</h3>";
    echo "<h4 align='center'>$name</h4>";
    echo "<form align='center' action='adventureworks_demo_pdo.php' enctype='multipart/form-data' method='POST'>
<input type='hidden' name='action' value='uploadpicture'/>
<input type='hidden' name='productid' value='$productID'/>
<table align='center'>
         <tr>
           <td align='center'>
             <input id='fileName' type='file' name='file'/>
           </td>
         </tr>
         <tr>
           <td align='center'>
            <input type='submit' name='submit' value='Upload Picture'/>
           </td>
         </tr>
</table>
</form>";
}

function DisplayWriteReviewButton( $productID )
{
    echo "<table align='center'><form action='adventureworks_demo_pdo.php' enctype='multipart/form-data' method='POST'>
          <input type='hidden' name='action' value='writereview'/>
          <input type='hidden' name='productid' value='$productID'/>
          <input type='submit' name='submit' value='Write a Review'/>
          </p></td></tr></form></table>";
}

function DisplayWriteReviewForm( $productID )
{
    /* Display the form for entering a product review. */
    echo "<h5 align='center'>Name, E-mail, and Rating are required fields.</h5>";
    echo "<table align='center'>
<form action='adventureworks_demo_pdo.php' enctype='multipart/form-data' method='POST'>
<input type='hidden' name='action' value='submitreview'/>
<input type='hidden' name='productid' value='$productID'/>
<tr>
<td colspan='5'>Name: <input type='text' name='name' size='50'/></td>
</tr>
<tr>
<td colspan='5'>E-mail: <input type='text' name='email' size='50'/></td>
</tr>
<tr>
<td>Rating: 1<input type='radio' name='rating' value='1'/></td>
<td>2<input type='radio' name='rating' value='2'/></td>
<td>3<input type='radio' name='rating' value='3'/></td>
<td>4<input type='radio' name='rating' value='4'/></td>
<td>5<input type='radio' name='rating' value='5'/></td>
</tr>
<tr>
<td colspan='5'>
<textarea rows='20' cols ='50' name='comments'>[Write comments here.]</textarea>
</td>
</tr>
<tr>
<td colspan='5'>
                 <p align='center'><input type='submit' name='submit' value='Submit Review'/>
</td>
</tr>
</form>
          </table>";
}

function EndProductsTable()
{
    echo "</table><br/>";
}

function GetSearchTerms( $success )
{
    /* Get and submit terms for searching the database. */
    if (is_null( $success ))
    {
echo "<h4 align='center'>Review successfully submitted.</h4>";}
echo "<h4 align='center'>Enter search terms to find products.</h4>";
echo "<table align='center'>
            <form action='adventureworks_demo_pdo.php' enctype='multipart/form-data' method='POST'>
            <input type='hidden' name='action' value='getproducts'/>
            <tr>
               <td><input type='text' name='query' size='40'/></td>
            </tr>
            <tr align='center'>
               <td><input type='submit' name='submit' value='Search'/></td>
            </tr>
            </form>
            </table>";
}

function PopulateProductsTable( $values )
{
    /* Populate Products table with search results. */
    $productID = $values['ProductID'];
    echo "<tr>";
    foreach ( $values as $key => $value )
    {
        if ( 0 == strcasecmp( "Name", $key ) )
        {
            echo "<td><a href='?action=getreview&productid=$productID'>$value</a></td>";
        }
        elseif( !is_null( $value ) )
        {
            if ( 0 == strcasecmp( "ListPrice", $key ) )
            {
                /* Format with two digits of precision. */
                $formattedPrice = sprintf("%.2f", $value);
                echo "<td>$$formattedPrice</td>";
            }
            else
            {
                echo "<td>$value</td>";
            }
        }
        else
        {
            echo "<td>N/A</td>";
        }
    }
    echo "<td>
            <form action='adventureworks_demo_pdo.php' enctype='multipart/form-data' method='POST'>
            <input type='hidden' name='action' value='writereview'/>
            <input type='hidden' name='productid' value='$productID'/>
            <input type='submit' name='submit' value='Write a Review'/>
            </td></tr>
            </form></td></tr>";
}
?>
</body>
</html>

Ventajas e inconvenientes

PDO ofrece las siguientes características funcionales:

  • Manejo de conexiones con los diferentes proveedores de base de datos
  • Manejo de los errores producidos en la conexión
  • Cierre y persistencias de las conexiones
  • Manejo de las transacciones, permitiendo el autocommit
  • Inserciones de procedimientos e instrucciones preparadas
  • Manejo de errores y avisos

Contenidos relacionados

Recursos
Área: Desarrollo » Construcción de Aplicaciones por Capas » Capa de Persistencia » PHP
Código Título Tipo Carácter
RECU-0259 Propel Referencia Recomendado