Motivos para usar PHP con PDO siempre - reasons for development with PHP pdo always

Porque debería usar PHP’s PDO Para acceder a Bases de Datos? Parte 1

Muchos programadores aprendieron como obtener acceso a bases de datos mysql usando las extensiones mysql o mysqli.
A partir de PHP 5.1, se encuentra disponible una mejor opción. PDO (PHP Data Objects) provee métodos para preparar consulta SQL
Y trabajar con objetos que le harán mucho más productivo!

Introducción PDO
“PDO – PHP Data Objects – es una capa de acceso estandarizada que proporciona un método uniforme de acceso a múltiples bases de datos”.
No toma en cuenta para la sintaxis de base de datos específica, pero puede permitir migrar fácilmente de entre motores bases de datos y plataformas sin muchos dolores de cabeza, cambiando la cadena de conexión en la mayoría de los casos.
Este post está dirigido a personas que actualmente usan las extesiones mysql y mysqli para obtener acceso a bases de datos.

Motores de Bases de datos soportados
La extensión puede soportar cualquier base de datos para que exista escrito un driver PDO. Actualmente los controladores de bases de datos disponibles son las siguientes:

• PDO_DBLIB ( FreeTDS/Microsoft SQL Server/Sybase )
• PDO_FIREBIRD ( Firebird/Interbase 6 )
• PDO_IBM ( IBM DB2 )
• PDO_INFORMIX ( IBM Informix Dynamic Server )
• PDO_MYSQL ( MySQL 3.x/4.x/5.x )
• PDO_OCI ( Oracle Call Interface )
• PDO_ODBC ( ODBC v3 (IBM DB2, unixODBC ywin32 ODBC) )
• PDO_PGSQL ( PostgreSQL )
• PDO_SQLITE ( SQLite 3 ySQLite 2 )
• PDO_4D ( 4D )
Todos estos controladores no están necesariamente disponibles en su sistema, una forma rápida de saber con que controladores se cuenta en el sistema:
?
1
2
3
print_r(PDO::getAvailableDrivers()); 

Establecer Conexión
Diferentes bases de datos pueden tener diferentes métodos de conexión. A continuación, muestro el método para conectarse a algunos de los motores de bases de datos más populares. Observe que los tres primeros son idénticos a excepción de la conexión SQLite el cual cuenta con una sintaxis propia.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try
  // MS SQL Server ySybase con PDO_DBLIB 
  $DBH = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass"); 
  $DBH = new PDO("sybase:host=$host;dbname=$dbname, $user, $pass"); 
   
  // MySQL con PDO_MYSQL 
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 
   
  // SQLite
  $DBH = new PDO("sqlite:my/database/path/database.db"); 
catch(PDOException $e) { 
    echo $e->getMessage(); 

Por favor, tome nota del bloque try/catch, siempre debe realizar sus operaciones PDO en un try/catch, y utilizar el mecanismo de excepción pertinente, esto lo veremos en breve. Normalmente, usted sólo va a hacer una sola conexión, $DBH representa nuestra conexión a la base de datos que especifiquemos.
Usted puede cerrar cualquier conexión estableciendo la instancia del objeto en null.
?
1
2
3
4
//SQLite
$DBH = null; 

Puede obtener más información sobre las opciones específicas de base de datos y/o cadenas de conexión para otras bases de datos en PHP.net .

PDO y las Excepciones
PDO puede utilizar excepciones para controlar los errores. Puede forzar PDO en uno de los tres modos de error al establecer el atributo error mode en la conexión de su base de datos. Ésta es la sintaxis:
?
1
2
3
4
5
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT ); 
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING ); 
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); 

No importa el valor que se establezca en el error mode, un error de conexión siempre produce una excepción y la creación de una conexión siempre debe estar contenida en un bloque try/catch.

PDO:: ERRMODE_SILENT
Este es el modo de error por defecto. Si lo deja en este modo, se debe comprobar si hay errores. Los otros dos métodos son más ideales para la programación de SECO.

PDO:: ERRMODE_WARNING
Este modo emitirá un nivel de alerta de PHP, y permite a la programa continuar con su ejecución. Es útil en procesos de depuración.

PDO:: ERRMODE_EXCEPTION
Este es el modo sugerido en la mayoría de las situaciones. Se dispara una excepción, lo que le permite controlar los errores con gracia y ocultar los datos que puedan ayudar a alguien a realizar operaciones mal intencionadas en el sistema. Un ejemplo de tomar ventaja de las excepciones:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Conexion
try
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 
  $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); 
   
  //Error incrustado DELECT = DELETE 
  $DBH->prepare('DELECT name FROM employee); 
catch(PDOException $e) { 
    echo "Boom!!!!."
    file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND); 

Hay un error intencional en la instrucción de selección, lo que provocará una excepción. La excepción envía los detalles del error a un archivo de registro, y muestra un mensaje amistoso (o no muy claro) para el usuario.


Porque debería usar PHP’s PDO Para acceder a Bases de Datos? Parte 2

Insertar y actualización
Inserción de nuevos datos o actualizar los datos existentes es una de las operaciones de base de datos más comunes. Uso de DOP, esto es normalmente un proceso de dos pasos. Todo lo descrito en esta sección se aplica por igual tanto INSERT como para UPDATE.

Aquí un ejemplo del tipo más básico de inserción:
?
1
2
3
4
5
# STH means "Statement Handle" 
$STH = $DBH->prepare("INSERT INTO person ( first_name ) values ( 'Cathy' )"); 
$STH->execute(); 

También se puede realizar la misma operación utilizando el método exec(). En la mayoría de los casos, usted va a utilizar el método más largo para lograr tomar ventaja de declaraciones preparadas. Incluso si sólo va a utilizarla una vez, ya que las declaraciones preparadas le ayudarán a protegerse de los ataques de inyección SQL.

Sentencias preparadas
El uso de declaraciones preparadas le ayudará a protegerse de la inyección de SQL.


Una declaración preparada es una instrucción SQL precompilada que se pueden ejecutar varias veces mediante el envío sólo de datos al servidor. Tiene la ventaja adicional de establecer de forma automática los datos utilizados en los marcadores de posición asegurándonos así de un ataque de inyección SQL.
Utilice una declaración preparada mediante la inclusión de marcadores de posición (parámetros) en su instrucción SQL. Veamos 3 ejemplos: uno sin marcadores de posición, uno con marcadores de posición sin nombre, y uno con marcadores de posición con nombre.

?
1
2
3
4
5
6
7
8
9
10
// sin marcadores de posición
$STH = $DBH->("INSERT INTO person (name, addr, city) values ($name, $addr, $city)"); 
   
# usando marcadores de posición  sin nombre
$STH = $DBH->("INSERT INTO person (name, addr, city) values (?, ?, ?) ");
  
# usando marcadores de posición con nombre
$STH = $DBH->("INSERT INTO person (name, addr, city) value (:name, :addr, :city)");


Es recomendable evitar el primer método, que se utiliza aquí para la comparación. La opción de usar marcadores con nombre o sin nombre afectará la forma de configurar los datos en las instrucciones SQL.

Marcadores de posición sin nombre

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$STH->bindParam(1, $name); 
$STH->bindParam(2, $addr); 
$STH->bindParam(3, $city);  
 
$name = "Daniel" 
$addr = "1 Wicked Way"
$city = "Arlington Heights"
$STH->execute(); 
   
$name = "Steve" 
$addr = "5 Circle Drive"
$city = "Schaumburg"
$STH->execute();



Contamos con dos pasos para ejecutar nuestras sentencias SQL. En primer lugar, asignamos variables diferentes a los marcadores de posición (líneas 2-4). Luego, asignamos valores a los marcadores de posición y por ultimo ejecutamos nuestra sentencia SQL. Para ejecutar otra sentencia SQL solo será necesario cambiar los valores de las variables y ejecutar nuevamente la sentencia SQL.

¿Esto parece un poco difícil de manejar para las sentencias con una gran cantidad de parámetros? Eso es cierto. Sin embargo, si los datos se almacenan en una matriz, hay una opción más corta:

?
1
2
3
4
5
6
$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff'); 
   
$STH = $DBH->("INSERT INTO person (name, addr, city) values (?, ?, ?); 
$STH->execute($data);



Waao, Que fácil!
Los datos de la matriz se aplican a los marcadores de posición en orden secuencial. $data[0] será asignado al primer marcador de posición, $data[1],en el segundo, etc Sin embargo, si los índices de matriz no están en orden, esto no funcionará muy bien que digamos, y se tendrá que volver a indexar la matriz.

Marcadores de posición con nombre
Probablemente se podría adivinar la sintaxis, pero aquí dejo un ejemplo:

?
1
2
3
$STH->bindParam(':name', $name);


Aquí también se puede utilizar una matriz (array), pero en este caso trabaja con las matrices asociativas. Ejemplo:

?
1
2
3
4
5
6
7
$data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' ); 
   
# the shortcut! 
$STH = $DBH->("INSERT INTO person (name, addr, city) value (:name, :addr, :city)"); 
$STH->execute($data); 


No es necesario que las claves de la matriz comiencen con dos puntos, pero todo lo demás es necesario para lograr que coincidan los valores en los marcadores de posición con nombre. Si usted tiene una matriz de matrices se puede iterar sobre cada una de ellas, y simplemente ejecute su sentencia SQL con cada conjunto de datos.

Otra característica interesante de los marcadores de posición con nombre es la posibilidad de insertar objetos directamente en la base de datos, suponiendo que las propiedades del objeto coinciden con los campos con nombre. Veamos un ejemplo con un objeto y cómo añadirlo:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class person { 
    public $name
    public $addr
    public $city
   
    function __construct($n,$a,$c) { 
        $this->name = $n
        $this->addr = $a
        $this->city = $c
    
    # ... 
   
$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); 



Se convierte el objeto en una matriz y se ejecuta la sentencia SQL, las propiedades son tratadas como claves de matriz.

Seleccionando datos

Los datos se obtienen a través del metodo -> fetch (), el cual es un método de nuestro identificador de instrucción. Antes de llamar a fecth(), lo mejor es decirle PDO cómo quieres obtener los datos. Para lo cual se cuenta con las siguientes opciones:
PDO:: FETCH_ASSOC: devuelve una matriz indexada por nombre de columna
PDO:: FETCH_BOTH (por defecto): devuelve una matriz indexada por nombre y número de columna
PDO:: FETCH_BOUND: Asigna los valores de las columnas a las variables definidas con el metodo ->bindColumn()
PDO:: FETCH_CLASS: Asigna los valores de las columnas a las propiedades de la clase. Se crearan las propiedades si no existen
PDO:: FETCH_INTO: Actualiza una instancia existente de la clase especificada.
PDO:: FETCH_LAZY : Combina PDO:: FETCH_BOTH/DOP:: FETCH_OBJ, creando los objetos y las variables para su uso.
PDO:: FETCH_NUM: devuelve una matriz indexada por número de columna.
PDO:: FETCH_OBJ: devuelve un objeto anónimo con nombres de propiedades que corresponden a los nombres de columna.

En realidad, hay tres que cubren la mayoría de las situaciones: FETCH_ASSOC, FETCH_CLASS y FETCH_OBJ. La sintaxis que se utiliza con el fin de establecer el método fecth() es la siguiente:

?
1
2
3
$STH->setFetchMode(PDO::FETCH_ASSOC);


FETCH_ASSOC

Este crea una matriz asociativa, indexada por nombre de columna. Esto debería ser muy familiar para cualquiera que haya usado las extensiones mysql/mysqli. Veamos un ejemplo de selección de datos con este método:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
# creamos nuestra sentencia SQL
$STH = $DBH->query('SELECT name, addr, city from person); 
   
# configuramos el modo deseado
$STH->setFetchMode(PDO::FETCH_ASSOC); 
   
while($row = $STH->fetch()) { 
    echo $row['name'] . "\n"
    echo $row['addr'] . "\n"
    echo $row['city'] . "\n"


El bucle while se ejecuta hasta terminar de escribir en pantalla el resultado obtenido.

FETCH_OBJ

Este crea un objeto para cada fila de datos captados. Ejemplo:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# creamos nuestra sentencia SQL
$STH = $DBH->query('SELECT name, addr, city from person); 
   
# configuramos el modo deseado
$STH->setFetchMode(PDO::FETCH_OBJ); 
   
# mostramos el resultado
while($row = $STH->fetch()) { 
    echo $row->name . "\n"
    echo $row->addr . "\n"
    echo $row->city . "\n"
}


FETCH_CLASS
Las propiedades del objeto se establecen antes que el constructor sea llamado. Esto es importante.


Este método le permite recuperar los datos directamente en una clase especificada. Cuando se utiliza FETCH_CLASS, las propiedades de su objeto se establecen antes de llamar al constructor. Las propiedades que no existan como según las columnas obtenidas se crearan automáticamente.
Esto significa que si sus datos necesitan cualquier transformación después de salir de la base de datos, se pueden hacer automáticamente por su objeto, ya que cada objeto es creado.
Ejemplo, imagine una situación en la que la dirección tiene que ser parcialmente protegida por cada registro. Podemos hacer esto operando con la propiedad en el constructor. veamos:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
class secret_person { 
    public $name
    public $addr
    public $city
    public $other_data
   
    function __construct($other = '') { 
        $this->address = preg_replace('/[a-z]/', 'x', $this->address); 
        $this->other_data = $other
    


Como los datos se traen en esta clase, la dirección tiene caracteres entre a-z en minúscula y la sustituiremos por la letra x. Ahora, al momento de usar la clase todas las transformaciones curren de forma transparente:

?
1
2
3
4
5
6
7
8
$STH = $DBH->query('SELECT name, addr, city from person); 
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person'); 
   
while($obj = $STH->fetch()) { 
    echo $obj->addr; 
}


Si la dirección es “5 Bronds”, se obtendrá “5 Bxxxxx”. Por supuesto, puede haber situaciones en las que desea que el constructor se llame antes de asignar los datos. PDO ofrece una solución ante esto también.

?
1
2
3
$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'secret_person');  


Ahora, cuando se repita el ejemplo anterior con este modo establecido (PDO:: FETCH_PROPS_LATE) La dirección no se oculta, ya que el constructor se llama y las propiedades ya fueron asignadas.
Por último, si usted necesita pasar argumentos al constructor durante la obtención de datos en objetos con PDO, use el siguiente modo:

?
1
2
3
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person', array('stuff')); 


Si usted necesita para pasar datos de forma dinámica al constructor para cada objeto, puede establecer el modo al momento de ejecutar fecth():

?
1
2
3
4
5
6
$i = 0; 
while($rowObj $STH->fetch(PDO::FETCH_CLASS, 'secret_person', array($i))) { 
    $i++ 
}



Conclusión
Espero que estos dos artículos ayuden a muchos programadores a cambiarse de las extensiones mysql y mysqli.

PHP con PDO vs SQLSRV - comparison PDO and sql srv

 Para mí, la mejor manera de llegar a conocer un nuevo API es escribir algo de código. Así que, como un ejercicio de aprendizaje, convertí la aplicación de ejemplo que se incluye en la documentación del uso de la API sqlsrv procesal para usar el API orientada a objetos PDO (Los archivos convertidos se adjuntan a este mensaje. Usé la base de datos de ejemplo AdventureWorks2008, que puede descargar aquí .). Tal vez un mejor ejercicio sería reescribir toda la aplicación de ejemplo en un estilo orientado a objetos, pero quería permanecer centrado en cómo los cambios en el código de acceso de datos, así que voy a guardar el ejercicio más riguroso para más adelante.
Si usted ha escrito mucho código PDO contra otras bases de datos, la aplicación de ejemplo convertida en sí no puede ser tan interesante para usted. Sin embargo, mis observaciones de cómo comparar la API sqlsrv y la API de PDO podría ser interesante, así que voy a empezar por ahí. Tengo que decir que me quedé un poco decepcionado con las limitaciones de la interfaz PDO. Esto no es una crítica de este controlador PDO en particular, es sólo que la API sqlsrv ofrece algunas gran funcionalidad que no pueden ser fácilmente expuestos en la interfaz PDO. Esto es algo de lo que me di cuenta:
  • La funcionalidad streaming que está disponible en el API sqlsrv de procedimiento para la recuperación de datos no se puede aprovechar en la interfaz PDO. El API sqlsrv aprovecha PHP arroyos para que pueda enviar y recuperar datos  . Sin embargo, con el controlador PDO, no se puede recuperar datos como una secuencia. Dependiendo de la aplicación, esto puede tener un impacto significativo sobre el uso de memoria.
  • La funcionalidad ofrecida en sqlsrv_has_rows (determina si un conjunto de resultados tiene filas) y sqlsrv_num_rows (determina el número de filas de un conjunto de resultados) no está disponible a través de PDO. Hay soluciones, pero implican trayendo un conjunto de resultados (en parte o en su totalidad) en la memoria. Una vez más, esto puede no ser un problema dependiendo de la aplicación, pero podría ser.
  • La capacidad de moverse a través y recuperar un único campo en un conjunto de resultados de fila sólo se puede hacer con PDOStatement :: fetchObject al usar PDO. Con la API sqlsrv, la combinación de sqlsrv_fetch / sqlsrv_get_field no sólo le permite recuperar un solo campo, que le permite especificar el tipo de datos PHP y codificación cuando se recuperan los datos. Esto no está disponible a través de PDO. El PDOStatement :: fetchColumn método se acerca, pero no permite que usted se mueva cuando los campos de la fila actual.
  • La interfaz PDO no proporciona ninguna manera para el manejo de las advertencias que se provocan por la base de datos. Por defecto, el conductor sqlsrv trata la mayoría de las advertencias como errores para que puedan ser manejados . (Puede desactivar este comportamiento con el sqlsrv_configure función.) El controlador PDO sólo permite que los errores se manejan.
En el lado positivo, me gustó mucho el PDO :: lastInsertId método y la capacidad para lidiar con los errores de manejo de excepciones. En el código de ejemplo siguiente se puede ver cómo estas características hacen de código mucho más legible.
Tengo curiosidad por saber qué tan relevante o importante es esta información. ¿Son importantes para usted estas características sqlsrv (que no se aparecieron en la interfaz PDO)? ¿Qué tan importantes son? ¿Por qué? 
El resto de este post es para la gente que no se ha escrito mucho código PDO. Voy a mirar a una parte del código de la aplicación de ejemplo en la documentación del controlador sqlsrv y lo comparo con el mismo código escrito con el controlador PDO.

Conexión a una base de datos

No hay sorpresas aquí la conexión con la autenticación de Windows (y no hay sorpresas cuando se conecta con la autenticación de SQL Server). Tengo que hacer una llamada extra con DOP para establecer el modo de control de errores, pero me da la ventaja de trabajar con excepciones ahora.
sqlsrv
$ ServerName = "(local) \ sqlexpress"; 
$ ConnectionOptions = array ("Base de datos" => "AdventureWorks2008");
$ Conn = sqlsrv_connect ($ serverName, $ ConnectionOptions); 
if ($ conn === false) 
{Die (FormatErrors (sqlsrv_errors ()));}
PDO
$ ServerName = "(local) \ sqlexpress"; 

intentar 
{ 
$ Conn = new PDO ("sqlsrv: Servidor = $ serverName; Database = AdventureWorks2008", "", ""); 
$ Conn-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION); 
} 
catch (Exception $ e) 
{ 
die (print_r ($ e-> getMessage ())); 
}

Recuperando datos

Dos cosas a destacar aquí:
  1. Con PDO, saqué todo el conjunto de resultados en la memoria para que pueda contar con los resultados.Con la API sqlsrv, puedo usar un cursor desplazable para contar los resultados en el servidor.
  2. La función FormatErrors envuelve una llamada a sqlsrv_errors en el ejemplo sqlsrv. En el código de PDO, tengo la ventaja de trabajar con excepciones.
sqlsrv
$ queryTerms = array ($ _POST ['query']); 
$ Tsql = "SELECT ProductID, Name, color, tamaño, ListPrice 
DE Production.Product 
Donde nombre LIKE '%' +? + '%' Y ListPrice> 0.0 "; 
$ CursorType = array ("desplazable" => SQLSRV_CURSOR_KEYSET); 
$ GetProducts = sqlsrv_query ($ conn, $ tsql, $ queryTerms, $ CursorType); 
if ($ GetProducts === false) 
{Die (FormatErrors (sqlsrv_errors ()));}
if (($ sqlsrv_has_rows GetProducts)) 
{ 
$ RowCount = sqlsrv_num_rows ($ GetProducts); 
BeginProductsTable ($ rowCount); 
while ($ row = sqlsrv_fetch_array ($ GetProducts, SQLSRV_FETCH_ASSOC))
{ 
PopulateProductsTable ($ row); 
} 
EndProductsTable (); 
} 
más 
{ 
DisplayNoProdutsMsg (); 
}
PDO
intentar 
{ 
$ queryTerms = array ($ _POST ['query']); 
$ Tsql = "SELECT ProductID, Name, color, tamaño, ListPrice 
DE Production.Product 
Donde nombre LIKE '%' +? + '%' Y ListPrice> 0.0 "; 
$ GetProducts = $ conn-> prepare ($ tsql); 
$ GetProducts-> execute ($ queryTerms); 
$ products = $ GetProducts-> fetchAll (PDO :: FETCH_ASSOC); 
$ ProductCount = count (productos $); 
if ($ ProductCount> 0) 
{ 
BeginProductsTable ($ ProductCount); 
foreach ($ productos como $ row) 
{ 
PopulateProductsTable ($ row); 
} 
EndProductsTable (); 
} 
más 
{ 
DisplayNoProdutsMsg (); 
} 
} 
catch (Exception $ e)
{ 
die (print_r ($ e-> getMessage ())); 
}

Insertar datos

Realmente, no hay sorpresas aquí, pero tenga en cuenta que la API sqlsrv permite que los datos se transmiten a la base de datos, mientras que la API de PDO no.
sqlsrv
. $ comentarios = "data :/ / text / plain", $ _POST ['comentarios']; 
$ = corriente fopen ($ comentarios, "r"); 
$ Tsql = "INSERT INTO Production.ProductReview (ProductID, 
ReviewerName, 
ReviewDate, 
EmailAddress, 
Clasificación, 
Comentarios) 
VALORES "(,,,,,??????);

$ params = array (& $ _POST ['productid'], 
& $ _POST ["Nombre"], 
date ("Ymd"), 
& $ _POST ['Email'], 
& $ _POST ['Rating'], 
& $ Stream);
$ InsertReview = sqlsrv_prepare ($ conn, $ tsql, $ params); 
if ($ insertReview === false) 
{Die (FormatErrors (sqlsrv_errors ()));}

if (sqlsrv_execute ($ insertReview) === false) 
{Die (FormatErrors (sqlsrv_errors ()));}
PDO
intentar 
{
$ Tsql = "INSERT INTO Production.ProductReview (ProductID, 
ReviewerName, 
ReviewDate, 
EmailAddress, 
Clasificación, 
Comentarios) 
VALORES "(,,,,,??????);

$ params = array (& $ _POST ['productid'], 
& $ _POST ["Nombre"], 
date ("Ymd"), 
& $ _POST ['Email'], 
& $ _POST ['Rating'], 
$ _POST ['Comentarios']); 
$ InsertReview = $ conn-> prepare ($ tsql); 
$ InsertReview-> execute ($ params); 
} 
catch (Exception $ e) 
{ 
die (print_r ($ e-> getMessage ())); 
}

Recuperar datos binarios

Una vez más, dos cosas a destacar aquí:
  1. Con la API sqlsrv, puedo usar la combinación de sqlsrv_fetch / sqlsrv_get_field para recuperar un solo campo y especificar que quiero recuperarla como una corriente PHP.
  2. La capacidad de trabajar con excepciones en el código de PDO para hacer más legible el código.
sqlsrv
$ Tsql = "SELECT LargePhoto 
DE Production.ProductPhoto AS p 
ÚNETE Production.ProductProductPhoto AS q 
EN p.ProductPhotoID = q.ProductPhotoID 
? DONDE ProductID = ";
$ params = array ($ _GET ['productId']);
$ Stmt = sqlsrv_query ($ conn, $ tsql, $ params); 
if ($ stmt === false) 
{ 
echo "Error en la ejecución de la sentencia </ br>."; 
morir (print_r (sqlsrv_errors (), true)); 
}
if (sqlsrv_fetch ($ stmt)) 
{ 

$ Image = sqlsrv_get_field ($ stmt, 
0, 
SQLSRV_PHPTYPE_STREAM (SQLSRV_ENC_BINARY)); 
fpassthru ($ imagen); 
} 
más 
{ 
echo "Error en la recuperación de datos </ br>."; 
morir (print_r (sqlsrv_errors (), true)); 
}
PDO
intentar 
{ 
$ Tsql = "SELECT LargePhoto 
DE Production.ProductPhoto AS p 
ÚNETE Production.ProductProductPhoto AS q 
EN p.ProductPhotoID = q.ProductPhotoID 
? DONDE ProductID = ";

$ Stmt = $ conn-> prepare ($ tsql); 
$ Stmt-> execute (array ($ _GET ['productId'])); 
$ BindColumn stmt-> (1, 
$ Imagen, 
PDO :: PARAM_LOB, 
0, 
PDO :: SQLSRV_ENCODING_BINARY); 
$ Stmt-> fetch (PDO :: FETCH_BOUND); 
echo $ imagen; 
} 
catch (Exception $ e) 
{ 
die (print_r ($ e-> getMessage ())); 
}

Inserción de datos binarios

La capacidad de trabajar con las excepciones y la PDO :: lastInsertId método de hacer el código PDO aquí mucho más legible. Con la API sqlsrv, no hay ninguna función integrada para obtener el último ID después de una inserción, por lo que necesita para ejecutar una consulta por lotes y trabajar a través del segundo conjunto de resultados.
sqlsrv
$ Tsql = "INSERT INTO Production.ProductPhoto (LargePhoto) 
VALORES (?); SELECT SCOPE_IDENTITY () AS Número de foto "; 
$ FileStream = fopen ($ _FILES ['file'] ['tmp_name'], "r"); 

$ UploadPic = sqlsrv_prepare ($ conn, $ tsql, array ( 
array (& $ fileStream, 
SQLSRV_PARAM_IN, 
SQLSRV_PHPTYPE_STREAM (SQLSRV_ENC_BINARY), 
SQLSRV_SQLTYPE_VARBINARY ('max')))); 

if ($ uploadPic === false) 
{Die (FormatErrors (sqlsrv_errors ()));} 

if (sqlsrv_execute ($ uploadPic) === false) 
{Die (FormatErrors (sqlsrv_errors ()));} 

$ Next_result = sqlsrv_next_result ($ uploadPic); 
if ($ next_result === false) 
{Die (FormatErrors (sqlsrv_errors ()));} 
if (sqlsrv_fetch ($ uploadPic) === false) 
{Die (FormatErrors (sqlsrv_errors ()));}
$ Número de foto = sqlsrv_get_field ($ uploadPic, 0);
$ Tsql = "Production.ProductProductPhoto ACTUALIZACIÓN 
SET ProductPhotoID =? 
? DONDE ProductID = ";
if (sqlsrv_query ($ conn, $ tsql, array ($ Número de foto, $ _POST ['productid'])) === false) 
{Die (FormatErrors (sqlsrv_errors ()));}
PDO
intentar 
{ 

$ Tsql = "INSERT INTO Production.ProductPhoto (LargePhoto) 
VALORES "(?); 
$ 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 ();
$ Número de foto = $ conn-> lastInsertId (); 
$ Tsql = "Production.ProductProductPhoto ACTUALIZACIÓN 
SET ProductPhotoID =? 
? DONDE ProductID = "; 
$ AssociateIds = $ conn-> prepare ($ tsql); 
$ associateIds-> execute (array ($ Número de foto, $ _POST ['productid'])); 
} 
catch (Exception $ e) 
{ 
die (print_r ($ e-> getMessage ())); 
}
Una vez más, los dos archivos que componen la aplicación de ejemplo se encuentran en el archivo zip adjunto a este mensaje.
Eso es todo por este post. Por favor, hágamelo saber lo que piensa de esta versión previa del controlador de SQL Server para PHP 2.0. Me aseguraré de que el equipo de desarrollo escucha sus comentarios.

array ordenado y sin valores repetido (ordered array without repeated values ) JAVA PHP JS etc

Un tip de pocas lineas y funcional multilenguaje

PHP :

para entrar en contexto, tengo datos que recorro con un for, y quiero guardar las fechas en donde juegan los equipos, pero estan en desorden y hay fechas repetidas, lo que voy a hacer, es guardar la data en una variable de texto separada por "|" (opcional) y a la vez en una variable de tipo array. a la variable de texto le pregunto "strpos" y busque si existe la fecha, de lo contrario agrega al array.

/*proceso para no repetir fechas*/

datos = "12 enero, 16 enero, 12 enero ,25 enero, 9 enero, 25 enero, 1 enero";

$arrfechas = array();
   $dia =  explode(",",$datos );
        $pos = strpos($fechas, $dia);
          if ($pos === false) {
              $arrfechas[] = "$dia";
              $fechas .= "$dia|";//
          } 
asort($arrfechas);

CommentFB