Introducción
PHP 5 soporta muchos de los gestores de bases de datos relaciónales existentes
en el mercado. Las dos alternativas más comunes son ProstgreSQL y MySQL.
Aunque PostgreSQL es mucho mejor en cuanto a características y funciones
soportadas del SQL 92 estándar, MySQL se ha hecho más popular en el
ambiente de los servidores Web. Cuando los servidores Web ofrecen su servicio
como LAMP se refieren a Linux + Apache + MySQL + PHP.
Este capítulo cubre las operaciones más comunes que los desarrolladores
de PHP pueden hacer con MySQL, desde recuperar o modificar datos,
buscar textos o hacer una copia de seguridad de la base de datos.
Administración de usuarios
Una gran parte del uso de la seguridad y efectividad de MySQL tiene que
ver con comprender el sistema de privilegios. MySQL permite dar permisos
al detalle basándose en grupos, usuarios, conexiones y comandos a
utilizar. En teoría, se puede dar privilegios a ciertos usuarios para que sólo
puedan escribir en algunas columnas de varias tablas. Es una buena idea
dar a cada usuario los permisos mínimos necesarios para que pueda interactuar
con su base de datos. En realidad, en un mundo ideal, no debería
preocuparse por dar permisos a los usuarios o crear bases de datos. Si su
trabajo profesional se basa en el desarrollo de aplicaciones, su administrador
de bases de datos debería poner a punto el servidor de MySQL para
facilitar su trabajo. Si se está interesado en conocer los entresijos del servidor
de bases de datos, recomiendo al lector que lea la documentación o;/-
line de la Web www.mysql.com o consiga uno de los muchos libros que
tratan el tema.
En el Apéndice A puede ver cómo instalar MySQL y dar los permisos necesarios
para que pueda probar los ejemplos.
Conexión a MySQL
La conexión no puede ser más sencilla. Es un proceso de dos pasos:
• Se conecta con el servidor de MySQL.
• Se solicita la conexión a una base de datos específica.
Es importante recordar que MySQL es un servidor que puede estar alojado
en el mismo ordenador que PHP 5, o en otro diferente. Por eso, la conexión
se hace de forma distinta a SQLite.
Para conectar a MySQL es necesario enviar como parámetros la dirección
del servidor, el usuario y la contraseña.
<?php
$servidor = "localhost";
$usuario = "luis";
$pass = "secreto";
$base_datos = "Compras";
//Conexión al servidor de bases de datos
$descriptor = mysql_connect($servidor,$usuario, $pass) ;
//Se selecciona la base de datos
mysql_select_db($base_datos,$descriptor);
//Se cierra la conexión cuando terminemos
mysql__close ( $descriptor) ;
?>
La función mysql_connect () permite conectar a un servidor. En este
caso, hemos puesto como servidor a l o c a l h o s t porque estamos utilizando
nuestro ordenador local para hacer las pruebas.
Otra cuestión importante es que el servidor MySQL puede almacenar
varias bases de datos de un mismo usuario, por eso tenemos que utilizar
la f u n c i ó n m y s q l _ s e l e c t _ d b (), para seleccionar la que queremos utilizar.
Por último, tenemos la función m y s q l _ c l o s e () que se encarga de cerrar
una conexión con el servidor.
El ejemplo siguiente muestra cómo se puede crear una clase reutilizable
en todos los proyectos que sirva para conectarse a una base de datos:
<?php
class Servidor_Base_Datos
{
private $servidor;
private $usuario;
private $pass;
private $base_datos;
private $descriptor;
function construct($servidor,$usuario,$pass,$base_datos)
{
$this->servidor = $servidor;
$this->usuario = $usuario;
$this->pass = $pass;
$this->base_datos = $base_datos;
$this->conectar_base_datos();
}
prívate function conectar_base_datos()
{
$this->descriptor = mysql__connect($this->servidor,$this-
>usuario,$this->pass) ;
mysql_select_db($this->base_datos,$this->descriptor);
}
}
$servidor = " localhost";
$usuario = "luis";
$pass = "secreto";
$base_datos = "Usuario";
$usuario = new
Servidor_Base_Datos($servidor,$usuario,$pass,$base_datos);
?>
Nota:
No he añadido al objeto ningún tipo de control de errores, ya que
veremos ese tema con profundidad en el capítulo 17.
Seleccionar datos
Existen diferentes formas de recuperar datos desde MySQL, pero los más
usados son seguramente mysql_f e t c h _ q u e r y () y mysql_query () .
Si leyó el capítulo anterior sobre SQLite no tendrá ningún problema para
asimilar el funcionamiento de estas funciones.
Vamos a añadir dos métodos nuevos a la definición de la clase anterior
para que nos pueda servir en otras aplicaciones.
public function consulta($consulta)
{
$this->resultado = mysql_query($consulta,$this->descriptor) ;
}
public function extraer_registro ()
{
if ($fila = mysql_fetch_array($this->resultado,MYSQL_ASSOC)) •
return $fila;
} else {
return false;
}
}
El método c o n s u l t a () recibe una sentencia SQL que debe ejecutarse en
la base de datos apuntada por el descriptor $ t h í s- > d e s c r i p t o r .
El método e x t r ae r _ r eg i s t r o ( ) comprueba con la función
mysql_f e t c h _ a r r a y () si existen ficheros en el resultado de la consulta.
En caso afirmativo, devuelve un arraxj con los datos de ese registro.
En el capítulo anterior, vimos que un registro pasado comoarray permitía
acceder a las columnas mediante un índice numérico ($f i la [0] ) o mediante
el nombre de la columna (($f i l a [" i d _ u s u a r i o " ])).
La directiva MYSQL_ASSOc elimina la posibilidad de extraer los datos con
un Índice .numérico, mejorando la recuperación en Jos bucles del foreach.
El ejemplo siguiente muestra cómo utilizar los nuevos métodos:
<?php
//Primero se añade el fichero que contiene la clase
require_once("MySQL.php");
$servidor = "localhost";
$usuario = "luis";
$pass = "secreto";
$base_datos = "Compras";
$usuario = new
Servidor_Base_Datos($servidor,$usuario,$pass,$base_datos);
$usuario->consulta ("seslect * from Usuario");
while ($fila = $usuario->extraer_registro() ) {
foreach ($fila as $indice => $valor) {
echo "$indice: $valor<br>";
}
}
?>
El código anterior recupera la clase del fichero MySQL . php e inicializa las
variables necesarias para conectar con la base de datos.
También podemos utilizar un fichero de configuración, como el que vimos
en el capítulo 10, para almacenar los datos de la conexión.
La variable $ u s u a r i o recoge la creación del objeto de conexión y utiliza
el método c o n s u l t a () para recuperar el nombre de los usuarios de nuestra
Web.
Para extraer todos los datos nos encontramos con un bucle que va recuperando
un arraxj por registro, almacenándolo en $f i l a .
Utilizando f o r e a c h podemos extraer todas las columnas de la fila indicada.
Manipulación de datos
Seleccionar datos de una base de datos es sólo el principio; la potencia de
SQL nos permite también insertar, actualizar y borrar filas de una tabla.
Con el objeto que hemos creado es muy sencillo hacer consultas del tipo
INSERT, UPDATE o DELETE, llamando al método consulta () .
Insertar una fila
Para insertar una fila con nuestro objeto, tendremos que definir la consulta
y ejecutar el método consulta () .
<?php
require_once("MySQL.php");
$servidor = "localhost" ,-
$usuario = "root";
$pass = "" ;
$base_datos = "Compras";
$insertar = "INSERT INTO Usuario (nombre,cuenta) VALÚES
(\"Cristina\",2119) " ;
$usuario = new
Servidor_Base_Datos($servidor,$usuario,$pass,$base_datos);
^usuario->consuIta($insertar);
? >
Actualizar una fila
Antes de actualizar una fila, necesita identificar la fila o filas de la tabla
que quiere cambiar. En este ejemplo, se ha utilizado una sentencia SELECT
para averiguar primero el valor id_usuario de Luis Miguel y después
proceder a cambiar su cuenta bancaria.
<?php
require_once("MySQL.php");
$servídor = "localhost";
$usuario = "root";
$pass = " " ;
$base_datos = "Compras";
$consulta = "SELECT id_usuario FROM Usuario WHERE nombre='Luis
Miguel'";
$usuario = new
Servidor_Base_Datos($servidor,$usuario,$pass,$base_datos);
$usuario->consulta($consulta);
$fila = $usuario->extraer_registro() ;
$id_usuario = $fila["id_usuario"] ;
$actualizar = "UPDATE Usuario SET cuenta=9999 WHERE
id_usuario='$id_usuario'";
$usuario->consulta($actualizar);
?>
En un caso práctico, UPDATE puede utilizarse para modificar los datos
introducidos en un formulario Web.
Borrar una fila
Para borrar una fila puede seguir el mismo camino que se ha utilizado
antes para actualizar. Primero averigüe el registro que quiere eliminar y
después ejecute la consulta con la sentencia DELETE.
<?php
require_once("MySQL.php");
$servidor = "localhost";
{usuario = "luis";
$pass = "secreto";
$base_datos = "Compras";
$consulta = "SELECT id_usuario FROM Usuario WHERE nombre='Luis
Miguel'";
$usuario = new
Servidor_Base_Datos{$servidor,$usuario,$pass,$base_datos);
$usuario->consulta($consulta);
$fila = $usuario->extraer_registro() ;
$id_usuario = $fila["id_usuario" ] ;
$borrar = "DELETE FROM Usuario WHERE id_usuario =
1$id_usuario'";
$usuario->consulta($borrar);
?>
Errores con las comillas
Examinemos ahora el código siguiente:
<?PHP
require_once("MySQL.php");
if (isset ($_POST["nombre"] ) ]| isset ($_POST["cuenta" ]) ) {
$servidor = "localhost";
$usuario = "root";
$pass = " " ;
$base_datos = "Compras";
$nombre = $_POST["nombre" ] ;
$cuenta = $_POST["cuenta"] ;
$usuario = new Servidor_Base_Datos($servidor,$usuario,
$pass,$base_datos);
$insertar = "INSERT INTO Usuario(nombre,cuenta)
VALÚES ('$nombre','$cuenta')";
$usuario->consulta ($insertar) ;
}
?>
<HTML>
<BODY>
<form action="formulario_Usuario . php" method="POST">
Nombre: <INPUT type="text" name="nombre"><br>
Cuenta: <INPUT type="text" name="cuenta"><br>
<input type="submit" name="Enviar" >
</form>
</BODY>
<HTML>
El pequeño formulario que muestra la figura 12.2 permite insertar en la
tabla Usuario nuevos clientes.
Los campos de texto que recogen el nombre y la cuenta, pueden recibir
cualquier tipo de carácter; hay ciertos símbolos que pueden provocar que
un programa falle y son utilizados malintencionadamente por hackers para
corromper el sistema.
Si en la casilla destinada a escribir el nombre, escribe un nombre y en medio
una comilla simple y otra doble tal y como muestra el ejemplo:
Luis Migue'1 Cabezas Gra"nado
El método c o n s u l t a () intentará ejecutar:
mysql_query("INSERT INTO Usuario(nombre,cuenta) VALÚES (' Luis
Migue'1 Cabezas Gra"nado','')");
¿Puede ver el problema? Cuando MySQL lee la sentencia cree que es:
mysql_query("INSERT INTO Usuario(nombre,cuenta) VALÚES (' Luis Migue'
El resto de la sentencia causará un error y fallará la consulta. La solución
es añadir el símbolo de escape \ delante de la comilla simple para que
MySQL tome el símbolo ' como un simple carácter.
mysql_query("INSERT INTO Usuario(nombre,cuenta) VALÚES (' Luis
Migue\'l Cabezas Gra\"nado','')");
Existen tres soluciones para añadir el símbolo de escape a todas las comillas
que aparezcan en campo de texto:
• Lo primero que puede hacer es configurar el archivo php.ini, activando
la opción magic_quotes_gpc. Con esta opción, a todos los datos
pasados entre páginas Web por los métodos GET y POST, se les inserta
automáticamente símbolos de escape en las comillas que aparezcan.
• Si m a g i c _ q u o t e s no está activo en su servidor, PHP 5 tiene la función
a d d s l a s h e s (), que tiene el mismo cometido que la opción anterior.
Si magic_quotes está activo no podrá utilizar esta función,
porque se añadirían dos símbolos de escape.
• El tercer camino, muy similar a a d d s l a s h e s , usa la función
m y s q l _ e s c a p e _ s t r i n g . Esta función añade símbolo de escape a las
comillas simples, comillas dobles, caracteres de final de fichero y retorno
de carro. Es un método implementado por MySQL, por eso es
más recomendable utilizar a d d s l a s h e s .
Para saber si el fichero php.ini tiene activado magic_quotes existe la
función g e t _ m a g i c _ q u o t e s _ g p c ( ) . Puede añadir algunas líneas de
código a su formulario para que controle este tipo de error de la siguiente
forma:
<?php
require_once("MySQL.php");
if (isset($_POST["nombre"]) || isset($_POST["cuenta" ])) {
$servidor = "localhost";
$usuario = "luis";
$pass = "secreto";
$base_datos = "Compras";
if (get_magic_quotes_gpc()) {
$nombre = $_POST["nombre"];
$cuenta = $__POST ["cuenta" ] ;
} else {
$nombre = addslashes($_POST["nombre"]);
$cuenta = addslashes($_POST["cuenta"]);
}
$usuario = new Servidor_Base_Datos($servidor,$usuario,
$pass,$base_datos);
$insertar = "INSERT INTO Usuario(nombre,cuenta) VALÚES
('$nombre','$cuenta' ) " ;
$usuario->consulta($insertar);
}
?>
Contando filas
A menudo es útil conocer el número de filas devueltas por una consulta
antes de hacer cualquier cosa con el resultado. Puede averiguar el número
de filas mediante el uso de alguna función de PHP o la utilización de
MySQL para obtener el número de registros.
Contar filas con PHP
La función mysql_num_rows () devuelve el número de filas seleccionadas.
Su uso puede ampliar el objeto de bases de datos:
public function numero_filas()
{
return mysql_num_rows($this->resultado);
}
Además de esta función tenemos mysql_num_f i e l d s ( ) , que devuelve
el número de campos del una tabla; es necesaria cuando hacemos una consulta
de datos y no sabemos cuántas columnas hemos seleccionado.
Contar filas con MySQL
La alternativa es utilizar una consulta de SQL con la sentencia count ( * ) .
Esto requiere hacer dos consultas, una para obtener el número de filas y
otra para obtener el resultado.
Utilicemos el objeto para realizar la operación:
<?php
require_once("MySQL.php");
$servidor = "localhost";
$usuario = "root";
$pass = "" ;
$base_datos = "Compras";
$usuario = new
Servidor_Base_Datos($servidor,$usuario,$pass,$base_datos);
$consulta = "select count(*) as numero_filas from Usuario";
$usuario->consulta($consulta);
$fila = $usuario->extraer_registro() ;
$numero_filas = $fila["numero_filas"];
$consulta = "select * from Usuario";
$usuario->consulta($consulta);
echo "El número de filas es: $numero__f ilas<br>" ;
while ($fila = $usuario->extraer_registro()) {
foreach ($fila as $indice => $valor) {
echo "$indice: $valor<br>";
}
}
?>
La primera sentencia SELECT cuenta el número de filas y al resultado le
da el nombre numero__f i l a s .
Para acceder al número se hace como siempre, leyendo el resultado del
.irray $f i l a [ "numero_f i l a s " ] .
Contar filas afectadas
Es posible que sea necesario saber cuántas filas han sido afectadas después
de añadir, actualizar o borrar algunas filas.
La función mysql_af f e c t e d _ r o w s () devuelve el número de registros
afectados después de un cambio en las filas de una tabla. Actualizando
nuestra clase, tenemos:
public function filas_afectadas()
{
return mysql_affected_rows($this->descriptor);
}
Último número insertado
Cuando utilice campos auto numéricos en una tabla e inserte un nuevo
registro, será útil conocer el número de la última fila insertada.
Para obtener este número tan solo tiene que utilizar la función
m y s q l _ i n s e r t _ i d ( ) . Se puede utilizar de la siguiente forma:
public function ultima_fila()
{
return mysql_insert_id($this->descriptor);
}
Búsquedas dentro de una tabla
La forma de buscar ocurrencias en una columna es utilizar la sentencia
LIKE de SQL.
SELECT * FROM Usuario WHERE nombre LIKE '%Luis%'
El símbolo % es un comodín, es decir, puede sustituir a cualquier carácter
dentro de la columna donde busque.
Definición de bases de datos
Como indicamos antes, lo ideal es que un administrador de MySQL le
genere las bases de datos y las tablas. Después de esto, con su usuario y
contraseña podrá hacer las consultas que tenga autorizadas.
En muchos casos, la figura del administrador de bases de datos no existe
y es el desarrollador el que asume este papel. En este caso, le interesará
conocer la forma de crear desde un script sus bases de datos.
Creación de bases de datos
Para crear una base de datos tiene que utilizar la función m y s q l _ c r e a t e _
db () . Recibe dos parámetros, el primero es el nombre de la base de datos
que quiere crear y el segundo el descriptor devuelto por la función
mysq_connect () . La función mysql_drop_db () borra la base de datos
del gestor de MySQL.
<?php
$descriptor = mysq_connect($servidor, $usuario, $clave) ;
mysql_create_db("Nueva_Base" , $descriptor);
?>
Creación de tablas
La creación de tablas debe hacerse a través del lenguaje de consultas SQL,
como vimos en el capítulo anterior. Como ya sabe, la función mysql_query () acepta consultas de distintos tipos. Aprovechando esto, puede incluir una consulta para crear una tabla nueva.
SQLite es una base de datos poco tipada, es decir, que sólo es capaz de
almacenar dos tipos de datos: números o caracteres. En cambio, MySQL
es fuertemente tipada, porque tiene un elevado conjunto de tipos para
aplicar a sus columnas. La tabla 12.1 muestra algunos tipos de datos que
puede aplicar en la sentencia CRÉATE.
Como ejemplo puede ver el siguiente código:
<?
$descriptor = mysq_connect($servidor, $usuario, $clave);
mysql_create_db("Concesionario" , $descriptor) ;
mysql_ select_db ( "Concesionario") ,-
$consulta = "CRÉATE TAELE vehículos (
Íd_vehicul0 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
color VARCHAR(25),
fecha_compra DATETIME)";
$resultado = mysql_query($consulta) ;
$mensaje = mysql_drop_db("Concesionario");
?>
La columna i d _ v e h i c u l o identifica a un único vehículo de la tabla. Como
puede ver, en MySQL, tiene que añadir algunos modificadores a la columna
para identificar sus características. Estos modificadores son obligatorios
en MySQL. Por ejemplo, en SQLite no hace falta añadir ninguna
propiedad para que el valor se incremente automáticamente. En MySQL
es necesario especificar la propiedad AUTO_lNCREMENT. Es obligatorio
además que todas las columnas tengan un tipo de dato definido.
Resumen
MySQL es, sin duda, el sistema más utilizado a escala mundial. La mayor
parte de las aplicaciones en PHP están escritas para MySQL, porque da
una fiabilidad y velocidad absolutas. Hay que decir también que la versión
4 tiene bastantes restricciones con respecto a otros gestores de bases
de datos como PostgreSQL, pero se irán solventando en las futuras versiones.
Si terminó el capítulo con éxito, todavía le queda un paso por andar. La
extensión de MySQL que hemos utilizado es la que viene por defecto funcionando
con PHP 5. Recientemente se ha creado desde cero una nueva
forma de interactuar con MySQL, que permite hacer transacciones o consultas
almacenadas (de la forma que lo hace Oracle). La extensión se llama
MySQLi y por su leve dificultad, se escapa del objetivo de este libro. |