Acceder a las bases de datos
Introducción
1. Información general
La utilización de una base de datos SQL es a menudo esencial para implementar un sitio web dinámico. De hecho, se trata de una forma estándar de almacenamiento de datos útiles para el sitio web:
-
Lista de usuarios con sus preferencias.
-
Catálogo de productos.
-
Seguimiento de las transacciones realizadas.
PHP ofrece soporte integrado para muchas bases de datos, como MySQL, Oracle, Microsoft SQL Server, Informix, Sybase. Asimismo, PHP es compatible con ODBC (Open DataBase Connectivity) y, por tanto, puede acceder a cualquier base de datos compatible con ODBC.
Además, PHP viene con SQLite, una biblioteca que implementa un motor de base de datos SQL. SQLite se puede utilizar para almacenar datos en una base de datos SQL sin tener que realizar la parte del servidor de la base de datos (como es el caso de MySQL, Oracle, etc.).
En este capítulo estudiaremos MySQL y Oracle.
Normalmente, cuando se utiliza una base de datos, el script PHP necesita llevar a cabo una o varias de las siguientes tareas:
-
Conectarse y desconectarse.
-
Leer los datos (una o varias líneas).
-
Actualizar los datos (adición, modificación o supresión).
Estas diferentes tareas se tratan en este capítulo.
Se requieren conocimientos mínimos de SQL para abordar este capítulo.
Para los ejemplos que aquí se presentan, suponemos la existencia de una base de datos que contiene...
Utilizar MySQL
1. Preámbulo
La extensión MySQL: MySQLi (prefijo mysqli_) permite acceder a una base de datos.
Esta extensión se puede usar ya sea como procedimiento o bien en forma de objeto.
En su forma orientada a objeto, la extensión MySQLi ofrece tres clases principales:
mysqli |
Conexión entre PHP y MySQL. |
mysqli_stmt |
Consulta preparada. |
mysqli_result |
Resultado de la ejecución de una consulta. |
Estas diferentes clases ofrecen métodos que permiten efectuar las distintas acciones (ejecución de una consulta, recuperación del resultado, etc.).
En su forma de procedimiento, la extensión MySQLi ofrece funciones que permiten efectuar las mismas acciones. De manera transparente, varias de estas funciones devuelven o aceptan como parámetros objetos de tipo mysqli o mysqli_result.
En este libro, presentamos únicamente la forma de procedimiento de la extensión MySQLi.
La extensión MySQLi permite usar las consultas preparadas.
Una consulta preparada es una consulta que contiene parámetros representados por un signo de interrogación (?).
Ejemplos
SELECT * FROM artículo WHERE id = ?
INSERT INTO artículo(texto,precio) VALUES(?,?)
Por el contrario, una consulta no preparada es una consulta en la que se especifican todos los valores.
Ejemplos
SELECT * FROM artículo WHERE id = 1
INSERT INTO artículo(texto,precio) VALUES('Plátanos',10.5)
Más adelante en este capítulo, veremos cómo ejecutar consultas de lectura y de actualización, primero con consultas no preparadas (véase la sección Utilizar consultas no preparadas) y luego con consultas preparadas (véase la sección Utilizar consultas preparadas).
2. Conexión y desconexión
a. Conexión
La función mysqli_connect permite establecer una conexión con una base de datos MySQL.
Sintaxis
objeto mysqli_connect([cadena host [, cadena usuario
[, cadena contraseña] [, cadena nombre_base [,entero puerto[,
cadena socket]]]]]])
Donde
host |
Nombre (o dirección IP) del host al que debe conectarse (máquina local predefinida). |
usuario |
Nombre del usuario que se utiliza para establecer la conexión. Valor predeterminado: el propietario del proceso del servidor web. |
contraseña |
Contraseña que se utilizará... |
Utilizar Oracle
1. Preámbulo
La extensión «Oracle OCI8», al contrario de lo que su nombre pueda hacernos pensar, se puede utilizar para acceder a cualquier versión de Oracle. Esta extensión es muy completa y muy potente; permite utilizar los tipos LOB y ROWID y establecer vínculos entre las variables PHP y las variables en la consulta SQL (concepto de «bind variable»).
2. Entorno NLS
El entorno NLS (National Language Support), utilizado en la ejecución de las consultas, se define por medio de las variables de entorno habituales colocadas en el servidor que ejecuta PHP:
-
NLS_LANG
-
NLS_DATE_FORMAT...
Si estas variables de entorno no se han establecido, se toma el valor predeterminado de Oracle Server.
Esto puede dar lugar a diferencias de funcionamiento de un mismo programa entre dos entornos. Por ejemplo, si recupera en una consulta una columna de tipo DATE, se realiza una conversión en cadena automáticamente (ya que PHP no admite el tipo DATE como tal) según el parámetro NLS_DATE_FORMAT activo; dependiendo de la configuración y el entorno, la cadena recuperada puede tener diferentes formatos (DD/MM/AAAA, DD-MON-YY...).
Problemas similares ocurren con los datos numéricos que también se convierten en una cadena con un separador decimal y un separador de grupo que puede variar en función del entorno.
Si no se controla el entorno, es posible actuar al nivel de código PHP para obtener un código portátil de un entorno a otro:
-
bien efectuando sistemáticamente conversiones explícitas en las instrucciones SQL (TO_CHAR(SYSDATE,’DD/MM/YYYY’), TO_DATE(’31/08/2001’,’DD/MM/YYYY’), TO_CHAR(precio,’9999.99’),TO_NUMBER (’123.45’, ’999.99’) por ejemplo);
-
bien ejecutando, después de cada apertura de sesión, consultas ALTER SESSION (ALTER SESSION SET NLS_DATE_FORMAT = ’DD/MM/YYYY’ o ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ’, ’ por ejemplo).
Volveremos a este tema en la sección Ilustración de problemas relacionados con el entorno NLS.
3. Conexión y desconexión
a. Conexión
La función oci_connect permite abrir una conexión con una base de datos de Oracle.
Sintaxis simplificada
recurso oci_connect(cadena usuario, cadena contraseña, ...
PHP Data Objects (PDO)
PHP Data Objects (PDO) es una extensión, que define una interfaz uniforme para acceder a las bases de datos en PHP. El acceso a una base de datos a través de PDO se efectúa por medio de un controlador que expone las características de la base de datos.
Cabe señalar que PDO no proporciona una capa de abstracción de la base de datos, sino una capa de abstracción del acceso a las bases de datos. Las consultas que escriba deben respetar la sintaxis de la base de datos que utiliza; PDO no reescribe consultas SQL y no emula las características que faltan (a excepción de las consultas con parámetros, si fuera necesario).
Muchas bases de datos disponen de un controlador PDO, como MySQL y Oracle.
PDO es una extensión orientada a objetos compuesta de tres clases:
-
PDO: conexión entre PHP y la base de datos,
-
PDOStatement: consulta preparada y, después de la ejecución, resultado asociado,
-
PDOException: excepción planteada por PDO.
En este capítulo, presentaremos esta extensión utilizando un sencillo ejemplo comentado:
<?php
// Definición de los parámetros de conexión.
// La sintaxis de la fuente (Data Source Name o DSN)
// es específica a cada controlador.
// El número del caso para probar se pasa en la URL con la
// variable 'test'.
// Recuperar el valor de la variable $test para...
Gestionar los apóstrofos en el texto de las consultas
En el caso del uso de consultas no preparadas, puede plantearse un problema si una cadena de caracteres literal presente en una consulta contiene un apóstrofo.
Ejemplo (inserción en la base de un dato que contiene un apóstrofo)
<?<?php
// Dato que supone un problema (puede introducirse sin querer
// en un formulario).
$texto = "Pomme d'api";
$precio = 10;
// Consulta.
$consulta = "INSERT INTO artículos(texto,precio)" .
"VALUES('$texto',$precio)";
echo "$consulta<br />";
// Ejecución con MySQL.
echo "<p><b>MySQL</b><br />";
mysqli_report(MYSQLI_REPORT_OFF); // Desactivar reporte de errores
$conexion = mysqli_connect();
$ok = mysqli_select_db($conexion, ‘diane');
$resultado = mysqli_query($conexion, $consulta);
echo mysqli_error($conexion),'<br />';
// MySQL no genera ninguna alerta
// Ejecución con Oracle.
echo "<p><b>Oracle</b><br />";
$conexion = oci_connect('demeter','demeter','diane');
if ($cursor = oci_parse($conexion,$consulta)) {
$resultado = oci_execute($cursor);
}
?> >
Resultado
INSERT INTO artículos(texto,precio) VALUES('Pomme d'api',10)
MySQL
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax
to use near 'api',10)' at line 1
Oracle
Warning: oci_parse(): ORA-01756: quoted
string not properly terminated in /app/scripts/index.php on line 19
En SQL, el delimitador de cadena de caracteres es el apóstrofo: si una consulta envía la cadena ’Pomme d’api’ a la base de datos, esta última interpretará ’Pomme d’ como una cadena y no sabrá qué hacer con el resto (api’).
Para resolver este problema, se debe indicar a la base de datos que los apóstrofos...
Ejemplos de integración en formularios
1. Resumen general
Para concluir este capítulo, presentamos algunos ejemplos de acceso a las bases de datos de formularios.
Se proponen cuatro ejemplos:
-
la construcción de una lista de selección en un formulario;
-
un formulario que muestra una lista;
-
un formulario que permite introducir datos en una lista;
-
un formulario de búsqueda y de introducción de datos de tipo «página».
Por motivos de concisión, en estos ejemplos, el control de la introducción de datos está prácticamente ausente, y el formato es muy simple.
Los ejemplos están diseñados para funcionar del mismo modo con MySQL y Oracle. Para ello, el acceso a las bases de datos se realiza utilizando varias funciones que se implementan en una biblioteca específica para cada producto. Para hacer funcionar un ejemplo en una base de datos particular, basta con incluir la biblioteca correspondiente.
Las funciones utilizadas para el acceso a las bases de datos son las siguientes:
conexión |
Conexión a la base de datos. |
seleccionar_artículos |
Selección de todos los artículos. |
leer_artículo_siguiente |
Lectura del artículo siguiente en el resultado de la consulta de selección de todos los artículos. |
seleccionar_un_artículo |
Selección de un artículo cuyo identificador se pasa como parámetro. |
guardar_artículo |
Guardar los cambios de un artículo. |
guardar_artículos |
Guardar las actualizaciones (creación, modificación, eliminación) de una lista de artículos (en asociación con el formulario de publicación de lista). |
Sintaxis
booleano conexión(&$conexion,&$error)
booleano seleccionar_artículos($conexion,&$consulta,&$error)
mixto leer_artículo_siguiente($conexion,$consulta,&$artículo,&$error)
booleano seleccionar_un_artículo($conexion,$identificador,&$artículo,&$error)
booleano guardar_artículo($conexion,$artículo,&$error)
mixto guardar_artículos($conexion,$líneas,&$error)
Donde:
$conexion |
Identificador de la conexión devuelto por la función conexión (parámetro pasado por referencia) y utilizado como entrada para el resto de las funciones (parámetro... |