miércoles, 20 de julio de 2011

Conectando Oracle con PHP (PDO)

 En esta ocasion veremos cómo hacer una conexión mediante PHP y Oracle, para esto nos basaremos en el objeto PDO mencionado anteriormente, hasta aquí se asume que ya está configurado el php.ini para usar el respectivo driver (Si no es así, puedes ver el artículo sobre la configuración del PDO aquí ).

Empecemos...

Voy a explicarles, línea por línea, posteriormente, mostraré el código completo.

La Conexión...
1. Para la conexión a Oracle, necesitaremos 3 datos indispensables:
  1. El listener o la cadena de host a conectarnos.
  2. La Contraseña.
  3. El Usuario
-Así pues,  para facilitar la visualización del código, declararemos 3 variables; la primera de ellas es la más larga, esta variable almacenará un TNSNAME, esto con el fin de que nuestra conexión sea exitosa; sin embargo, existe otra forma más corta, por el momento, en este ejemplo usaré la más robusta y eficaz de todas.

$tns="(DESCRIPTION=(ADDRESS_List=
                                   (ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))
                      )
                      (CONNECT_DATA=
                              (SERVICE_NAME=DB1)
                      )
         )" ;
*En este punto, los tres campos que podrías modificar son:
  • HOST: Este se modifica en caso de que la Base de Datos se encuentre en otro host, diferente servidor, de lo contrario puede quedarse así tal cual se muestra (O escribir "localhost"). 
  • PORT: El puerto por defecto es el 1521, a excepción de que lo hayas modificado. 
  • SERVICE_NAME: Este pertenece a la base de datos, en muchas bases, se maneja el nombre de "orcl" por ejemplo.
-Posteriormente declararemos nuestras variables de usuario y contraseña.

$user="pruebas" ; //El nombre de usuario
$pass="daniboy"; //La contraseña
2. Ahora, nos centraremos en la creación del objeto que nos permitirá conectar a la Base de Datos.  Este objeto lo almacenaremos en una variable:
                $conexion =new PDO("oci:dbname".$tns,$user,$pass);

La cadena "oci:dbname:" es usada por el driver para generar la conexión, además de los parámetros ya mencionados.
A pesar de que la línea anterior nos permite conectar a la Base de Datos, puede ser que esta no exista, para tal caso, colocar la línea dentro de un bloque try/catch nos permitirá saber si la conexión fue exitosa.
try
{
      $conexion =new PDO("oci:dbname".$tns,$user,$pass);
      echo "Accediendo...";
} 
catch ( PDOException $e )
echo "Error: ".$e->getMessage( );  }
3. Capturar una excepción de esta forma, sólo nos limita a que aparezca el mensaje de error cuando no se pueda conectar a la base de datos, pero ¿Qué sucede si una transacción no se termina correctamente debido a algúna anomalía de integridad o alguna otra causa? Simplemente la excepción no nos mostraría nada (Esto se debe a los valores por defecto con que el objeto PDO se crea). Para poder activar la excepción cuando se produzca un error, basta con  colocar el atributo PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION en el método setAttribute del objeto PDO:
 $conexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
 Ahora nuestro bloque podrá capturar excepciones tanto a nivel de conexión, como a nivel de transacciones.

Las transacciones...
1. Realizar una operación como Insertar, Borrar, Modificar es una tarea fácil, para esto, el objeto cuenta con el método exec, el cual admite un parámetro que será nuestra  sentencia SQL.
  Para demostrar esto, insertaremos un registro en una tabla llamada prueba2.

          $inser="insert into prueba2 values('x',1,'z')"; //Cadena con la instrucción insert
          $conex->exec( $st );
//Ejecutamos la transacción
          
echo "La transacción fue realizada exitosamente";
            
Si la operación ha sido realizada exitosamente, se mostrará el mensaje "La transacción fue realizada exitosamente" de lo contrario, saltará al catch.

2. Una vez que hayamos insertado nuestro registro, nos dispondremos a ver si realmente se ha guardado además de ver las otras filas que existen en la tabla prueba2.

    Para esto, usaremos tres funciones: prepare, executefetchAll. La primer función(prepare) almacena la consulta que vayamos a ejecutar; la segunda función (execute) precisamente se encarga de eso, de ejecutar la sentencia; por último, la función fetchAll nos devolverá un arreglo, en el cual cada registro obtenido se almacena también como un arreglo, es decir se produce un arreglo que contiene 'x' arreglos de filas.

    Aunque toda esta definición parece ser muy difícil de llevarla a la práctica, en realidad no demuestra ser gran ciencia, para mostrar los datos, usaremos un ciclo foreach para recorrer todo el arreglo, también usaremos la herramient list ( ) para obtener los valores por cada fila (En este caso, la tabla sólo contiene tres campos).

$st=$conex->prepare("Select * from prueba2"); //La función devuelve un statement object

            $st->execute( );

            $resultado=$st->fetchAll( ); //El resultado lo guardamos en una variable diferente.

            foreach($resultado as $mat//Por cada arreglo guardalo en $mat
            {
              //Declaro mi list con tres variables, cada una tendrá el valor de cada columna por registro.
               list($c1,$c2,$c3)=$mat;    
                //Mandamos a imprimir en pantalla
                  echo "$c1---$c2--- $c3";
            }
Con esto el código quedaría de la siguiente manera:
< ?php
 
$user="pruebas" ; 
$pass="daniboy"; 
$tns="(DESCRIPTION=(ADDRESS_List=
                                   (ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))
                      )
                      (CONNECT_DATA=
                              (SERVICE_NAME=DB1)
                      )
         )" ;
try
{
      $conexion =new PDO("oci:dbname".$tns,$user,$pass);
      $conexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
       echo "Accediendo..."
      $inser="insert into prueba2 values('x',1,'z')"; //Cadena con la instrucción insert
     $conex->exec( $st ); //Ejecutamos la transacción
      echo "La transacción fue realizada exitosamente";          
$st=$conex->prepare("Select * from prueba2"); //La función devuelve un statement object
            $st->execute( )
            $resultado=$st->fetchAll( ); //El resultado lo guardamos en una variable diferente.
            foreach($resultado as $mat//Por cada arreglo guardalo en $mat
            {
       //Declaro mi list con tres variables, cada una tendrá el valor de cada columna por registro.
               list($c1,$c2,$c3)=$mat;  
                    echo "$c1---$c2--- $c3"; //Mandamos a imprimir en pantalla
            }//Fin Foreach
  }
catch ( PDOException $e )
echo "Error: ".$e->getMessage( );  }
? >