Está en la página 1de 131

MÓDULO 3

UNIDADES DIDÁCTICAS:

6. Utilización de MySQL

7. PHP y las bases de datos (PDO)

8. Utilidades prácticas
 
MÓDULO 3

Utilización de MySQL

Unidad 6

Índice de la unidad:

1. Arquitectura de una aplicación web

2. Teoría sobre bases de datos

3. Servidor MySQL

4. Sentencias MySQL

5. Resumen
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Introducción
En esta Unidad vamos conocer a la arquitectura de una aplicación web que
utiliza bases de datos.

Asimilarás el concepto y estructura de una base de datos.

Además, adquirirás conocimientos básicos de la base de datos MySQL y


utilizar correctamente sus sentencias para realizar diferentes operaciones con
los contenidos de las bases de datos.

Para acabar la Unidad, aprenderás y sabrás aplicar correctamente las


principales sentencias SQL.

Arquitectura de una aplicación web que use bases de


datos
Hemos visto hasta ahora cómo generar páginas dinámicas con PHP. En los
ejercicios y ejemplos anteriores hemos podido apreciar la capacidad de este
lenguaje para crear este tipo de páginas, si bien la información mostrada hasta
el momento es bastante sencilla y elemental. Pero PHP adquiere verdadera
potencia y utilidad en la generación de páginas dinámicas cuando utiliza la
información archivada en bases de datos.

Éste es precisamente el terreno en el que los lenguajes generadores de


páginas web alcanzan resultados espectaculares, hasta el punto de que más
del 90% de los websites se sirven de este procedimiento para enviar al cliente
su información. Por ejemplo, cualquier cadena de noticias tiene una base de
datos que puede ser actualizada permanentemente, incluso a larga distancia
por los corresponsales remotos, cuya información ofrece en tiempo real a los
clientes que entran en su web. Lo mismo pasa con las empresas de comercio
electrónico (e-commerce): usan diferentes bases de datos para contener
información sobre sus productos, los perfiles de sus clientes reales o
potenciales y los datos de las compras que éstos vayan haciendo. También las
web de las entidades bancarias usan bases de datos para archivar y mostrar
información sobre los movimientos en las cuentas corrientes y otras
operaciones de sus clientes.

En esta Unidad vamos a abordar conocimientos básicos sobre las bases de


datos y cómo se integran en una página web, estudiando concretamente la
base de datos MySQL y el lenguaje de consulta SQL. En la siguiente Unidad
abordaremos, directamente ya, cómo trata PHP las bases de datos al generar
las páginas dinámicas.

Arquitectura de una aplicación web

- 279 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

En el apartado Funcionamiento de un programa codificado con PHP de la


Unidad 1 presentamos el siguiente esquema:

En este gráfico aparecen sólo dos de las tres capas (tiers) que integran el
proceso completo de interpretación de una página web.

En la primera capa o nivel el usuario, utilizando su navegador, hace una


solicitud al servidor, con el que se conecta a través del protocolo HTTP. Le pide
que interprete un script y le remita el resultado, que se recibe en formato de
página HTML.

En la segunda capa o nivel el servidor envía esa solicitud al intérprete PHP


para que ejecute el programa y devuelve el resultado al navegador del cliente.

Pero ahora, llegado el momento, debemos añadir una tercera capa o nivel, que
está integrada por la base o bases de datos con las que conecta el servidor y
de las que extrae la información solicitada por el cliente. Es decir, el servidor,
cuando encuentra en el programa órdenes y funciones de creación,
modificación y consulta de una base de datos, acceda a ella y extrae, elimina o
actualiza esa información, según las operaciones que deban ejecutarse en el
script.

Para establecer esta conexión entre el servidor y la base de datos, es preciso


utilizar enlaces que sirvan de canal de comunicación entre ambos. Estos
enlaces pueden ser de dos tipos:

 Acceso mediante bibliotecas nativas (APIs)

El acceso mediante bibliotecas nativas que tenga cada tipo de base de


datos, denominado API (Application Programming Interface), está
integrado por el conjunto de funciones propias de un tipo de base de
datos que puede incorporar el programador cuando está utilizando ese
tipo de base.

Este tipo de enlace es más rápido y eficaz cuando se trabaja sólo con un
tipo de base de datos, pero exige cambiar el código si se utiliza otro tipo
de base de datos (los nombres de cada función son diferentes, el orden
de los argumentos distinto, las funcionalidades disponibles son distintas,
etcétera). Por ejemplo, Oracle y MySQL tienen APIs (bibliotecas de
funciones que en PHP se denominan extensiones) completamente
diferentes.

- 280 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

En las primeras versiones de PHP, la única manera de acceder a una


base de datos era a través de una biblioteca específica que debía estar
activada en PHP y que contenía las funciones necesarias.

Actualmente (Mayo de 2014), PHP sigue incluyendo muchas de estas


extensiones y todavía se pueden utilizar, pero en su lugar se recomienda
utilizar la biblioteca PDO que se comenta a continuación.

 Acceso mediante PDO (Objetos de Datos de PHP)

Para poder escribir programas independientes del tipo de base de datos


elegido, es necesario utilizar una capa de abstracción que permita
acceder de una forma común a cualquier tipo de base de datos.

Entre ellos, está el tipo estándar de capa de abstracción ODBC (Open


DataBase Connectivity), que es más genérico y sirve para conectar
cualquier servidor con aquellas bases que lo soporten, que son casi
todas. En PHP existe una extensión llamada también ODBC que permite
conexiones ODBC. El inconveniente de esta extensión ODBC es que
introduce un elemento más en la cadena, el controlador ODBC del
sistema operativo, lo que ralentiza el rendimiento del servicio.

Para arreglar este problema, PHP ha desarrollado su propia capa de


abstracción orientada a objetos llamada PDO que incluye controladores
para acceder a las bases de datos más populares. Si bien, al utilizar
PDO no podemos olvidarnos completamente del tipo de base de datos
utilizado como, por ejemplo, la conexión al servidor de bases de datos la
creación de tablas, etcétera.

Hoy por hoy, la extensión PDO es la biblioteca recomendada para


acceder a bases de datos con PHP y es la que vamos a estudiar en
este curso.

Así queda el esquema completo incluyendo el servidor de base de datos:

- 281 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Así pues, en las Unidades 6 y 7 vamos a aplicar el proceso completo:

 Se escribe el código fuente de la página web en lenguaje PHP


incluyendo las funciones PDO.
 Se guarda este código en el servidor web.
 El navegador del usuario solicita al servidor la página codificada y
guardada en los dos pasos anteriores.
 El servidor interpreta el código PHP conectando, cuando sea preciso,
con la base de datos y realizando con ella las operaciones previstas.
 El servidor envía el resultado del código PHP al navegador del usuario,
que ve en su pantalla la página en formato HTML.

- 282 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Teoría sobre bases de datos


En este apartado vamos a explicar brevemente algunos conceptos
fundamentales sobre las bases de datos. Suponemos que el alumno o alumna
ya tiene conocimientos suficientes sobre las mismas y, por tanto, abordaremos
sólo algunos conocimientos más relacionados con la forma en que PHP accede
a las bases de datos y trata su información.

El término base de datos es informático, pero puede aplicarse también a la


forma como se almacena, ordena y utiliza manualmente la información. Por
ejemplo, la agenda en la que apuntamos manualmente los datos con el
nombre, dirección y teléfono de nuestros amigos o personas con las que
necesitamos relacionarnos, puede ser considerada una base de datos en este
sentido más amplio. Igualmente, el archivador en el que guardamos las fichas
bibliográficas de una investigación o de una biblioteca también puede ser
considerado como tal. En todas ellas se almacena información, se ordena de
alguna forma (alfabéticamente en la agenda, por temas, autores o títulos en el
fichero de la biblioteca, etcétera) y se consulta cuando es necesario.

Sin embargo, en el sentido informático, la palabra base de datos se refiere a


una colección, conjunto o depósito de datos, almacenados en un soporte
magnético o de otro tipo, accesibles por múltiples usuarios de forma rápida y
eficaz mediante el ordenador a través de una o de varias aplicaciones
informáticas independientes de los datos. Éstos se relacionan entre sí y están
organizados de tal manera que es fácil introducirlos, actualizarlos, recuperarlos
o llevar a cabo con ellos otras operaciones de gestión.

En el caso de PHP es el servidor quien conecta con la base de datos, a


petición del navegador del usuario, y realiza las operaciones previstas en la
aplicación, devolviendo posteriormente al navegador del cliente los resultados
de esas operaciones.

Generalmente, en las bases de datos relacionales, de las que hablaremos


después, la información está almacenada y organizada en ficheros formados
por filas y columnas, como puede verse en el ejemplo siguiente, en el que se
presentan algunos datos de cinco libros de una biblioteca:

Columnas
Título Autor Editorial
Antonio Muñoz
El invierno en Lisboa Seix Barral
Molina
Fondo de Cultura
¿Tener o ser? Erich Fromm
Económica
Filas
Crónica de una muerte Gabriel García
Bruguera
anunciada Márquez
El lobo estepario Hermann Hesse Anaya Editores
La vida está en otra
Milan Kundera Seix Barral
parte

- 283 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Cada fila contiene el título, el autor y la editorial de un libro y se relaciona con


las demás filas gracias a que incluye el mismo tipo de información (datos de los
libros) y en todas ellas la información está organizada de la misma forma: la
primera columna contiene el título del libro, la segunda, el autor y la tercera, la
editorial.

Así pues, una base de datos contiene un conjunto de ficheros cuya


información está organizada de tal forma que puede ser tratada
informáticamente con rapidez y eficacia. La información de una base de datos
puede almacenarse en un solo fichero o en varios.

Los ficheros de una base de datos están grabados en el servidor. Tienen un


nombre (por ejemplo, flores, ríos, libros, coches, amigos, articulo, clientes,
ventas, facturas, etcétera). Su denominación debe seguir las normas
establecidas para que el nombre de un fichero sea correcto. Como puede
verse, hemos prescindido de las tildes en los identificadores que las llevan
ortográficamente.

El tipo o extensión de estos ficheros de base de datos puede ser muy variado,
según el tipo de base de datos utilizado: en dBase es dbf (Data Base File,
Fichero de Base de Datos), en Access mdb, en Interbase db o dbf, en MySQL
myd, etcétera.

Las filas de un archivo de base de datos se denominan registros y las


columnas, campos (fields, en inglés).

Así pues, un fichero de base de datos está integrado por registros, que son
cada uno de sus elementos o componentes (flor, río, libro, coche, amigo,
artículo, cliente, venta o factura). Todos los registros contienen un conjunto de
campos en los que se almacena su información; este conjunto define la
estructura del fichero que integra una base de datos.

En la representación gráfica siguiente puede observarse, en forma de tabla, la


estructura de un fichero que contiene una base de datos con información sobre
personas:

Campos

Nombre Sueldo Fecha_nac Observacion Foto


1
2
3
4
Registros
5
6
7
8
9

- 284 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

10
11

En las filas aparecen hasta once registros cada uno de los cuales, en este
caso, contiene los cinco campos siguientes: Nombre, Sueldo, Fecha_nac,
Observacion y Foto.

En el ejemplo anterior sólo se han incluido once registros y cinco campos, pero
de hecho en las bases de datos que vamos a usar el número de registros es
ilimitado (depende de la capacidad del soporte) y el de campos es muy amplio,
según el tipo de base de datos usada. Todos los registros tienen los mismos
campos.

Si comparamos un fichero de base de datos con los archivadores de una


biblioteca, podemos decir que éstos integran la base de datos. Cada archivador
es como un fichero de la base de datos, las fichas que hay en su interior son
los registros y los apartados de cada ficha (título, autor, editorial, etcétera) son
los campos.

Cada campo de un registro tiene un nombre, un tipo, una longitud o ancho,


un número de decimales si es de tipo numérico o de coma flotante y un
índice opcional. Según el tipo de base de datos que se esté utilizando, el
identificador del campo, la clase de tipos y la longitud de los mismos pueden
ser diferentes. Nos vamos a referir, como ejemplo, sólo a la estructura de las
bases de datos creadas con MySQL.

NOTA: este apartado no pretende ser una descripción exhaustiva del uso de la
base de datos MySQL y del lenguaje SQL. Tiene como objetivo recordar los
conceptos básicos de la programación con Bases de datos.

El nombre de cada campo puede ser muy largo, si bien recomendamos que en
el orden práctico sea lo más breve posible y tenga algún significado. Debe
atenerse a las reglas de todos los identificadores ya comentadas
anteriormente.

Hay estos tipos de campos, que citamos de forma genérica:

1. Campo de tipo Carácter. Es el más común (letras, dígitos, signos, etcétera),


y contiene información que es tratada como una cadena de caracteres. Se
asigna este tipo a un campo cuando no se realizan operaciones aritméticas con
sus datos, ni contiene una fecha, ni es un texto mayor de 255 caracteres. Por
ejemplo, se asigna este tipo al campo cuyo contenido va a ser el nombre de
una persona, sus apellidos, domicilio, localidad, provincia, etcétera. Admite
índice. En MySQL hay dos tipos de campos para almacenar datos de esta
clase: CHAR y VARCHAR. Tiene una longitud desde 1 hasta 255 caracteres. Si
la longitud de la cadena que se asigna a este campo no alcanza los 255
caracteres, el tipo CHAR completa con espacios en blanco los que falten
ocupando siempre este campo la misma longitud. En cambio, el tipo de
carácter VARCHAR sólo ocupa el espacio que precise la cadena de texto, es

- 285 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

decir, su longitud es variable y, por tanto, se ahorra espacio cuando el


contenido puede ser muy diferente en longitud.

2. Campo de tipo Numérico. Se utiliza para escribir números, incluidos los


signos positivo y negativo. Se asigna este tipo a un campo cuando se realizan
operaciones aritméticas con números enteros o reales, como sumar, restar,
multiplicar, dividir, etcétera. Admite índice. MySQL admite estos valores para
determinar los campos de este tipo: TINYINT, SMALLINT, MEDIUMINT, INT,
BIGINT, REAL, DOUBLE, FLOAT, DECIMAL y NUMERIC. Como puede verse,
en realidad los valores posibles se refieren a si es un campo de número entero
o decimal y al número de dígitos con los que debe representarse el valor en
cada caso.

3. Campo de tipo Fecha. Puede contener fechas y tiempos (horas, minutos,


segundos). Admite índice. MySQL admite aquí los valores siguientes: DATE,
TIME, TIMESTAMP y DATETIME.

4. Campo de tipo Memo. Es un campo de longitud variable que admite gran


cantidad de texto según nuestras necesidades. Para cada registro tendrá una
longitud distinta, según la cantidad de texto que se introduzca en este campo.
No admite índice. MySQL admite aquí los valores siguientes: TINYBLOB,
BLOB, MEDIUMBLOB, LONGBLOB, TINYTEXT, TEXT, MEDIUMTEXT y
LONGTEXT.

5. Campo de tipo serie. Es un campo donde se puede poner uno de los valores
incluidos en una lista o serie de valores. MySQL admite aquí los valores
siguientes: ENUM y SET.

Ventajas de las bases de datos

Hemos dicho que los archivadores de una biblioteca o de una agenda pueden
considerarse, en cierta forma, bases de datos, pues en ellos se almacena
información en un determinado orden y es posible buscar esta información,
consultarla, modificarla o eliminarla con facilidad.

Sin embargo, todas estas operaciones suelen llevar mucho tiempo y, en


ocasiones, no se efectúan tan fácilmente como desearíamos. Además, ocupan
bastante espacio si la información es abundante. Incluso, en ocasiones,
algunas operaciones fundamentales son imposibles de realizar manualmente.

Por ejemplo, si tenemos 1.000 fichas bibliográficas ordenadas por autor y


necesitamos ordenarlas por título, la operación ha de realizarse manualmente,
mirando una a una cada ficha, lo cual puede hacerse muy largo y pesado.
Podíamos haber escrito dos ejemplares de cada ficha, uno para el archivo por
autores y otro para el de títulos, pero esto hubiera llevado el doble de tiempo,
de trabajo y éstas ocuparían el doble de espacio.

Supongamos ahora que necesitamos seleccionar todas las fichas en las que
aparece la misma editorial. De nuevo la tarea puede parecernos pesada y

- 286 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

larga, y lo es. No digamos si se cambia la situación de los libros en los armarios


de la biblioteca. También será necesario modificar la signatura en las fichas.

Hemos puesto este ejemplo para explicar los graves problemas que se derivan
de la gestión manual de la información. Las dificultades aumentan a medida
que crece el volumen de información que debe manejarse y según sean los
criterios de ordenación y selección.

En una base de datos informática, en cambio, al gestionarse la información


automáticamente, muchos de los problemas anteriormente mencionados
desaparecen.

En primer lugar, la rapidez de las operaciones fundamentales (introducción de


datos, ordenación por diferentes campos, consultas, búsquedas, elaboración
de informes, actualización y modificación de los datos, etcétera) aumenta de
una forma muy destacada.

En segundo lugar, el espacio que ocupa una base de datos es mucho menor
que el de cualquier otra forma de archivo manual. En un disco flexible de 3,5
pulgadas puede almacenarse casi un millón y medio de caracteres. En los
discos duros de los actuales servidores el volumen de información puede ser
prácticamente ilimitado.

En tercer lugar, las operaciones fundamentales de gestión de la información


son automáticas, lo cual hace que sean menos pesadas y tediosas si son
llevadas a cabo por el ordenador. Así pues, el trabajo se humaniza y el tiempo
libre de las personas que manejan la información es mayor.

Finalmente, la seguridad de los datos informatizados también es mayor que la


contenida en archivos de tipo manual, pues el ordenador nos permite hacer
rápidamente cuantas copias queramos de esa información en diferentes
soportes.

Desde la aparición de los ordenadores, éstos se han dedicado al


almacenamiento y organización de grandes volúmenes de datos. Igualmente,
se han aplicado a la evaluación de las diversas soluciones propuestas para
resolver los problemas de estructuración y acceso a dicha información.

Bases de datos relacionales

Se ha descubierto que la mejor forma de resolver estos problemas es organizar


la información de forma relacional. De aquí ha surgido el concepto de bases de
datos relacionales (RDBMS, Relation DataBase Management System).

El fundamento teórico de las bases de datos relacionales es complejo, ya que


se basa en el concepto matemático de relación entre los elementos de un
conjunto. Sus características y propiedades formales requieren ciertos
conocimientos de la teoría de conjuntos. Sin embargo, en la práctica, el

- 287 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

concepto de relación es muy sencillo de utilizar porque en ésta la organización


de los datos es muy clara e intuitiva.

En otros tipos de organización de la información, como las bases de datos


jerárquicas o las bases de datos en red, anteriores a las relacionales,
aparecían distintas categorías de datos y estructuras muy complejas y poco
flexibles que dificultaban la posibilidad de relacionar éstos con eficacia y
rapidez. En cambio, en las bases de datos relacionales la información se
organiza en ficheros que tienen estructura tabular o en forma de tabla, en la
que todos los datos tienen la misma categoría. Cada tabla también recibe el
nombre de relación.

Por ejemplo, en el gráfico siguiente puede observarse una tabla que contiene
diversos datos de personas:

Cabecera Nombre Dirección Edad Sexo Profesión


1 León García C/ Zurita, 25 25 V Admtvo.
2 María Pérez C/ Flores, 15 30 M Abogada
Filas
José Rodríguez C/ Río Sil, 11 50 V Dependiente
(Registros) 3
4 Juana de Dios Avda. Canarias, 50 70 M Jubilada
5 Begoña López Pza. Segovia, s/n 15 M Estudiante

|___________|________|___|_____|
Columnas (Campos)

Como se ve, una tabla consta de filas y de columnas; en cada columna,


denominada campo en la base de datos, hay un dato: Nombre, Dirección,
Edad, etcétera; cada fila es un registro que contiene todos los datos de los
elementos de la base. Cada tabla tiene un registro especial, denominado
cabecera, que contiene los nombres de los campos y sus atributos (tipo y
longitud).

Generalmente, una base de datos no consta de una sola tabla, sino de varias.

Gráficamente puede representarse así:

- 288 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Estas tablas no son independientes unas de otras, sino que tienen al menos un
campo común con las otras a través del cual se puede acceder a la información
que contienen todas en conjunto.

Por ejemplo, la base de datos de una biblioteca puede estar integrada por una
tabla de libros, otra de lectores, otra de préstamos y otra de editoriales. El
fichero de libros puede contener la información completa de cada volumen:
título, autor, editorial, año de edición, precio, número de páginas, código de
materia, número de registro, etcétera.

El fichero de editoriales contendrá los datos de cada entidad editora: nombre,


dirección, teléfono, plazo de entrega, descuentos, etcétera.

El fichero de lectores estará integrado por los datos personales y profesionales


de éstos: nombre, DNI, dirección, teléfono, profesión, centro de trabajo, número
de carné, etcétera.

El fichero de préstamos contendrá datos de este tipo: número de registro del


libro prestado, número de carné del lector, fecha del préstamo, plazo, etcétera.

Como puede verse, la información no debe repetirse en todos los ficheros, pero
sí debe poder relacionarse. Por ejemplo, los ficheros de libros y editoriales,
tienen en común el campo EDITORIAL. Los ficheros de libros y préstamos
tienen en común, al menos, el NÚMERO DE REGISTRO del libro prestado,
gracias a lo cual desde uno se puede acceder a los datos del otro. Los ficheros
de lectores y préstamos tienen en común el campo CARNÉ, etcétera.

Son bases de datos relacionales Microsoft Access, Oracle, SQL Server,


MySQL y otras.

Hay otro tipo de base de datos que está orientado a los objetos (ODBMS,
Object Oriented DBMS) en las que cada dato es tratado como si fuera un

- 289 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

objeto con sus atributos y métodos. Son de este tipo ObjectStore, Versand,
GemStore, etcétera.

También hay otro tipo que reúne características propias de los dos tipos
anteriores, como PostgreSQL, que son conocidas como ERDBMS (Extended
Relacional DBMS) y como ORDBMS (Object Relational DBMS). PHP puede
tratar prácticamente todas las bases de datos mencionadas.

Diseño de bases de datos

El diseño de bases de datos puede presentar distinto tipo de dificultad


dependiendo de la complejidad e interrelación de los datos que se quiera
gestionar.

Imaginemos que una compañía aérea quiere gestionar toda la información


contenida en una base de datos relativa a los aviones y su mantenimiento, a
los vuelos, viajes, destinos, clientes, personal de la empresa, agencias de
viajes, billetes, asistencia, etcétera. Es evidente que, en este caso, la
complejidad es enorme y que para realizar el diseño de esta base se requiere
la colaboración de técnicos especialistas que faciliten la tarea.

Sin embargo, en la mayoría de las ocasiones el diseño de una base de datos


se resuelve con uno, dos o tres ficheros como máximo. En este caso no es
necesario profundizar en aspectos complejos de técnicas de diseño, sino que
basta aplicar el sentido común para organizar los ficheros de la base de datos
de forma coherente.

Deben crearse tantos ficheros como categorías o grupos de elementos distintos


haya que organizar. Por ejemplo, en una tienda que vende al por menor
bastaría con crear un fichero de artículos y otro de proveedores, y a lo sumo
otros tres: de pedidos, de ventas y de clientes.

Antes de ponerse a crear una base de datos con el ordenador, es preciso


diseñarla previamente sobre el papel. La planificación es fundamental en este
caso para evitar errores graves: falta de datos necesarios, repetición
innecesaria de algunos, equivocación del tipo de campo o falta de precisión en
su longitud. Aunque es posible modificar la estructura de una base de datos,
una vez creada, se puede perder mucho tiempo e incluso datos en esta
operación.

Diseñar una base de datos consiste en determinar los datos que van a
introducirse en ella, la forma como se van a organizar y el tipo de esos datos.
Además, se debe precisar la forma como se van a solicitar y las clases de
operaciones que hay que realizar con los mismos: aritméticas, lógicas, de
fechas, de carácter, etcétera. También conviene conocer los resultados
concretos que se espera obtener: consultas, informes, actualizaciones,
documentos, etcétera.

- 290 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

A continuación, se resumen las operaciones que deben llevarse a cabo al


diseñar una base de datos:

1. Atendiendo a la información que contiene es preciso:

• Identificar los diferentes elementos informativos


(artículos, clientes, ventas, facturas, etcétera) que
forman parte de la base de datos.

• Determinar los datos que debe contener cada uno de esos


elementos.

• Precisar el grado de necesidad y de utilización de cada


dato.

• Concretar las operaciones que se van a realizar con los


datos: aritméticas, lógicas, de salida sólo por la
pantalla, de salida también por la impresora, etcétera.

• Seleccionar el dato o datos esenciales que deben ser el


campo clave por el que se ordenarán las unidades o
elementos mencionados.

• Fijar los datos comunes a los diferentes ficheros de la


base de datos que van a permitir relacionar la
información distribuida entre ellos.

2. Atendiendo a la estructura de la base de datos

• Distribuir la información en ficheros según los


diferentes grupos que se hayan hecho (artículos,
clientes, etcétera) y dar un nombre a cada fichero.

• Determinar el nombre de cada campo de los registros de


cada fichero. Este nombre ha de ser claro y debe
significar algo para que pueda recordarse fácilmente.

• Decidir qué tipo conviene asignar a cada campo según la


clase de operaciones que vayamos a realizar con sus
datos.

• Asignar a cada campo una longitud apropiada para tener


los datos fundamentales sin despilfarro de memoria
interna ni de espacio en el disco duro o soporte
empleado.

• Establecer un orden lógico y práctico agrupando los


campos según un criterio concreto: clase e importancia de
los datos, frecuencia de utilización, proximidad,

- 291 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

parecido, etcétera.

• Decidir cuál o cuáles van a ser los campos clave


permanentes y situarlos al principio de la estructura.

• No incluir campos que puedan ser el resultado de


diversas operaciones de tratamiento posterior.

• Fijar los campos comunes a todos los ficheros para


poder relacionarlos con otros de la misma aplicación.

- 292 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Servidor de base de datos MySQL


La base de datos MySQL ha formado y forma desde el principio una pareja
perfecta con PHP. En este apartado vamos a trabajar con ella, ya que es la
que utilizamos en el curso.

La mayoría de los desarrolladores, desde que PHP puede utilizar bases de


datos, han seleccionado esta base de datos. Por ejemplo, hace ya algunos
años que la NASA migró algunas de sus aplicaciones web a PHP utilizando
como base de datos precisamente MySQL.

Con el fin de asimilar bien los contenidos sobre las bases de datos, en esta
Unidad sólo se van a explicar de forma sencilla y práctica dos asuntos
importantes:

1. La base de datos MySQL, a través del Cliente MySQL Workbench, que


facilita y hace más intuitiva la comprensión de los conceptos. Así se evita, a la
vez, la poco estimulante tarea de escribir una a una las instrucciones en el
prompt del sistema. El estudio y las prácticas realizadas con esta utilidad
prepararán a los alumnos y alumnas para poder aplicar estos conceptos a otros
tipos de bases de datos.

2. Las funciones de PHP que permiten tratar las bases de datos y su


información en MySQL. Este asunto se abordará en el apartado siguiente.

Con los conocimientos anteriores bien asimilados, será más fácil comprender
con detalle y aplicar correctamente las funciones de PHP que permiten
conectarse a una base de datos, realizar consultas, acceder a los resultados de
las consultas y realizar otras operaciones auxiliares e informativas sobre
cualquiera de las bases de datos que usamos en el curso. También será
posible utilizar el lenguaje de consulta SQL para obtener informes. Esto es
precisamente lo que abordaremos en la Unidad siguiente.

Para tener acceso a las bases de datos, en primer lugar, hay que arrancar el
servidor de datos MySQL.

Arrancamos el Panel de control de XAMPP. Si hacemos clic en el botón “Start”


del servidor MySQL, a continuación, se cambiará el texto del botón a “Stop”.
Además, desde este Panel se ofrecen varias opciones para gestionar el
servidor, que nos permiten realizar, entre otras, configurar el servidor (Config)
y administrar el servidor de nuevo (Admin), etcétera. A continuación, se
muestra el servidor MySQL arrancado:

- 293 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

En la captura anterior, si usas Windows, su Firewall solicitará permiso para la


ejecución del servidor MySQL, debemos pulsar el botón “Permitir acceso”.

Ahora ya podemos arrancar el fichero Mysql.exe (utilidad MySQL monitor) que


aparece en el directorio de instalación de XAMPP, en el caso de Windows
C:\xampp\mysql\bin. Este programa se ejecutará en modo MSDOS y se
presentará en la pantalla la ventana principal de este gestor de bases de
datos. Para arrancarlo debemos escribir mysql.exe -u root (con "-u root"
estamos indicando el usuario con el que queremos conectarnos al servidor)
desde una ventana de comandos en el directorio C:\xampp\mysql\bin. Éste es
su texto inicial:

- 294 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

El cursor se coloca detrás del promtp mysql> esperando que vayamos


introduciendo las órdenes o comandos que deban ejecutarse. Por ejemplo, si
escribimos

mysql> show databases;

se muestra a continuación:

mysql> show databases;


+--------------------+
| Database |
+--------------------+
| information_schema |
| cdcol |
| mysql |
| performance_schema |
| phpmyadmin |
| test |
| webauth |
+--------------------+
7 rows in set (0.02 sec)

mysql> Si escribimos

mysql> \h

aparece la

For information about MySQL products and services, visit:


http://www.mysql.com/
For developer information, including the MySQL Reference Manual,
visit:
http://dev.mysql.com/

To buy MySQL Enterprise support, training, or other products, visit:


https://shop.mysql.com/

- 295 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

List of all MySQL commands:


Note that all text commands must be first on line and end with ';'

? (\?) Synonym for `help'.


clear (\c) Clear the current input statement.
connect (\r) Reconnect to the server. Optional arguments are db and
host.
delimiter (\d) Set statement delimiter.
ego (\G) Send command to mysql server, display result
vertically.
exit (\q) Exit mysql. Same as quit.
go (\g) Send command to mysql server.
help (\h) Display this help.
notee (\t) Don't write into outfile.
print (\p) Print current command.
prompt (\R) Change your mysql prompt.
quit (\q) Quit mysql.
rehash (\#) Rebuild completion hash.
source (\.) Execute an SQL script file. Takes a file name as an
argument.
status (\s) Get status information from the server.
tee (\T) Set outfile [to_outfile]. Append everything into given
outfile.
use (\u) Use another database. Takes database name as argument.
charset (\C) Switch to another charset. Might be needed for
processing binlog with multi-byte charsets.
warnings (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.

For server side help, type 'help contents'

El uso de esta herramienta supone que debemos conocer las órdenes de


MySQL y su sintaxis correcta, procedimiento ya algo anticuado y de otra época.
Por eso, hemos preferido servirnos de una utilidad más moderna bajo
Windows, con la que podemos realizar en MySQL todas las operaciones con
las bases de datos, a la vez que aprender de una forma más amigable los
comandos de MySQL que permiten realizar todas las operaciones propias de
las bases de datos. Se denomina MySQL Workbench.

Abandonamos, pues, con el comando quit; la utilidad MySQL monitor y vamos


a instalar esta moderna aplicación con la que vamos a aprender a trabajar con
las bases de datos de tipo MySQL.

MySQL Workbench

Para instalar este cliente MySQL debemos acceder con el navegador a la


página siguiente en Internet:

http://www.mysql.com/products/workbench/

- 296 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Hacemos clic en el botón “Download Now” y aparecerá esta página:

A continuación, elegimos la versión correspondiente al sistema operativo que


estemos utilizando y pulsamos el botón “Download”. En la página que aparece
a continuación, pulsamos la opción “No thanks, just start my download”:

- 297 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Una vez se descarga el fichero, lo descomprimimos en una carpeta de la


instalación XAMPP, por ejemplo en la carpeta C:\xampp\mysql\MySQL
Workbench 6.1.6 CE:

A continuación, creamos un acceso directo en el escritorio de la aplicación


MySQLWorkbench.

- 298 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Finalmente, ejecutamos la aplicación MySQL Workbench y aparece a


continuación la siguiente pantalla:

A continuación, vamos a establecer una conexión con el servidor MySQL que


hemos arrancado. Para ello, hacemos clic en el botón (+) que aparece en la
siguiente ventana y rellenamos los campos que aparecen a continuación:

- 299 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Pulsamos el botón “Test Connection” para comprobar que la conexión funciona


correctamente. El botón OK que aparece a su lado da de alta la nueva
conexión “curso PHP 5”:

Haciendo clic sobre la nueva conexión “curso PHP 5” conectamos el gestor con
el servidor MySQL local:

• En la mitad superior pueden observarse tres elementos:

1. El menú de opciones y los iconos de acceso rápido:

- 300 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

2. La ventana del Navigator (Navegador) muestra el estado del servidor, las


conexiones establecidas, los usuarios, etcétera. SCHEMAS muestra las bases
de datos a los que tiene acceso y las tablas y los campos que integran esta
base de datos. Si hacemos doble clic sobre el nombre de una base de datos en
particular veremos que su texto se cambia a negrita; esto indica que hemos
activado esta base de datos y todas las SQL's se aplicarán sobre la misma. La
ventana es la siguiente:

3. En la ventana siguiente puede verse el cuadro de texto para introducir una


Consulta SQL. Es importante saber que en este cuadro de texto podremos
introducir varias consultas al mismo tiempo. Cada consulta SQL debe terminar
con el carácter punto y coma. El botón Execute sirve para ejecutar las
consultas. También disponemos del atajo de teclado [CONTROL + INTRO]
para ejecutar las consultas. La ventana es ésta:

- 301 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Además, en esta ventana, al escribir las sentencias SQL, el programa ofrece, a


modo de ayuda, diferentes posibilidades para terminar la sentencia:

Con el atajo de teclado [CONTROL + BARRA ESPACIO] podemos forzar que


aparezca esta ventana de ayuda.

• En la parte inferior de la ventana principal van apareciendo de forma


automática mensajes que indican si la ejecución de la SQL ha ido bien

- 302 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

mostrando un mensaje de error en caso contrario. En la imagen anterior se


puede ver estos mensajes.

- 303 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Principales sentencias de MySQL


En este apartado vamos a estudiar las sentencias fundamentales que permiten
tratar bases de datos de tipo MySQL.

Vamos a utilizar las principales sentencias de este gestor de datos escribiendo


mediante la aplicación Cliente MySQL Workbench los efectos que produce la
interpretación de cada comando.

Así pues, para estudiar este tema, hay que activar el Servidor MySQL de
XAMPP y el Cliente MySQL Workbench para observar lo que pasa.

Creación de una bases de datos

Para trabajar con una base de datos, en primer lugar hay que crearla. Se hace
con la orden create database seguida del nombre que queremos darle. Para
crear la base de datos “almacen”, escribimos

CREATE DATABASE almacen;

Podemos comprobar que ha sido creada de cuatro formas diferentes:

1. Leyendo el mensaje que devuelve MySQL indicando que se ha hecho :

20:20:20 CREATE DATABASE almacen 1 row(s) affected 0.000 sec

2. Mirando con el Explorador de ficheros que se ha creado una carpeta nueva


con el nombre “almacen” en el directorio

3. Desde el Cliente MySQL Workbench en la parte Schemas el botón Refresh


. Se verá que hay una nueva base de datos denominada “almacen” que aún
no tiene ninguna tabla en su interior.

- 304 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

4. Ejecutando en la propia ventana del MySQL monitor la orden show


databases, que estudiamos a continuación.

Como puede ocurrir que ya exista un base de datos con el mismo nombre que
la se pretende crear, en cuyo caso aparecería un error de creación de la base
de datos, lo mejor es usar la sintaxis condicional create database if not
exists almacen;. De esta forma, si la base de datos existe, no se crea una
nueva destruyendo la anterior.

Mostrar todas las bases de datos

La sentencia show databases; se usa para mostrar todas las bases de datos
que haya en el servidor MySQL. Podemos observarlo en la ventana siguiente:

Recordamos que las bases de datos mysql son imprescindibles para el


funcionamiento correcto del sistema y del curso, por lo cual no deben borrase
nunca.

Utilizar una base de datos

Para poder usar una base de datos, por ejemplo para acceder a sus tablas, es
preciso abrirla antes, operación que se realiza con la sentencia use <nombre de
la base de datos>. Por ejemplo, si queremos abrir la base de datos “almacen”,
escribiremos use almacen y, si se ha podido abrir, el sistema muestra el
mensaje de confirmación Database changed . A partir de aquí, ya podemos
crear tablas en su interior o acceder a los registros y campos de las mismas. Si
usamos la aplicación Cliente MySQL Workbench basta con hacer doble clic

- 305 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

sobre el nombre de la base de datos que queremos usar; veremos que su texto
cambia a negrita indicándonos que está activa.

Crear una tabla

Una vez que hemos abierto la base de datos “almacen”, vamos a crear tres
tablas sencillas dentro de la misma: “productos”, “compras” y “clientes”. Para
crear la tabla “productos”, damos la orden siguiente:

create table if not exists productos (


codigo INT PRIMARY KEY AUTO_INCREMENT,
nombre VARCHAR(30) NOT NULL,
precio_euros DECIMAL(8,3) DEFAULT 0.0 NOT NULL,
stock TINYINT NOT NULL,
descuento SET('S','N') NOT NULL DEFAULT 'S',
caduca DATE,
notas TEXT);

Con esta orden hemos creado, dentro de la base de datos “almacen”, la tabla
“productos”, que tiene esta estructura:

Nombre del campo Tipo de campo Longitud Propiedades


PRIMARY KEY
codigo INT 11
AUTO_INCREMENT
nombre VARCHAR 30 NOT NULL
precio DECIMAL 8,3 NOT NULL
stock TINYINT 4 NOT NULL
NOT NULL
descuento SET
DEFAULT "S"
caduca DATE
notas TEXT

La misma información puede obtenerse con la sentencia

show columns from productos;

como puede verse en esta ventana:

- 306 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Conviene hacer algunas observaciones que el alumno debe tener en cuenta:

1. En la tabla “productos” hemos creado seis campos cuyo identificador debe


ser válido: codigo, nombre , precio_euros , stock , descuento , caduca y notas .

2. A cada campo le hemos asignado su tipo, longitud y características


adecuadas, según el contenido que vamos a introducir en ellos:

 El campo codigo es de tipo numérico entero INT y tiene una longitud de


11 dígitos (incluido el signo – si lo hay); no puede ser nulo, es decir,
estar vacío; es el índice primario, es decir, el valor único (uno distinto
para cada registro) por el que MySQL va a ir ordenando los registros a
medida que se den de alta; y se autoincrementa cada vez que se añade
un registro nuevo. Observe el alumno que en el tipo de campo no ha
sido preciso escribir la longitud, pues MySQL asume por defecto que el
tipo INT es de 11 posiciones. Los tipos numéricos enteros pueden ser
más largos o más cortos, según el número máximo que pretendamos
introducir en ese campo: TINYINT asigna 4, SMALLINT asigna 6,
MEDIUMINT asigna 9, BIGINT asigna 20.

 El campo nombre es de tipo VARCHAR, tiene una longitud de 30 y no puede


ser nulo. Si se observa ahora la sintaxis de la sentencia, se verá que
hemos puesto la longitud de este campo entre paréntesis. El valor
máximo posible es de 255. El tipo CHAR se comporta igual que VARCHAR,
con la diferencia de que CHAR guarda la longitud completa indicada,
aunque parte del campo esté vacía, como ya hemos explicado en un
apartado anterior.
 El campo precio_euros es de tipo DECIMAL, lo cual indica que el número
que se puede guardar en él tendrá parte entera y parte decimal.
Tampoco puede ser nulo y por defecto toma “0.000”. Hay que tomar nota
de la sintaxis precio_euros DECIMAL(8,3) : entre paréntesis se ponen
dos números separados por una coma. El primero (8) es la longitud del
número completo y el segundo (3) indica el número de decimales que
tiene. Para tratar campos en los que haya que escribir números reales
MySQL dispone también de diferentes tipos: FLOAT (de coma flotante) y
DOUBLE, que no exigen poner longitud. El primero soporta hasta 11
posiciones incluidas el signo - , el punto decimal, la parte entera y la
decimal. El segundo soporta hasta 20 posiciones.
 El campo stock es de tipo TINYINT, tiene una longitud de 4 y no puede
ser nulo. En el mismo sólo podremos registrar como máximo el valor 127
para saber las existencias de un producto.
 El campo descuento es de tipo SET, admite sólo los valores “S” o “N”, por
defecto toma “S” y no puede ser nulo. No precisa ponerle longitud. El
tipo ENUM se comporta de una forma similar al tipo SET y tiene la misma
sintaxis. Hay que observar cómo debe escribirse el conjunto de valores
que puede contener este campo: entre paréntesis, cada valor entre
comillas y separados unos valores de otros por una coma.

- 307 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

 El campo caduca es de tipo DATE, es decir que va a contener una fecha.


No hay que poner longitud. Para este tipo de datos MySQL dispone
además de los tipos TIME para la hora, minutos y segundos, DATETIME,
para la fecha y la hora y TIMESTAMP para el número de segundos
transcurridos desde el 1 de enero de 1970 (época Unix).
 El campo notas es de tipo TEXT. Este tipo de datos permite introducir
gran cantidad de información, de bastantes Mb, al igual que el tipo BLOB.
No hay que poner longitud.

3. Utilizar esta forma de trabajar resulta demasiado pesada, al tener que ir


escribiendo sentencia a sentencia.

Por eso, lo más cómodo y productivo es crear ficheros de texto, es decir, script
MySQL, que se guardan donde nos convenga con la extensión sql. En ellos se
escriben las sentencias MySQL que deseamos se ejecuten cuando sea
necesario.

Una vez escrito y guardado el fichero con la extensión sql, se puede ejecutar
de dos formas:

• Desde una ventana de comandos del sistema operativo, ejecutando


mysql.exe -u root y redireccionando hacia él el fichero sql. Por ejemplo,
supongamos que hemos creado el script creatabla.sql y que lo hemos
guardado en C:\cursoPHP5\alumnos. Nos situamos en una ventana de
comandos en el camino C:\XAMPP\mysql\bin y escribimos:

mysql -u root <C:\cursoPHP5\alumnos\creatabla.sql (Intro)

Si las sentencias son correctas, se ejecutarán y producirán los efectos


pretendidos. Si el fichero ejecutable estuviera en un camino y el fichero sql en
otro, hay que indicar el camino para que el sistema pueda hallar los ficheros
indicados.

Si las sentencias del fichero sql son muchas y se ejecutan seguidas de forma
que el resultado ocupa más de una pantalla, puede utilizarse el comando More
de la ventana de comandos para detener la ejecución en cada pantalla.
Escribir, entonces,

mysql -u root <C:\cursoPHP5\alumnos\creatabla.sql | More


(Intro)

De nuevo, reconocemos que este procedimiento no deja de ser pesado y


engorroso. Por eso, aconsejamos utilizar el siguiente.

• Desde el Cliente MySQL Workbench en la opción del Menú File/Open SQL


Script, abrimos el fichero sql y lo ejecutamos. Si no funciona correctamente,
podemos arreglarlo en el editor según los mensajes de error que se aparecen
en la parte inferior de la ventana.

- 308 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Utilizando MySQL Workbench puedes abrir el proyecto Ejemplo 1


(Almacén) de la Unidad 6. Estudia el código fuente y ejecútalo para mostrar
el resultado de su ejecución en el servidor MySQL.

Puede verse el fichero script MySQL con el que hemos creado la base de datos
“almacen” y sus tres tablas “productos”, “compras” y “clientes”. Como no es un
fichero de PHP, no puede interpretarse ni generar una página web, sino sólo
sirve para crear esta base de datos. En la Unidad siguiente aprenderemos a
hacerlo con funciones de PHP.

Con los ejemplos de esta Unidad, referidos todos a MySQL, sólo pretendemos
que el alumno asimile bien los principales contenidos sobre las bases de datos
y sus tablas.

Introducir registros en una tabla

Podemos insertar un registro en la tabla “productos” con la sentencia siguiente:

insert into productos values (0,"Pala",10.55,100,"S",


"2001-12-16","Fuerte y barata");

Otra forma de hacerlo es escribiendo en un fichero de tipo txt la información


anterior, por ejemplo, en el fichero datos_productos.txt, e incorporando los
datos de esta forma:

load data local infile "datos_productos.txt"


into table productos;

Utilizando MySQL Workbench puedes abrir el proyecto Ejemplo 2 (Datos


Almacén) de la Unidad 6. Estudia el código fuente y ejecútalo para mostrar
el resultado de su ejecución en el servidor MySQL.

Tanto en la tabla “productos” como en “compras” y en “clientes” hemos


introducido tres registros. Conviene que el alumno mire en el Ejemplo 2 el
código para ver cómo pueden completarse los valores de los diferentes
campos, sobre todo los de fecha y los numéricos, tanto enteros como reales. Si
ejecuta este script varias veces seguidas, se añadirán tres registros nuevos
cada vez con los mismos datos. Para comprobar que se han cargado los datos
correctamente en las tablas desde el Cliente MySQL Workbench hay que hacer
doble clic sobre el nombre de la tabla y luego pulsar el botón Execute [Control
+ Intro].

Seleccionar o consultar registros dentro de una tabla

La sentencia SELECT permite buscar y mostrar los datos de una tabla. Su


estructura es bastante rica y compleja. Por ello, aconsejamos a los alumnos
que consulten algún libro o dirección de Internet sobre el lenguaje SQL. Aquí
sólo vamos a abordar algunas sentencias, las más importantes, para poder
incorporar estas órdenes dentro de los scripts PHP en la Unidad siguiente. En

- 309 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

concreto, dentro del propio Cliente MySQL Workbench puede obtenerse ayuda
en inglés sobre los diferentes comandos que admite MySQL. Siempre que lo
necesite, el alumno puede consultarlo si no dispone de otro material que le
resulte más asequible:

Por ejemplo, en la sección SELECT, se indica la sintaxis siguiente:

SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
[PARTITION partition_list]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]

- 310 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Veamos cómo se usa esta orden en sus cláusulas más importantes y


frecuentes:

Aplicada a la base de datos “productos”, la sentencia

select codigo,nombre,caduca from productos;

muestra estos campos de todos los registros de la tabla citada.

Si queremos que la búsqueda sólo se realice entre los 50 primeros registros de


la tabla , podemos utilizar la cláusula limit así:

select codigo,nombre,caduca from productos limit 0,50;

Las órdenes siguientes pueden incorporarse en un fichero script MySQL de


texto e ir ejecutándose una a una como hemos indicado (File/Open SQL Script
en el Menú del programa) para poder ver el resultado. En el Ejemplo 3 hemos
colocado varias sentencias select con sintaxis variadas para que el alumno o
alumna pueda apreciar la selección de registros que se hace según las
cláusulas que integren su estructura.

Con la orden anterior se muestran estos datos:

codigo nombre caduca


1 Pala 2014-12-16
2 Azadón 2014-08-01
3 Cuerda de pita 100 metros 2014-08-01

Si queremos que aparezcan todos los campos, usamos la sintaxis

select * from productos;

Si queremos que aparezca el valor del campo caduca sin repeticiones,


podemos usar la orden

select count(distinct caduca) from productos;

Detrás de la cláusula select podemos indicar, como hemos visto, varios


argumentos diferentes para seleccionar los registros de la consulta:

1. El nombre de uno o de varios campos de una o de varias tablas.

2. El signo * para indicar que aparezcan todos los campos.

3. El operador distinct para eliminar de la consulta los registros duplicados.

4. Las funciones de agrupamiento count() para contar, sum() para suma y


avg() para hallar la media de un campo numérico.

- 311 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

5. Otras funciones, como max() para hallar el valor máximo numérico y min()
para buscar el mínimo.

En el Ejemplo 3 puede verse su sintaxis y los resultados de la cláusula select


aplicando diferentes sintaxis.

La cláusula from (desde) indica el origen de las tablas en las que está archivada
la información. Detrás de ella debe escribirse el nombre de la tabla o tablas,
separadas por comas, de las que se quiere obtener la información. Dentro de
ésta puede asignarse un alias o nombre más sencillo, breve y manejable con el
que deseamos referirnos en adelante a cada tabla. Por ejemplo, en las tablas
“productos” y “clientes” hay un campo denominado “nombre”. Para poder
identificar cada uno dentro de una misma cláusula select, debemos escribir:

select productos.nombre,clientes.nombre
from productos,clientes;

De una forma más breve, podíamos haber usado un alias para cada tabla así:

select P.nombre,C.nombre from productos P,clientes C;

La cláusula where (donde) se usa para seleccionar sólo los registros de una
tabla que cumplan una determinada condición. Por ejemplo, la instrucción

select * from productos where nombre=”Pala”;

mostrará todos los campos de la tabla “productos” que lleven como contenido
“Pala” en el campo nombre.

La condición puede ser compleja usando expresiones en las que intervengan


nombres de campos, valores constantes y operadores, como

select * from productos


where nombre="Pala" and stock>50 and precio_euros>10;

En este caso se mostrarán los registros de la tabla “productos” que contengan


"Pala" en el campo nombre y de los que haya en stock más de 50 ejemplares
cuyo precio_euros sea superior a 10 euros. Se pueden usar también alias
para referirnos a las tablas e incluir en la condición campos de diferentes
tablas.

Pueden utilizarse, igualmente, funciones dentro de las expresiones, como

select nombre,tipo
from clientes where year(alta)>2013;

donde mostramos sólo el nombre y el tipo de los registros de la tabla “clientes”


cuyo año de la fecha de alta sea posterior a 2013.

- 312 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

La cláusula group by (agrupados por) permite hacer una consulta sumaria, es


decir, en lugar de mostrase todos los registros, se agrupan los que tengan unas
mismas características y se muestra sólo cuántos son. Por ejemplo, la
instrucción

select descuento,count(*)
from productos group by descuento;

muestra sólo el número de registros de la tabla “productos” que tienen


descuento y el número de los que no lo tienen.

La cláusula having (si hay) permite limitar el número de grupos poniendo una
condición a la integración de los grupos. Debe usarse sólo detrás de group by
para insertar la condición. Por ejemplo, la instrucción

select descuento,count(*)
from productos group by descuento
having count(*)>1;

muestra sólo el número de registros de la tabla “productos” que tienen


descuento y que no lo tienen si son más de 1. Así pues, no aparece ahora el
producto que no tiene descuento, pues sólo hace un grupo de 1.

La cláusula order by (ordenar por) hace aparecer en la consulta los registros


ordenados por el campo que se indique. Por ejemplo, la instrucción

select * from productos order by nombre;

muestra los registros de la tabla “productos” ordenados por el campo nombre.


Por defecto, se ordenan de forma ASCendente (de menor a mayor en el código
ASCII), pero podemos ordenarlos también al revés añadiendo la cláusula
DESC. Si ahora escribimos

select * from productos order by nombre desc;

los registros de mostrarán ordenados de mayor a menor (en el código ASCII).

También es posible mostrar los registros ordenados por un segundo campo


cuando hay coincidencia de dos o más registros en el primero. Por ejemplo, la
instrucción

select * from productos order by nombre,stock;

en el caso de que hubiera dos o más productos con el nombre “Azadón”,


mostraría éstos ordenados según el número, de menor a mayor, del campo
stock.

Desde la versión 4.0 del servidor MySQL es posible también utilizar las
Subqueries (subconsultas). Es decir, utilizar el resultado de una consulta dentro
de otra. Por ejemplo, la instrucción

- 313 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

SELECT * FROM clientes


WHERE clientes.codigo IN (SELECT compras.codigo_cliente from compras)

obtiene todos los registros de la tabla “clientes” que tengan dado de alta algún
registro en la tabla “compras”.

Además, desde la versión 4.0 del servidor MySQL también es posible también
utilizar las JOINS (uniones). Las joins son básicamente la combinación de dos
o más registros de diferentes tablas usando alguna sentencia de comparación.
Por ejemplo, la instrucción siguiente muestra el mismo resultado que la anterior

SELECT * FROM clientes


LEFT JOIN compras ON clientes.codigo = compras.codigo_cliente

Como suele ser muy común confundirse con las distintas combinaciones que
se pueden realizar en las consultas entre varias tablas, vamos a aclarar las
diferencias entre cada una.

Existen las combinaciones internas de tablas donde cada registro de la tabla


A se combina con otro de la tabla B que cumpla las condiciones.

Por ejemplo, seleccionamos todos los registros de la tabla clientes que tengan
algún registro dado de alta en la tabla compras:

SELECT * FROM clientes, compras


WHERE clientes.codigo = compras.codigo_cliente;

Esta consulta anterior se podría haber expresado de forma explícitamente así:

SELECT * FROM clientes


INNER JOIN compras ON clientes.codigo = compras.codigo_cliente

Ambas consultas anteriores muestran el mismo resultado:

Este tipo de combinaciones de tablas en las consultas suele ser la más


utilizada, pero si, por ejemplo, es necesario obtener un listado de todos los
clientes, que hayan realizado o no compras, entonces debemos realizar una
combinación externa de tablas:

SELECT * FROM clientes


LEFT JOIN compras ON clientes.codigo = compras.codigo_cliente;

- 314 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

De esta forma, se realizada un outer join por la izquierda, es decir, nos


traemos todos los registros de la tabla izquierda (clientes) tengan o no su
correspondencia con la tabla derecha. Por otro lado, si hubiéramos utilizado la
orden right join el resultado hubiera mostrado todos los registros de la tabla
derecha tengan o no su correspondencia con la de la izquierda. Aquellos
registros sin correspondencia entren en el campo de búsqueda mostrarán el
valor NULL (nulo). En este caso, el cliente Delos aparece con los campos
clientes.codigo y compras.codigo_cliente a null:

Si el alumno o alumna desea aumentar sus conocimientos sobre subqueries o


joins puede dirigirse al manual de MySQL donde se muestran la sintaxis y más
ejemplos.

Utilizando MySQL Workbench puedes abrir el proyecto Ejemplo 3


(Consultas Almacén) de la Unidad 6. Estudia el código fuente y ejecútalo
para mostrar el resultado de su ejecución en el servidor MySQL.

Aconsejamos al alumno que al ejecutar las sentencias SQL con el Cliente


MySQL Workbench haga clic con el botón derecho del ratón sobre las tablas
modificadas y, seguidamente, en la opción “Select Rows – Limit 1000”:

Así, desde esta última ventana podrás ir añadiendo y modificando el contenido


de los registros de las tablas “productos”, “compras” y “clientes”; luego, desde
esta ventana puedes ir viendo los resultados de las sentencias SQL:

- 315 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Actualizar los registros de una tabla

Para modificar el contenido de los registros de una tabla, hay que utilizar la
sentencia update , que tiene esta sintaxis:

update <nombre de la tabla> set <nombre del campo>


= <expresión>,...,... [where <condición>]

Por ejemplo, si queremos que en la tabla “productos” dentro del campo stock
se ponga el valor 120 en aquellos registros que contengan el valor 100,
podemos usar la instrucción

update productos set stock = 120 where stock=100;

Si no hubiéramos usado la condición en la cláusula where, se habrían cambiado


los valores del campo stock de todos los registros de la tabla.

Si ejecutas la sentencia anterior con MySQL Workbench verás que aparece el


siguiente error:

Error Code: 1175. You are using safe update mode and you tried to
update a table without a WHERE that uses a KEY column To disable safe
mode, toggle the option in Preferences -> SQL Queries and reconnect.

El error indica que la aplicación no permite modificar campos si no se indica en


la cláusula WHERE un campo de tipo clave. Para que se permita la ejecución de
esta sentencia SQL debemos acceder a la opción del menú “Edit ->
Preferences” y desmarcar la opción “Safe updates”:

- 316 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Nota: este error aparecerá también para algunas consultas siguientes que no
usan un campo clave para filtrar los registros mostrados.

También podemos cambiar el contenido de varios campos a la vez y usar


funciones y operaciones para modificar los campos. Por ejemplo, aplicada a la
tabla “clientes” la instrucción

update clientes set baja=now(),


deudas_euros=deudas_euros*1.10;

modifica el actual valor NULL del campo baja con la fecha y hora actuales, e
incrementa el campo deudas_euros en el 10 %, en todos los registros

Si desemos modificar los registros de varias tablas a la vez la sintaxis que


debemos usar es la siguiente:

UPDATE tabla1, tabla2 ...


SET nombre_columna1=expr1, nombre_columna2=expr2 ...
[WHERE condición]

- 317 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Utilizando MySQL Workbench puedes abrir el proyecto Ejemplo 4


(Actualizaciones Almacén) de la Unidad 6. Estudia el código fuente y
ejecútalo para mostrar el resultado de su ejecución en el servidor MySQL.

Si ejecutas el script SQL puedes ver el uso de la sentencia update y los


resultados aplicando diferentes sintaxis.

Borrar registros

La sentencia delete permite eliminar registros de una tabla. Su sintaxis es

delete from <nombre de la tabla> [where <condición>]

Si no se incluye la cláusula where, que es opcional, se eliminan todos los


registros. Por ejemplo, la instrucción

delete from clientes;

deja la tabla sin registros, pero no la elimina. No es frecuente eliminar todos los
registros de golpe. Por eso, casi siempre se utiliza la cláusula where para
seleccionar los registros que se desea eliminar. Por ejemplo, la instrucción

delete from clientes where deudas_euros=0;

elimina los registros de la tabla “clientes” que no tengan deudas. En cambio,

delete from clientes where codigo=1;

elimina el registro que tenga el número 1 como codigo.

Si desemos llevar a cabo una eliminación múltiple en varias tablas la sintaxis


que debemos usar es la siguiente:

delete <nombre de la tablas donde borramos los registros>


from <nombre de la tablas sobre la que hacemos consultas > [where
<condición>]

Por ejemplo, para eliminar los registros cuyo código de cliente es 1 tanto en la
tabla clientes como en compras escribimos:

delete compras, clientes from compras, clientes


where clientes.codigo=1 and
compras.codigo_cliente=clientes.codigo;

Utilizando MySQL Workbench puedes abrir el proyecto Ejemplo 5


(Borrado de Almacén) de la Unidad 6. Estudia el código fuente y ejecútalo
para mostrar el resultado de su ejecución en el servidor MySQL.

Si ejecutas el script SQL puedes ver el uso de la sentencia delete y los


resultados aplicando diferentes sintaxis.

- 318 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

NOTA: es importante tener en cuenta que las sentencias SELECT, UPDATE y


DELETE pueden ser utilizadas conjuntamente con subconsultas. Además,
todas estas sentencias permiten actuar sobre varias tablas a la vez.

Crear y destruir índices

Los índices están asociados al fichero de los datos y sirven para mantener en
orden los registros de una tabla.

Para cada tabla sólo puede haber un índice primario, que ordena los registros
por uno o más campos al ir introduciendo los registros en una tabla. Un índice
primario identifica los registros de una tabla de forma única. Si se observa las
tres tablas creadas por nosotros, “productos”, “compras” y “clientes”, puede
verse que hemos generado en todos los casos un índice primario por el campo
“codigo”, de forma que éste será el orden natural al ir introduciendo los
registros. Este campo se autoincrementa de forma que, según se van
añadiendo registros, cada uno va tomando un número consecutivo.

La cláusula primary key , incluida dentro de la sentencia create table , permite


crear un índice primario. También puede verse en el Ejemplo 1 cómo lo hemos
hecho en la instrucción siguiente de creación de la tabla “productos”:

create table if not exists


productos( codigo INT PRIMARY KEY AUTO_INCREMENT,
nombre VARCHAR(30) NOT NULL,
precio_euros DECIMAL(8,3) NOT NULL,
stock TINYINT NOT NULL,
descuento SET('S','N') DEFAULT "S" NOT NULL,
caduca DATE,
notas TEXT);

También pueden crearse ficheros de índice no primario, tantos como se


necesite. Este tipo de índices no identifica cada registro de forma única, sino
que dos o más registros pueden llevar la misma clave. Los ficheros de índice
no primario se crean tomando como clave de ordenación uno o más campos de
la tabla. Su sintaxis es la siguiente:

create [unique|fulltext] index <nombre del índice> on <nombre de la


tabla>(nombre del campo,... )

La opción unique debe usarse cuando queremos que sólo haya un registro con
la misma clave, de forma que, al introducir otro con la misma, no se permita
hacerlo. La opción fulltext sólo puede usarse con campos de tipo varchar y
text, e indica que se tome su texto completo como clave de ordenación. Si se
usan como claves campos de tipo char y varchar, se puede indicar una
longitud de la clave de ordenación, sin que sea necesario usar el campo
completo. Si se usan como claves campos de tipo blob y text, es
imprescindible indicar una longitud de la clave de ordenación.

- 319 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Por ejemplo, si queremos crear un fichero de índice denominado c_nombre en


el que se ordenen los registros de la tabla “clientes” por el campo nombre,
debemos escribir la instrucción

create index c_nombre on clientes(nombre);

Si hubiéramos querido usar como clave de orden sólo los 10 primeros


caracteres del campo nombre, deberíamos haber escrito la instrucción

create index c_nombre on clientes(nombre(10));

La sentencia drop index permite eliminar índices. Tiene esta sintaxis

drop index <nombre del índice>


on <nombre de la tabla>

Por ejemplo, si queremos eliminar el índice c_nombre, debemos escribir

drop index c_nombre on clientes;

Utilizando MySQL Workbench puedes abrir el proyecto Ejemplo 6 (Indices


Almacén) de la Unidad 6. Estudia el código fuente y ejecútalo para mostrar
el resultado de su ejecución en el servidor MySQL.

En este Ejemplo 6 se realizan diferentes operaciones de creación de índices,


de mostrar los índices asociados a una tabla y de eliminación de los mismos
aplicadas a las tablas “productos” y “clientes”.

Eliminar tablas y bases de datos

Para eliminar una tabla hay que usar la sentencia drop table, que tiene esta
sintaxis:

drop table [if exists] <nombre de la tabla>,...

Por ejemplo, si queremos eliminar la tabla “productos”, hay que usar la


instrucción

drop table if exists productos;

Para eliminar una base de datos hay que usar la sentencia drop database, que
tiene esta sintaxis:

drop database [if exists] <nombre de la base de datos>,...

Por ejemplo, si queremos eliminar la base de datos “almacen”, hay que usar la
instrucción

drop database if exists almacen;

- 320 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Utilizando MySQL Workbench puedes abrir el proyecto Ejemplo 7


(Eliminación Almacén) de la Unidad 6. Estudia el código fuente y ejecútalo
para mostrar el resultado de su ejecución en el servidor MySQL.

En el Ejemplo 7 se eliminan las dos tablas creadas en la base de datos


“almacen” y la propia base de datos. El alumno puede estudiar en ese código
sql cómo se aplican las instrucciones comentadas anteriormente.

Notas importantes

1. Los siete ejemplos de este apartado no son código php, por lo cual no
pueden interpretarse ni generar páginas web como hemos hecho hasta ahora.

2. Es muy importante ejecutar los ejemplos en orden, pues en ellos se sigue un


proceso lógico: primero se crea la base de datos “almacén” y sus tres tablas
“productos”, “compras” y “clientes” (ejemplo 1); luego, se incorporan tres
registros cada una de las veces que se ejecuta el ejemplo 2; en el ejemplo 3 se
utilizan diferentes sintaxis de la sentencia select para hacer consultas;
posteriormente, se eliminan registros (ejemplo 4); a continuación, se actualizan
los datos de los registros (ejemplo 5); seguidamente, se crean índices y se
destruyen (ejemplo 6); y, finalmente, se eliminan las tablas y la base de datos
(ejemplo 7). De ahí la necesidad de proceder de forma lógica al ir ejecutando
los citados ejemplos.

3. Por otra parte, la utilidad Cliente MySQL Workbench puede ayudarnos a ver
los datos y a comprender más intuitivamente lo que pasa en cada proceso.
Para ejecutar scripts complejos con varios comandos SQL seguidos de ";"
debes usar la opción del Menú File/Open SQL Script.

4. Finalmente, queremos insistir en que sólo hemos expuesto lo básico del


lenguaje SQL, debido a que el aprendizaje del mismo no es objeto de este
curso, sino que se supone que los alumnos y alumnas que se han matriculado
en este curso de PHP deben tener ya previamente asimilados los
conocimientos básicos necesarios de SQL para realizar el curso de PHP.

- 321 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

Resumen

Hay que saber al final de esta unidad

 Cómo es la arquitectura de una aplicación PHP que


utilice bases de datos y mediante qué dos tipos de
enlaces puede acceder el servidor a las bases de
datos.

 Los conceptos fundamentales de las bases de datos


relacionales: diferentes tipos de bases de datos
relacionales, organización de la información en
filas (registros) y columnas (campos),
características de cada campo (nombre, tipo,
longitud, si es la clave de un índice, etcétera).

 Las ventajas que aportan las bases de datos al


almacenamiento y manejo de la información que
contienen.

 Cómo se lleva a cabo el diseño correcto y eficaz


de una base de datos.

 Arrancar el servidor de datos MySQL, comprobar que


está activado y desactivarlo (echarlo abajo) al
acabar la sesión de trabajo del curso.

 Arrancar el programa "MySQL monitor" desde una


ventana del DOS y escribir desde su prompt las
sentencias SQL básicas para tratar las bases de
datos y las tablas.

 Arrancar la utilidad "Cliente MySQL Workbench",


conectarse al servidor de datos y manejar con
cierta soltura las principales opciones de este
programa que permiten crear bases de datos y
tablas, eliminarlas, acceder a la información de
las mismas y tratarla, etcétera.

 Crear, guardar, abrir y ejecutar Queries con la


utilidad anterior.

 Aplicar correctamente las principales sentencias


SQL para crear bases de datos y tablas, mostrar

- 322 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

las que haya creadas, usarlas, introducir


registros en las tablas, consultar su información,
actualizarlos, eliminarlos, crear y eliminar
índices, así como eliminar tablas y bases de
datos.

- 323 -
Curso de Iniciación a PHP: Unidad 6
- Servidor de Base de datos MySQL -

- 324 -
MÓDULO 3

PHP y las bases de datos (PDO)

Unidad 7

Índice de la unidad:

1. Funciones PHP – Bases de datos

2. Crear, seleccionar y destruir una base de datos

3. Realizar consultas en una base de datos

4. Modificar la información de una base de datos

5. Instalación y uso de MyODBD

6. Resumen
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Introducción
En esta Unidad vamos a aprender a conectarse al servidor que contiene el
gestor de bases de datos MySQL. Además, crearemos una base de datos,
nos conectaremos a ella y borraremos sus tablas e información, sabiendo
utilizar, además, las funciones que controlan los posibles errores.

Veremos cómo consultar una base de datos utilizando queries en las que
intervengan las principales funciones de PHP para acceder a bases de
datos de tipo MySQL y tratar su información.

También insertaremos, actualizaremos y eliminaremos registros de una


tabla, haciendo uso, además, de formularios y de celdas de tablas para
mostrar su información, preguntarla o seleccionar campos

Instalaremos y usaremos el controlador MyODBC para poder conectar


desde MS Access con las bases de datos de tipo MySQL, así como saber
importar o exportar tablas entre ambos gestores de bases de datos.

Finalmente, mantendremos una base de datos a través de funciones de


usuario aplicando las principales operaciones de este tipo: altas, bajas,
consultas, búsquedas, actualizaciones, etcétera.

Conexión con una base de datos


Ya hemos comentado en las Unidades anteriores que PHP permite acceder y
tratar la información de las principales bases de datos que hay en el mercado
actualmente: Oracle, MySQL, PostgreSQL, SysBase, Informix, etcétera. En la
Unidad anterior también hemos comentado que puede hacerlo tanto a través
de los programas nativos de la propia base de datos (API) como mediante una
conexión genérica de tipo OBDC o PDO.

En esta Unidad vamos a exponer y explicar, precisamente, cómo accede PHP


a MySQL y las funciones que permiten realizar operaciones con las bases de
datos, sus tablas y los datos que contengan: crearlas, introducir información,
actualizar ésta, eliminarla, elaborar informes a partir de la misma, etcétera. Así
pues, en esta Unidad se estudiarán las principales funciones de PHP
relacionadas con el servidor de datos MySQL.

La extensión PDO (PHP Data Objects) permite acceder a distintas bases de


datos utilizando las mismas funciones, lo que facilita la portabilidad. Haremos,
pues, uso de esta extensión PDO para acceder a bases de datos.

En esta misma Unidad, más adelante, estableceremos también una conexión


OBDC que nos permitirá acceder a las bases de datos de tipo MS Access.

Si los alumnos y alumnas del curso han comprendido y asimilado bien los
conceptos fundamentales sobre las bases de datos relacionales, explicados en

- 327 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

la Unidad anterior, y aprenden a manejar en esta Unidad las bases de datos de


tipo MySQL, estarán preparados sin duda para poder aplicar las funciones
correspondientes de otros tipos de bases de datos, que también incorpora el
lenguaje PHP.

En esta Unidad vamos a seguir un proceso similar al de la Unidad anterior,


llevando a cabo más o menos las mismas operaciones con las bases de datos,
pero en este caso usando las funciones de PHP.

Establecer una conexión con el servidor de bases de datos MySQL

Para realizar una conexión con una base de datos hay que crear una instancia
de la clase PDO, que se utilizará en todas las consultas posteriores. En todas las
páginas PHP en las que usen consultas a bases de datos es necesario
conectar primero con dicha base de datos.

Si no se puede establecer la conexión con la base de datos hay que comprobar


que la base de datos esté arrancada y funcionando correctamente y que las
credenciales del usuario sean correctas.

Para poder acceder a MySQL mediante PDO, debe estar activada la extensión
php_pdo_mysql en el archivo de configuración php.ini. El servidor XAMPP ya
trae por defecto activada esta extensión.

El constructor PDO() establece una conexión con el servidor de bases de datos


MySQL (u otro servidor de bases de datos compatible). Tiene la siguiente
sintaxis:

PDO (nombre del servidor [:puerto]


[, string usuario
[, string contraseña
[, array opciones ]]]
)

Esta función devuelve un objeto si se establece la conexión o se lanza una


excepción si no se consigue conectar.

Como hemos visto, para establecer una conexión con el servidor MySQL,
pueden utilizarse hasta cinco datos:

1. Servidor: nombre del equipo o dirección IP donde está la base de datos.


Por defecto, si no se pone nada, se asume el servidor “localhost”.

2. Puerto: vía por donde se accede a la base de datos. Si no se pone, por


defecto se asume el valor por defecto que es el “3306”.

3. Usuario: nombre del usuario que accede a la base de datos. Por defecto es
el que tenga el propietario del servidor. En el servidor XAMPP es “root”.

- 328 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

5. Clave: es la contraseña de acceso que tiene el usuario. Si no se pone, se


asume una cadena vacía.

6. Opciones: parámetro opcional que permite establecer ciertas


características de la conexión.

La conexión con el servidor se cierra cuando acaba de interpretarse el script


PHP. Puede cerrarse antes indicándolo explícitamente destruyendo el objeto
PDO.

Por ejemplo, si queremos establecer una conexión con el servidor “mihost”


utilizando el nombre de usuario “joseja”, la clave “garcia” y conectar con la base
de datos “mi_base_de_datos”, debemos escribir:

try {
$db = new PDO("mysql:host=mihost;dbname=
mi_base_de_datos;charset=utf8", joseja, garcia);
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$db->setAttribute(PDO::NULL_TO_STRING, true);
} catch (PDOException $e) {
die ("<p><H3>No se ha podido establecer la conexión.
<P>Compruebe si está activado el servidor de bases de
datos MySQL.</H3></p>\n <p>Error: " . $e->getMessage() .
"</p>\n");
}

Hay que tener en cuenta que, para que estos datos sean aceptados como
válidos, es necesario que el servidor se denomine así. Además, el nombre del
usuario, la clave y la base de datos deben haber sido dados de alta en el
servidor MySQL antes de pretender usarlos, ya que el servidor procede a
autentificar estos datos antes de permitir la conexión.

El método setAttribute(atributo, valor) de la clase PDO permite establecer


un atributo en la conexión a la base de datos. Puedes encontrar el listado
completo de atributos en el manual de PHP. Hay que tener en cuenta que
algunos de estos atributos dependen de la base de datos que estemos
utilizando en un proyecto en concreto.

Entre los más importantes podemos encontrar los atributos que controlan el
formato del nombre de los campos de la base de datos (PDO::ATTR_CASE) y el
tipo de errores que mostrarán las consultas a la base de datos
(PDO::ATTR_ERRMODE).

En el ejemplo anterior hemos los atributos siguientes:

 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY: permite realizar consultas


utilizando un buffer para almacenar los resultados. Es recomendable
usar este atributo, pues así podemos lanzar varias consultas al mismo
tiempo dentro del código PHP.
 PDO::NULL_TO_STRING: si el resultado de un campo es NULL entonces,
este valor se convierte a una cadena vacía.

- 329 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Ahora bien, como esta instrucción, si se consigue, devuelve un objeto que sirve
de conexión a la base de datos que después hemos de utilizar, lo mejor es
asignar a una variable el nombre de este identificador, de esta forma:

$db = new PDO("mysql:host=mihost;dbname=


mi_base_de_datos;charset=utf8", joseja, garcia);

IMPORTANTE: hemos añadido a la cadena de conexión el juego de caracteres


que se usarán en la conexión con la base de datos: charset=utf8. Hay que
tener en cuenta que el código fuente de los ejemplos del curso usa el juego de
caracteres UTF8 para que sea compatible con los diferentes sistemas
operativos disponibles en el mercado. Por lo tanto, para que los caracteres
especiales como tildes y la letra “ñ” aparezcan correctamente en el fichero final,
es necesario configurarlo de esta manera.

Por otra parte, puede ser que no se logre conectar, en cuyo caso se produciría
una excepción del tipo PDOException que contiene un mensaje en inglés. Para
optimizar un poco la salida en este caso, lo mejor es utilizar un bloque
try…catch y la función die(), para prescindir del mensaje del sistema, y
mostrar un mensaje personalizado, de esta forma:

try {
$db = new PDO("mysql:host=mihost;dbname=
mi_base_de_datos;charset=utf8", joseja, garcia);
...
} catch (PDOException $e) {
die ("<p><H3>No se ha podido establecer la conexión.
<P>Compruebe si está activado el servidor de bases de
datos MySQL.</H3></p>\n <p>Error: " . $e->getMessage() .
"</p>\n");
}

El método getMessage() de la clase PDOException permite obtener el mensaje


original devuelto por el servidor de base de datos y getCode() indica el número
de código interno del error.

Además, como lo más probable es que necesitemos usar sucesivas


conexiones, lo mejor es asignar sus valores a las datos de conexión,
guardarlas en un fichero de texto y, luego, con la sentencia include o require
importarlas al script correspondiente cuando se necesiten para establecer una
conexión.

Por ejemplo, creamos el fichero uni7_utilidades.php y guardamos en el


mismo este contenido:

<?php

/* Fijamos las constantes de la conexión al servidor MySQL.


El nombre del servidor es el que admite por defecto el servidor
local.*/

- 330 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

define("SERVIDOR", "localhost");
define("USUARIO", "root");
define("CLAVE", "");

/* Función que conecta con el servidor MySQL y, si se indica,


selecciona la BD indicada como parámetro.*/
function conectaBD($BD='')
{
/* Intentamos establecer una conexión con el servidor.*/
try {
if ($BD=='')
$db = new PDO("mysql:host=".SERVIDOR.";
charset=utf8", USUARIO, CLAVE);
else $db = new PDO("mysql:host=" . SERVIDOR .
";dbname=" . $BD.";charset=utf8", USUARIO, CLAVE);
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,
true);
return($db);
} catch (PDOException $e) {
die ("<p><H3>No se ha podido establecer la conexión.
<P>Compruebe si está activado el servidor de bases
de datos MySQL.</H3></p>\n <p>Error: " .
$e->getMessage() . "</p>\n");
} // end try
}
?>

Después, ya podemos establecer la conexión en el script correspondiente, de


esta forma:

<?php

require("uni7_utilidades.php");
$db = conectaBD();
?>

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 1 (Conexión


base de datos) de la Unidad 7. Estudia el código fuente y ejecútalo para
mostrar en el navegador su resultado.

En el Ejemplo 1 de esta Unidad puede verse cómo hemos usado el constructor


PDO() para establecer una conexión con el servidor MySQL. Para poder
ejecutarlo, es preciso arrancar el servidor MySQL antes de intentar establecer
una conexión. Ahora ya no es preciso arrancar la utilidad MySQL Workbench ni
conectarse mediante la misma.

Conexión a servidores que contengan otros tipos de bases de


datos

Aunque en este curso sólo se usa el gestor de base de datos MySQL, ponemos
a continuación ejemplos para mostrar cómo que se conectaría a otros tipos de
bases de datos de las que pudiera disponer particularmente el alumno. En todo

- 331 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

caso, consultando el Manual de PHP puede obtenerse información detallada


sobre estas funciones y conocer su sintaxis.

Base de datos Función para conectarse

PostgreSQL new PDO('pgsql:host=servidor;port=5432;


dbname=base_datos', usuario, contraseña);

SQLite new PDO("sqlite:/datos/basedeDatos.sqlite");

En estos dos tipos de bases de datos, se realizan a la vez dos operaciones:


conectarse al servidor y a la base de datos.

ODBC new PDO( 'odbc:Driver={Microsoft Access Driver (*.mdb)};


DBQ=C:\\ejemplo.mdb;Uid=usuario' );;

En el último apartado de esta Unidad aprenderemos a establecer conexiones


mediante el estándar ODBC y a acceder a los datos de bases de datos de tipo
Access.

SQL Server new PDO( 'mssql:host=servidor;dbname=base_datos',


usuario, contraseña);

Oracle new PDO( 'oci:dbname=//servidor:40251/base_datos',


usuario, contraseña );

- 332 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Crear, seleccionar y destruir una base de datos


PHP permite también crear, seleccionar y borrar bases de datos asociadas a
un identificador de conexión dentro del servidor al que se ha conectado.

Queremos hacer aquí una advertencia importante. Las operaciones de crear y


eliminar bases de datos y tablas dentro de éstas son más bien propias del
administrador del servidor y, por tanto, no es habitual que un usuario o cliente
pueda crearlas y destruirlas. En cambio, son operaciones más propias de un
cliente hacer solicitudes que permitan consultar y, como máximo, ampliar,
modificar o eliminar el contenido de una base de datos desde su navegador.

Es importante saber que si se borra una base de datos, ésta no sólo pierde el
contenido, sino que, después, no se pueden recuperar sus datos.

En este apartado vamos a estudiar las maneras de crear bases de datos y


destruirlas. Asimismo, veremos cómo podemos seleccionar una entre las
diferentes base de datos que haya en el servidor.

Crear una base de datos

Para crear una base de datos de tipo MySQL asociada a una conexión PDO,
hay que utilizar directamente una query, es decir, es necesario ejecutar una
consulta SQL.

Por ejemplo, si queremos crear la base de datos “pruebas” asociada a la


conexión $db del apartado anterior, podemos escribir

$db->query('CREATE DATABASE pruebas');

Para asimilar bien el método query(), hay que estudiarlo detenidamente en el


apartado siguiente, donde se aborda.

Como puede producirse algún error, es conveniente utilizar una estructura


condicional de la forma siguiente:

if ($db->query('CREATE DATABASE pruebas'))


{
print("<H3>La base de datos \"pruebas\" se ha creado
correctamente.<P>Con el explorador puedes observar que se
ha creado<P>la carpeta \"pruebas\" en
C:\\XAMPP\bin\mysql\data. </H3>");
}
else // Si no se ejecuta correctamente mostramos el error al usuario
{
echo"<H3>No se ha podido crear la base de datos
\"pruebas\". Errores: </H3><PRE>";
print_r($db->errorInfo());
echo "</PRE>";
}

- 333 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Hemos aprovechado la estructura condicional anterior para incluir un nuevo


método que puede servirnos en la gestión de errores cuando se produzcan
éstos en cualquier tipo de operación con una base de datos. Es la siguiente:

La función errorInfo() devuelve la información del error asignado por MySQL


correspondiente al error que se ha producido. Por ejemplo, si ya existe la base
de datos “pruebas” por haber sido creada antes, se indicará lo siguiente al
ejecutarse la cláusula else de la estructura anterior:

Array
(
[0] => HY000
[1] => 1007
[2] => Can't create database 'pruebas'; database exists
)

El índice 1 indica el nº de código de error y el índice 2 es el texto de error en


inglés de la base de datos MySQL.

Si empleamos acertadamente esta función para manejar y controlar los errores,


se pueden conocer y detectar, antes de solucionarlos, posibles problemas al
realizar diferentes operaciones con las bases de datos.

Eliminar una base de datos

Para eliminar una base de datos de tipo MySQL asociada a una conexión, de
nuevo, hay que usar usando una query, es decir, ejecutar una consulta SQL.

Por ejemplo, si queremos borrar la base de datos “pruebas” asociada a la


conexión actual, podemos escribir

$db->query('DROP DATABASE pruebas');

Recordamos que para asimilar bien el método query(), hay que estudiarla
detenidamente en el apartado siguiente, donde se aborda.

Es importante tener mucho cuidado al utilizar esta función, ya que, si se


ejecuta, se perderá la base de datos con sus tablas y toda la información que
contengan, sin que sea posible recuperarlas posteriormente.

También en este caso conviene utilizar una estructura de control condicional y


las funciones de control de errores, como hemos hecho y explicado al crear
esta base de datos.

Creación de tablas

Como hemos dicho, PHP no dispone de funciones para crear tablas dentro de
las bases de datos. Ésta es más bien una operación del administrador del
servidor que contiene la información. Por ello, quien necesite crear tablas

- 334 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

dentro de una base de datos ha de recurrir a scripts de tipo sql que puede
ejecutar mediante la utilidad MySQL Workbench. De todo ello hemos hablado y
realizado suficientes prácticas en la Unidad 6.

No obstante, en el apartado siguiente veremos que se pueden crear tablas


mediante una query, es decir, ejecutando una consulta. Por ejemplo, si dentro
de la base de datos “pruebas” queremos incluir la tabla “agenda”, podemos
hacerlo así:

$consulta = "create table agenda (registro INT NOT NULL


AUTO_INCREMENT, nombre CHAR(50),direccion CHAR(100),
telefono CHAR(15), email CHAR(50), KEY (registro) )”;

$db->query($consulta);

En la primera de las dos instrucciones anteriores asignamos a la variable


$consulta la sentencia sql de creación de la tabla “agenda” indicando el
nombre de ésta, así como el nombre de los campos, su tipo y longitud.
Además, fijamos como clave de índice el campo “registro”.

En la segunda instrucción ejecutamos la query, gracias a lo cual dentro de la


base de datos “pruebas” se crea la tabla “agenda” con la estructura
especificada. En el apartado siguiente encontrarás toda la información
necesaria sobre el método query().

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 1 (Conexión


base de datos) de la Unidad 7. Estudia el código fuente y ejecútalo para
mostrar en el navegador su resultado.

En el Ejemplo 1 de esta Unidad aparece el código donde se crea la tabla


indicada, así como las consultas anteriores utilizadas en este apartado.

- 335 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Realizar consultas en una base de datos


PHP permite también consultar la información que haya en las tablas de una
base de datos emitiendo con ella diferentes tipos de informes.

En este apartado vamos estudiar las funciones que permiten realizar consultas
y elaborar informes a partir de la información contenida en las tablas de una
base de datos. Concretamente, nos vamos a conectar a la base de datos
“biblioteca”, y a servirnos de su información para elaborar los informes y
realizar las queries (consultas) de este apartado.

Ahora necesitamos conocer y recordar las sentencias SQL que vamos a poner
como argumentos de las funciones de PHP. En la Unidad 6 se explicaron las
más importantes. Si el alumno tiene alguna duda sobre la interpretación de las
mismas, puede recurrir a los contenidos de la Unidad anterior o bien consultar
algún manual propio sobre SQL o buscar información en las direcciones de
Internet, indicadas en la Presentación del curso, que hacen referencia a este
lenguaje.

Consultar una base de datos

El método query() de la clase PDO envía una sentencia SQL al servidor para
que éste la interprete. Su sintaxis es ésta:

query(consulta)

Lo más recomendable es crear una variable y asignarle el texto de la consulta.


Después, pasamos esta variable como primer argumento del método query().

Por ejemplo, si queremos enviar al servidor una consulta de la base de datos


“biblioteca” en la que se muestren el título y el autor de los libros de la tabla
“libros”, debemos escribir

$consulta="select titulo,autor from libros";


$db->query($consulta);

La función query() devuelve False para indicar que la sentencia es incorrecta y


se ha ejecutado con problemas y el conjunto de resultados si se ha ejecutado
correctamente. Además, no indica el número de filas devueltas (en el ejemplo
anterior, registros de la tabla), aunque la sentencia SQL se ejecute
correctamente.

Como puede producirse algún error, es conveniente utilizar alguno de los


procedimientos ya conocidos: una estructura condicional y la combinación de la
función die(), como ya hemos explicado anteriormente.

Como puede verse en el Ejemplo 2, hemos preferido la siguiente sintaxis:

$resultado = $db->query($consulta);
if (!$resultado) {

- 336 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

$error=$db->errorInfo();
print "<p>Error en la consulta. Error ". $error[2] ."</p>\n";
} else {
echo "<P>Resultado Consulta de la tabla 'libros':<P>
<TABLE border=1><TR><TD>Título</TD><TD>Autor</TD></TR>";
foreach ($resultado as $valor) {
print "<TR><TD>$valor[titulo]</TD>
<TD>$valor[autor]</TD></TR>\n";
}
echo "</TABLE>";
}

Conviene observar que el método query() ejecuta la consulta si es correcta,


pero no devuelve por sí sola ninguna información al navegador del cliente. Por
eso, hemos asignado su resultado a la variable $resultado, que vamos a usar
como identificador de la consulta para mostrar, posteriormente el resultado con
un bucle foreach().

Así pues, debemos combinar el primer método (query()) con la segunda


(foreach()) para poder asignar la información de la consulta a diferentes
variables y, luego, poder mostrar éstas en la pantalla del cliente.

En la Unidad anterior ya explicamos que una tabla está estructurada en filas


(registros) y columnas (campos). Pues bien, al producirse la consulta, el
identificador devuelto por la misma es una especie de matriz bidimensional que
tiene en la primera dimensión tantas filas como registros se hayan visto
afectados y en la segunda, tantas columnas como se haya indicado. Por
ejemplo, en nuestra consulta anterior, que ejecuta la sentencia SQL select
titulo,autor from libros, sabemos que hay 28 filas (todos los registros de la
tabla “libros”) y 2 columnas (los campos indicados).

Podemos acceder a cualquiera de esos 56 datos indicando simplemente el


número de fila y el de columna, contando siempre desde 0 en adelante. Por
ejemplo, puede verse en las siguientes sentencias cómo se obtienen los dos
campos (título y autor) de los dos primeros registros de la forma siguiente:

$datos_resultado = $resultado->fetchAll();
echo $datos_resultado[0][0].' de '. $datos_resultado[0][1];
echo $datos_resultado[1][0].' de '. $datos_resultado[1][1];

En lugar del número de columna, podemos indicar directamente el nombre del


campo, como cadena, o bien el alias que le hayamos asignado. Por ejemplo,
podemos escribir también así la primera instrucción de asignación:

echo $datos_resultado[0]['titulo'].' de '.


$datos_resultado[0]['autor'];

o bien, si hubiéramos definido la consulta como select titulo,autor as a


from libros, podíamos haber escrito

echo $datos_resultado[0]['titulo'].' de '.


$datos_resultado[0]['a'];

- 337 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

En las explicaciones anteriores hemos utilizado el acceso individualizado a


cada uno de los datos de la consulta por motivos didácticos, para que el
alumno comprenda bien cómo se produce la consulta y el resultado que
genera. Cabe destacar que no conocemos el número de registros de una base
de datos MySQL hasta que hacemos una consulta sobre la misma.

A continuación, estudiaremos otro método que permite un tratamiento más


adecuado y una presentación más eficaz de la información resultante de una
consulta. Es el siguiente:

Mediante un bucle foreach() devuelve el contenido de una sentencia SQL en


un array identificando cada elemento con un campo de la tabla:

foreach ($resultado as $valor) {


print "<TR><TD>$valor[titulo]</TD><TD>$valor[editorial]</TD>
<TD>$valor[anno_publica]</TD><TD>$valor[paginas]</TD>
<TD>$valor[precio_euros]</TD></TR>\n";
}

La función fetch() devuelve el contenido de una sentencia SQL en un array


identificando cada elemento con un campo de la tabla. Extrae sólo una fila del
resultado como una matriz asociativa y mueve el puntero al registro siguiente.
Su sintaxis es ésta:

fetch()([tipo_resultado, [sentido_movimiento_puntero
[,cantidad_avance_puntero]]])

Si la función fetch() llega al final de los registros resultantes de la consulta


SQL entonces devuelve FALSE en lugar de la matriz con los datos.

Si dos o más campos del resultado tienen el mismo nombre, el último tiene
prioridad. Para acceder a los otros campos con el mismo nombre, hay que
especificar el índice numérico o definir un alias para esos campos. Por ejemplo,
en nuestra base de datos “biblioteca” las tres tablas tiene el campo homónimo
“registro”. Para que en la matriz resultante de la consulta se distingan los tres,
deberíamos escribir así la sentencia SQL:

select l.registro as lr, u.registro as ur, p.registro


as pr from libros l,usuarios u, prestamos p;

De esta forma, en la matriz resultante tendríamos una columna para lr (registro


de libros), otra para ur (registro de usuarios) y una tercera para pr (registro de
préstamos).

El segundo argumento, que es opcional, es una constante y puede tener los


valores siguientes:

- 338 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

 PDO::FETCH_ASSOC: el método devuelve un array indexado por los


nombres de las columnas del resultado de la consulta.

 PDO::FETCH_BOTH (predeterminado): el método devuelve un array


indexado tanto por nombre de columna como por número (el índice 0 es
la primera columna) devuelto por el resultado de la consulta.

 PDO::FETCH_BOUND: el método devuelve TRUE y asigna los valores de las


columnas del resultados de la consulta a variables de PHP vinculadas
mediante el método PDOStatement::bindColumn().

 PDO::FETCH_CLASS: el método devuelve un nuevo objeto de la clase


indicada como parámetro, haciendo corresponder las columnas del
resultado de la consulta con los nombres de las propiedades de la clase.

 PDO::FETCH_INTO: incluye un objeto en la conexión antes de realizar la


consulta a la base de datos. Es necesario hacer coincidir el nombre de
las columnas con los nombres de las propiedades de la clase.

 PDO::FETCH_LAZY: combina PDO::FETCH_BOTH y PDO::FETCH_OBJ, creando


un objeto con los nombres de las columnas como propiedades del
objeto.

 PDO::FETCH_NAMED: devuelve un array de la misma forma que


PDO::FETCH_ASSOC. En el caso de que hubiera múltiples columnas con el
mismo nombre, el valor al que hace referencia dicha clave será, a su
vez, un nuevo array con todos los valores de la fila de tuviera ese
nombre de columna.

 PDO::FETCH_NUM: devuelve un array indexado por el número de columna


comenzando por la columna 0.

 PDO::FETCH_OBJ: devuelve un objeto en el que los nombres de sus


propiedades corresponden a los nombres de las columnas devueltas en
el resultado de la consulta.

Por razones evidentes es muy interesante utilizar el método fetch().

En el Ejemplo 2 de esta Unidad podemos aplicar el método explicado


incluyéndole dentro de un bucle para recorrer todos los registros de la tabla.
Éste es el código que podemos emplear:

while ($fila = $resultado->fetch()) {


print "<pre>\n";
print_r($fila);
print "</pre>\n";
}

El resultado en la página será el siguiente:

- 339 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Array
(
[titulo] => El túnel
[0] => El túnel
[editorial] => Alfaguara
[1] => Alfaguara
[anno_publica] => 2000
[2] => 2000
[paginas] => 128
[3] => 128
[precio_euros] => 5.650
[4] => 5.650
)

Array
(
[titulo] => Instinto de Inez
[0] => Instinto de Inez
[editorial] => Alfaguara
[1] => Alfaguara
[anno_publica] => 2001
[2] => 2001
[paginas] => 189
[3] => 189
[precio_euros] => 20.550
[4] => 20.550
)

...

El método rowCount() devuelve el número de filas que se han vista afectadas al


ejecutarse una sentencia SQL. Por ejemplo, podemos mostrar el título, la
editorial, el año de publicación, el número de páginas y el precio de todos los
libros que sean de la editorial “Alfaguara”, ordenados por título, con el bucle
siguiente y mostrar al final el número de registros obtenidos en la consulta:

$consulta="select titulo,editorial,anno_publica,paginas,
precio_euros from libros where editorial='Alfaguara'
order by titulo";

$resultado = $db->query($consulta);
if (!$resultado) {
print "<p>Error en la consulta.</p>\n";
} else {
echo "<P>Resultado Consulta de la tabla 'libros':<P>
<TABLE border=1><TR><TD>Título</TD>
<TD>Editorial</TD><TD>Año publicación</TD>
<TD>Páginas</TD><TD>Precio</TD></TR>";
foreach ($resultado as $valor) {
print "<TR><TD>$valor[titulo]</TD>
<TD>$valor[editorial]</TD>
<TD>$valor[anno_publica]</TD>
<TD>$valor[paginas]</TD>
<TD>$valor[precio_euros]</TD></TR>\n";
}
echo "</TABLE></P>";
echo "<CENTER><H4>En la consulta anterior se han visto

- 340 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

afectados " . $resultado->columnCount() .


" campos.<P></H4></CENTER>";

El método getColumnMeta(columna) devuelve las características de la columna


(campo de la tabla en la base de datos) al ejecutar una sentencia SQL. Puede
observarse cómo hemos usado esta función en el código siguiente:

$consulta="select * from usuarios LIMIT 0";


$resultado = $db->query($consulta);
if (!$resultado) {
print "<p>Error en la consulta.</p>\n";
} else {
for ($i = 0; $i < $resultado->columnCount(); $i++) {
$col = $resultado->getColumnMeta($i);
print "<TR><TD> $col[name]</TD><TD>$col[table]</TD>
<TD>$col[native_type]</TD><TD>$col[len]</TD>\n";
}
echo "</TABLE></P>";
}

En el Ejemplo 2 puede ejecutarse el código completo de la consulta anterior.


Puedes ver que el método getColumnMeta() devuelve una matriz que tiene este
contenido:

Array
(
[native_type] => VAR_STRING
[pdo_type] => 2
[flags] => Array
(
[0] => not_null
)
[table] => usuarios
[name] => Nombre
[len] => 15
[precision] => 0
)

Así, podemos conocer las características siguientes de un campo (columna de


la consulta), que se devuelven como elementos de una matriz:

 name: Nombre de la columna.


 table: Nombre de la tabla a la que pertenece la columna.
 len: Longitud máxima de la columna.
 flags: matriz que indica otras características de la columna.
 native_type: Tipo de la columna.
 pdo_type: Tipo de la columna en formato PDO.
 precision: Devuelve la precisión del campo.

El conocimiento de estos datos puede ser necesario en ocasiones. En el


Ejemplo 2 (opción Propiedades y flags de algunos campos) puede verse
cómo mostramos en la pantalla las propiedades del campo “sueldo_euros” de
la tabla “usuarios”.

- 341 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

El método exec() de la clase PDO envía una sentencia SQL al servidor para
que éste la interprete y devuelva el número de filas que ha afectado la consulta.
Su sintaxis es ésta:

exec(consulta)

Es un método muy útil para conocer a cuántos registros ha afectado una


consulta que modifique o borre varios registros a la vez.

Por ejemplo, si queremos enviar al servidor una consulta de la base de datos


“biblioteca” en la que se borren los registros de la tabla “libros” de la editorial
“Alfaguara”, debemos escribir

$consulta="delete from libros where editorial='Alfaguara'";


$total=$db->exec($consulta);
echo "Se han borrado $total registros de la tabla 'libros'.";

La función exec() devuelve False para indicar que la sentencia es incorrecta y


se ha ejecutado con problemas.

IMPORTANTE: este método puede devolver el valor booleano False, pero


también puede devolver el valor 0 (ningún registro afectado) que se evalúa
como False. Para detectar la diferencia hay que utilizar el operador === para
comprobar el valor devuelto por este método.

Cómo utilizar ventanas, botones y tablas

En los ejemplos anteriores hemos ofrecido la información de las bases de datos


“a pelo”, es decir, mostrando sus datos tal cual. En este caso nuestra intención
ha sido que los alumnos y alumnas asimilen bien las funciones explicadas y su
sintaxis. Por ello, no nos hemos preocupado demasiado de la presentación en
la pantalla de su información.

Pero, habitualmente, se utilizan etiquetas HTML para formatear la salida de la


información, seleccionar algún dato o introducirlo desde la pantalla de nuestro
navegador usando formularios. Esto se consigue rellenando etiquetas:
ventanas desplegables (Select) y botones (Input) con los datos de uno o de
varios campos de una tabla de datos. Además, la información puede hacerse
aparecer dentro de las celdas de alguna tabla (Table), de forma que los
registros y campos se incluyan en el interior de éstas.

Veamos algunos casos prácticos que hemos incluido en el Ejemplo 4. Este


ejercicio es bastante complejo. Por ello, si encuentras dificultad en comprender
el código de algunas opciones, abórdalo en su totalidad cuando acabes el
estudio completo de esta Unidad.

<?php 
  // Dibuja un botón sencillo mediante una tabla HTML 
  function boton_ficticio($caption,$url) 
  { 
    return "<TABLE border=1 CELLSPACING=0 CELLPADDING=3 bgcolor=black> 

- 342 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

        <TR><TD bgcolor=\"white\"> 
          <FONT size =\"‐1\"> 
            <a href = \"$url\">$caption</A> 
         </FONT> 
         </TD></TR></TABLE>"; 
  } 
   
  /* Fijamos las constantes de la conexión al servidor MySQL. 
   El nombre del servidor es el que admite por defecto el servidor 
   local.*/ 
  define("SERVIDOR", "localhost"); 
  define("USUARIO", "root"); 
  define("CLAVE", ""); 
   
  class agenda { 
     
    protected $db; 
     
    function __construct($BD="") //Esto es el constructor 
    {       
      /* Intentamos establecer una conexión con el servidor.*/ 
    try { 
      if ($BD!='') 
      $this‐>db = new PDO("mysql:host=" . SERVIDOR .  
                            ";dbname=" . $BD .";charset=utf8", USUARIO,  
                            CLAVE, array(PDO::MYSQL_ATTR_INIT_COMMAND  
                                                => "SET NAMES 'utf8'")); 
        else  
      $this‐>db = new PDO("mysql:host=" . SERVIDOR.  
                            ";charset=utf8", USUARIO, CLAVE,  
                             array(PDO::MYSQL_ATTR_INIT_COMMAND  
                                               => "SET NAMES 'utf8'")); 
       
      $this‐>db‐>setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,   
                                                                     true); 
      // Indicamos como atributo que se debe devolver una cadena  
               // vacía para los valores nulos 
      $this‐>db‐>setAttribute(PDO::NULL_TO_STRING, true); 
      // Si no indicamos la BD es que hay que crearla de nuevo 
      if ($BD=='') { 
      // Ejecutamos la SQL de Creación de BD directamente 
          // en el servidor MySQL. 
      /* Intentamos crear la base de datos "ejercicios". 
       * Si se consigue hacerlo, se informa de ello. 
       * Si no, también se informa y se indica cuál es el 
       * motivo del fallo con el mensaje de error.*/ 
           $sql = file_get_contents('ejercicios.sql');        
         $this‐>ejecuta_SQL($sql); 
      } 
    } catch (PDOException $e) { 
      die ("<p><H3>No se ha podido establecer la conexión. 
          <P>Compruebe si está activado el servidor de  
                            bases de datos MySQL.</H3></p>\n <p>Error: " .  
                            $e‐>getMessage() . "</p>\n"); 
    } // end try 
  }//end function constructor 
   
  function __destruct() //Esto es el destructor 

- 343 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

  { 
    if (isset($db)) // Desconectamos de la BD 
      $db=null; 
     
  }//end destructor agenda 
   
  // Añadir un contacto a la lista 
  function add_contacto ($registro, $Nombre, $Apellidos,  
                         $Telefono_oficina, $Telefono_movil,$email,  
                         $direccion, $localidad, $provincia, $codigo_postal,  
                         $telefono, $notas)  
  { 
    if ($registro>0)  
      $sql_script = "UPDATE agenda SET  
                          Nombre='$Nombre', Apellidos='$Apellidos',  
            Telefono_oficina='$Telefono_oficina',         
        Telefono_movil='$Telefono_movil',email='$email',  
            direccion='$direccion', localidad='$localidad',  
            provincia='$provincia',      
          codigo_postal='$codigo_postal', 
            telefono='$telefono', notas='$notas' 
            WHERE registro=$registro"; 
      else 
        $sql_script = "INSERT INTO agenda (Nombre, Apellidos,  
                          Telefono_oficina, Telefono_movil, email, direccion,  
                          localidad, provincia, codigo_postal, telefono,  
                          notas) 
            VALUES('$Nombre', '$Apellidos', '$Telefono_oficina',  
              '$Telefono_movil','$email', '$direccion',  
          '$localidad', '$provincia',  
          '$codigo_postal','$telefono', '$notas')";     
   
         
      $this‐>ejecuta_SQL($sql_script); 
    }//end add_contacto 
     
    // Nº total de contactos 
    function nume_contacto () { 
        $sql_script = "SELECT * FROM agenda"; 
      $resultado=$this‐>ejecuta_SQL($sql_script); 
      // Devolvemos el nº de filas que devuelve la consulta 
        return $resultado‐>rowCount(); 
    } 
       
    // Borrar contactos 
    function del_contacto($id_to_del) { 
    $sql_script = "delete FROM agenda where registro=$id_to_del"; 
    $this‐>ejecuta_SQL($sql_script); 
    } 
     
    // Vaciar tabla contactos 
    function del_all_contacto() { 
    $sql_script = "delete FROM agenda"; 
    $this‐>ejecuta_SQL($sql_script); 
    } 
     
    // Añadir o modificar contactos 
    function introduce($id_to_edit, $ver) { 
         

- 344 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

  $campos=array(   
         0=>array(0=>"Nombre",1=>"Nombre",2=>15, 3=>30, 4=>""), 
         1=>array(0=>"Apellidos",1=>"Apellidos",2=>30, 3=>100, 4=>""), 
         2=>array(0=>"Telefono_oficina", 
               1=>"Teléfono oficina",2=>15, 3=>30, 4=>""), 
         3=>array(0=>"Telefono_movil", 
               1=>"Teléfono móvil",2=>15, 3=>30, 4=>""), 
         4=>array(0=>"email",1=>"e‐Mail",2=>40, 3=>200, 4=>""), 
         5=>array(0=>"direccion",1=>"Dirección",2=>30, 3=>150, 4=>""), 
         6=>array(0=>"localidad",1=>"Localidad",2=>30, 3=>100, 4=>""), 
         7=>array(0=>"provincia",1=>"Provincia",2=>30, 3=>60, 4=>""), 
         8=>array(0=>"codigo_postal",1=>"Cód. Postal",2=>5, 3=>5, 4=>""), 
         9=>array(0=>"telefono", 
                  1=>"Teléfono personal",2=>30, 3=>100, 4=>""), 
         10=>array(0=>"notas",1=>"Notas",2=>65, 3=>254, 4=>"")); 
          
       if ($id_to_edit>0) { 
         $sql_script = "SELECT Nombre, Apellidos, Telefono_oficina,  
             Telefono_movil, email, direccion, localidad,  
             provincia, codigo_postal, telefono, notas  
             FROM agenda where registro='$id_to_edit'"; 
      $resultado=$this‐>ejecuta_SQL($sql_script); 
               
        $filas = $resultado‐>rowCount(); 
        if ($filas==0) { //resultado query vacío 
          echo "<CENTER> 
            <TABLE BORDER=1 WIDTH=600 bordercolorlight='#FFFFFF'  
                bordercolor='#FFFFFF' bgcolor='#C0C0C0'> 
            <TR><TD ALIGN=CENTER VALIGN=CENTER> 
              <H2>No se encuentra ningún registro</H2> 
            </TD></TR></TABLE></CENTER>"; 
        } 
        else //la búsqueda no es vacía 
        { 
          $myrow = $resultado‐>fetchAll();; 
          for ($i=0; $i < count($campos); $i++) 
            $campos[$i][4]=$myrow[0][$i]; 
        } 
      }//end if $id_to_edit>0 
       
      if ($ver==0)  
        echo "<FORM name='form9' method='post'  
            action=\"index_agenda.php?operacion=exec_alta\">"; 
      echo "<TABLE BORDER='0' cellspacing='10' cellpadding='0'  
            align='center' width='600'>"; 
             
      for ($i=0; $i < count($campos); $i++){ 
        echo "<TR><TD bgcolor='teal' align=center width=140> 
          <FONT size=‐1 color='white'>".$campos[$i][1]."</FONT> 
          </TD><TD>"; 
        if ($ver==1)  
          echo "<FONT size=‐1><B>". $campos[$i][4]."</B></FONT>";  
        else echo "<input type='text' name='".$campos[$i][0]. 
                       "' size='".$campos[$i][2]."' value =  
                      \"".$campos[$i][4]. "\"  
                      maxlength='".$campos[$i][3]."'>"; 
        echo "</TD> 
        </TR>"; 

- 345 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

      }//for 
      echo "</TABLE><CENTER>"; 
       
      if ($ver==0) { 
        echo "<INPUT type='hidden' NAME='registro' value =  
                           '$id_to_edit'>"; 
        if ($id_to_edit>0) //estamos modificando 
          echo "<INPUT TYPE='SUBMIT' NAME='pulsa'  
              VALUE=\"Modificar contacto\">"; 
        else echo "<INPUT TYPE='SUBMIT' NAME='pulsa'  
              VALUE=\"Alta contacto\">"; 
      } 
      echo "</CENTER>"; 
      if ($ver==0) echo "</FORM>";   
       
   }//end Añadir o modificar contactos 
    
   // Buscar contactos 
   function buscar($lo_q_busco) { 
     if ($lo_q_busco!="")  
       $sql_script="SELECT * FROM agenda  
           WHERE apellidos like '%".$lo_q_busco."%'  
                 ORDER BY apellidos"; 
     else $sql_script = "SELECT * FROM agenda order by apellidos"; 
      
   $resultado=$this‐>ejecuta_SQL($sql_script); 
               
    $filas = $resultado‐>rowCount(); 
   
     if ($filas==0) { //resultado query vacío 
       echo "<CENTER> 
         <TABLE BORDER=1 WIDTH=650 bordercolorlight='#FFFFFF'  
           bordercolor='#FFFFFF' bgcolor='#C0C0C0'> 
         <TR><TD ALIGN=CENTER VALIGN=CENTER> 
           <H2>No se encuentra ningún registro</H2> 
         </TD></TR></TABLE></CENTER>"; 
     }else //la búsqueda no es vacía 
      
       echo "<TABLE BORDER='0' cellspacing='1' cellpadding='1'  
            align='center' width='650'> 
        <TR> 
          <TH bgcolor='teal'> 
            <FONT color='white'>Nombre</FONT> 
          </TH> 
          <TH bgcolor='teal'> 
            <FONT color='white'>Apellidos</FONT> 
          </TH> 
          <TH bgcolor='teal'> 
            <FONT color='white'>Teléfono</FONT> 
          </TH> 
          <TH bgcolor='teal' colspan='3'> 
            <FONT color='white'>Operaciones</FONT> 
          </TH> 
        </TR>"; 
    foreach ($resultado as $valor)  
    { 
      echo "<TR> 
      <TD><FONT size='‐1'><B>$valor[Nombre]</B></FONT></TD> 
      <TD><FONT size='‐1'><B>$valor[Apellidos]</B></FONT></TD> 

- 346 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

      <TD><FONT size='‐1'>  
                                <B>$valor[Telefono_oficina]</B></FONT></TD>  
      <TD>".boton_ficticio("Consulta","  
                           index_agenda.php?operacion=   
                      introduce&ver=1&nume=$valor[registro]#ancla")."</TD> 
      <TD>".boton_ficticio("Editar","index_agenda.php?operacion= 
                       introduce&ver=0&nume=$valor[registro]#ancla")."</TD> 
      <TD>".boton_ficticio("Borrar","index_agenda.php?operacion=
            borrar&nume=$valor[registro]")."</TD> 
      </TR>"; 
    } // end bucle 
    echo "</TABLE>"; 
  }//END function Buscar contactos 
   
  // Función que ejecuta una SQL 
   function ejecuta_SQL($sql) { 
    $resultado=$this‐>db‐>query($sql); 
    if (!$resultado) 
    { 
      echo"<H3>No se ha podido ejecutar la consulta:  
                             <PRE>$sql</PRE><P><U> Errores</U>: </H3><PRE>"; 
      print_r($this‐>db‐>errorInfo());          
      die ("</PRE>"); 
    } 
    return $resultado; 
  } // end ejecuta_SQL 
   
  }//END clase agenda   

?> 

En el código anterior puedes observar que creamos la base de datos


"ejercicios" mediante un fichero de texto que almacena la estructura de las
tablas y añade algunos registros a las mismas mediante las sentencias
siguientes:

$sql = file_get_contents('ejercicios.sql');
$this->ejecuta_SQL($sql);

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 4 (Agenda) de la


Unidad 7. Estudia el código fuente y ejecútalo para mostrar en el navegador
su resultado.

Si ejecutas este programa puedes ver una página que, mediante una clase
PDO se gestiona el contenido de una agenda almacenado en la base de datos
MySQL de XAMPP:

- 347 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

- 348 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Modificar la información de una base de datos


PHP permite también modificar la información que haya en una base de datos
actualizando los registros de sus tablas, introduciendo nuevos registros o
eliminando algunos de los que tengan éstas. Las operaciones mencionadas se
llevan a cabo también mediante consultas en las que se usan sentencias SQL.

En este apartado vamos estudiar las funciones y métodos que permiten


realizar consultas que modifican la información de las bases de datos. Nos
serviremos, también en esta ocasión, de la base de datos “biblioteca”, la misma
que hemos consultado en el apartado anterior

Insertar, actualizar y borrar registros de una tabla

La forma de insertar, actualizar o borras registros de una tabla consiste en


ejecutar consultas al servidor de bases de datos de igual forma que haríamos
con el cliente MySQL Workbench.

Por ejemplo, si queremos dar de alta un nuevo usuario, debemos enviar al


servidor una consulta de la base de datos “biblioteca” en la que se añada un
registro a los que haya en la tabla “usuarios”. Puede hacerse así:

$consulta="insert into usuarios


values ('".$_POST["nombre"]."','".$_POST["apellidos"]."',
'".$_POST["dni"]."','1962-09-10',
'".$_POST["domicilio"]."', '".$_POST["localidad"]."',
'".$_POST["provincia"]."',2000.000,
'".$_POST["telefono"]."','','',NULL)";
if ($db->query($consulta))
{
print("<CENTER><H3>El registro ha sido dado de alta
correctamente</H3></CENTER>");
}
else // Si no se ejecuta correctamente mostramos el error al usuario
{
echo"<CENTER><H3>No se ha podido ejecutar la
consulta.<P>Compruebe si la sintaxis de
la misma es correcta.<P></H3>Errores: </H3><PRE>";
print_r($db->errorInfo());
echo "</PRE></CENTER>";
}

Las operaciones de actualizar y borrar registros se llevan a cabo igualmente


mediante consultas SQL en las que se incluyen las sentencias UPDATE y
DELETE, respectivamente, tal como se han explicado en la Unidad anterior.

Consultas preparadas

Muchos tipos de bases de datos permiten utilizar consultas preparadas que


pueden definirse como un tipo de plantillas de SQL compiladas para que las

- 349 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

aplicaciones puedan ejecutar consultas personalizadas usando parámetros.


Las consultas preparadas ofrecen dos grandes beneficios:

 La consulta sólo necesita ser analizada (o preparada) una vez, pero


puede ser ejecutada múltiples veces con los mismos o diferentes
parámetros. Cuando la consulta está preparada, la base de datos
analizará, compilará y optimizará su ejecución. En el caso de
consultas complejas, este proceso llevar algo de tiempo y ralentizar
notablemente una aplicación web, sobre todo, si es necesario repetir
la misma consulta muchas veces con los mismos parámetros. Por lo
tanto, utilizar consultas preparadas, la aplicación PHP evita que el
servidor de bases de datos repita el análisis/compilación/optimización.
Además, las consultas preparadas usan menos recursos y se
ejecutan más rápidamente.
 Los parámetros para las consultas preparadas no necesitan estar
entrecomillados; PHP se encarga automáticamente de hacerlo. Esto
simplifica el código fuente y mejora el desarrollo seguro de
aplicaciones.

Las consultas preparadas son tan útiles que la biblioteca PDO de PHP las
puede emular para los tipos de bases de datos que no las admitan. Así, el
código fuente es compatible en todas los tipos de base datos soportadas por
PDO.

Cuando una consulta SQL se deba ejecutar en múltiples ocasiones, por


motivos de rendimiento, es recomendable crear un objeto PDOStatement con el
método prepare() de la clase PDO y ejecutarlo repetidamente, posteriormente
cuando haga falta, con el método execute().

Fíjate en el siguiente ejemplo que inserta varios registros en la tabla “usuarios”


de la base de datos “biblioteca”:

<?php

$consulta = "INSERT INTO usuarios (Nombre, Apellidos, DNI,


Fecha_nacim, Domicilio, Localidad, Provincia,
Sueldo_euros, Telefono, E_mail, Notas, Registro)
VALUES (:nombre, :apellidos, :dni, :fecha, :domicilio, :localidad,
:provincia, :sueldo, :telefono, :email, :notas,
:registro)";
$resultado = $db->prepare($consulta);

$resultado ->bindParam(':nombre', $nombre);


$resultado ->bindParam(':apellidos', $apellidos);
...

// Insertar un usuario
$nombre = 'Nombre 1';
$apellidos = 'Apellidos 1';
$resultado->execute();

- 350 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

// Insertar otro usuario con diferentes valores


$nombre = 'Nombre 2';
$apellidos = 'Apellidos 2';
$sentencia->execute();

?>

Mediante el método bindParam() asociamos a las etiquetas definidas en el


método prepare() las variables PHP que almacenarán el contenido de los
campos. Puedes observar que la consulta se crear una única vez, pero se
ejecuta 2 veces.

Aprovechando esta funcionalidad de PDO podemos mejorar la primera consulta


de este apartado de la siguiente manera:

$consulta = "INSERT INTO usuarios (Nombre, Apellidos, DNI,


Fecha_nacim, Domicilio, Localidad, Provincia,
Sueldo_euros, Telefono, E_mail, Notas, Registro)

VALUES (:nombre, :apellidos, :dni, :fecha, :domicilio, :localidad,


:provincia, :sueldo, :telefono, :email, :notas,
:registro)";

$resultado = $db->prepare($consulta);
// Esta parte del código se puede ejecutar de forma separada
if ($resultado->execute(array(":nombre" => $_POST["nombre"],
":apellidos" => $_POST["apellidos"],
":dni"=>$_POST["dni"],
":fecha"=>"1962-09-10",
":domicilio"=>$_POST["domicilio"],
":localidad"=>$_POST["localidad"],
":provincia"=>$_POST["provincia"],
":sueldo"=>"2000",
":telefono"=>$_POST["telefono"])))
{
print "<p>Registro creado correctamente.</p>\n";
} else {
print "<p>Error al crear el registro.</p>\n";
}

En este caso, no hemos utilizado el método bindParam() y, en su lugar,


definimos directamente en el método execute() mediante una matriz las
variables asociadas a los campos.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 3 (Inserción


datos en BD) de la Unidad 7. Estudia el código fuente y ejecútalo para
mostrar en el navegador su resultado.

- 351 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

En este Ejemplo 3 aparece el código completo de estas operaciones (insertar,


actualizar y borrar registros de una tabla). En el mismo puede verse cómo
hemos utilizado las funciones explicadas en este apartado.

En los Ejemplo 4 de esta Unidad hemos incluido una sencilla aplicación de


mantenimiento de una agenda, de forma que en ellas se incorporen y utilicen
las principales funciones abordadas en este apartado y en el anterior:

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 4 (Agenda) de la


Unidad 7. Estudia el código fuente y ejecútalo para mostrar en el navegador
su resultado.

Estudiando su código, leyendo los comentarios y tratando de reproducir


programas similares, el alumno o alumna del curso puede asimilar
adecuadamente los contenidos de esta Unidad.

También el modelo de Proyecto final se sirve, de una forma integrada, de


estas funciones con las que PHP nos permite conectarnos a un servidor,
acceder a una base de datos y tratar correctamente la información de las
tablas. Ya desde este momento, cada alumno o alumna debe estudiar este
proyecto e ir elaborando uno propio, que debe remitir al tutor o tutora antes de
presentarse a la prueba final presencial.

- 352 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Instalación y uso de MyODBC


Instalación y configuración

En este apartado se explica el proceso de instalación del controlador (driver)


MyODBC 32 bits para Windows (es posible utilizar este controlador en otros
sistemas operativos pero no se explica en este curso cómo se hace). Esto nos
permitirá acceder desde un cliente Windows que disponga de MS Access a un
servidor MySQL.

Suponemos que el gestor de datos Microsoft Access está ya instalado en el


ordenador donde se realiza el curso. Si no lo estuviera, sería imposible llevar a
cabo los pasos explicados a continuación.

Lo primero que debemos hacer es descargar la versión más actualizada de


este controlador, puede recogerse en la dirección siguiente
http://www.mysql.com/products/connector/:

En la siguiente página debes seleccionar el sistema operativo sobre el que


queremos instalar el controlador (Windows) y descargar siempre la versión de
32 bits:

- 353 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Pulsamos el botón “Download” y, en la página que aparece, hacemos clic en la


opción “No thanks, just start my donwload”:

Queremos advertir que el controlador MyODBC no se instala con el curso y, por


tanto, el alumno no lo hallará ya funcionando en el ordenador donde trabaje. Si
quiere conectar una base de datos de tipo MySQL desde MS Access, debe
instalar previamente el controlador tal como indicamos a continuación.

- 354 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Para convertir nuestro MS Access en un cliente Windows de MySQL, en primer


lugar debemos instalar el controlador ejecutando el fichero descargado (a fecha
de escritura de este documento se denomina mysql-connector-odbc-5.3.2-
win32.msi).

Una vez instalado el driver ODBC para MySQL, debemos ejecutar la utilidad
Configurar orígenes de Datos (ODBC) que se encuentra en el Panel de Control
de Windows:

Se mostrará la siguiente ventana:

- 355 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

MUY IMPORTANTE: si usas Windows con 64 bits, es necesario ejecutar la


utilidad Configurar orígenes de Datos (ODBC) de 32 bits que se encuentra en
el directorio C:\Windows\SysWOW64:

Para accedr a esta utilidad debes ejecutar la aplicación odbcad32.exe.

A continuación, dentro de la pestaña DNS de usuario, pulsamos sobre el botón


Agregar, para añadir un nuevo origen de datos y seleccionamos el driver
MySQL ODBC ANSI 5.3 Driver correspondiente a la base de datos MySQL:

Después, pulsamos el botón Finalizar apareciendo la siguiente ventana:

- 356 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Seguidamente, escribimos los valores siguientes, suponiendo, por ejemplo, que


vamos a conectarnos con la base de datos “biblioteca” del servidor MySQL y
pulsamos el botón OK:

• Data Source Name: nombre que daremos a la conexión. En nuestro ejemplo,


ponemos CursoPHP5.

• Server: es el nombre o dirección IP del servidor al que nos queremos


conectar. En nuestro ejemplo, ponemos localhost.

• User: nombre de usuario. En nuestro ejemplo, ponemos root.

• Password: clave del usuario. En nuestro ejemplo, lo dejamos en blanco.

• Database: nombre de la base de datos MySQL a la que queremos


conectarnos. En nuestro ejemplo, ponemos biblioteca.

Si pulsamos el botón “Test” podemos ver si la configuración realizada funciona


correctamente:

- 357 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Conexión remota a MySQL desde MS Access

Veamos cómo podemos conectarnos a una base de datos MySQL que está en
un servidor remoto usando un cliente Windows a través de MS Access. Para
poder hacerlo, es preciso tener instalado en nuestro cliente Windows el driver
MyODBC, así como haber arrancado el servidor MySQL.

Debemos seguir estos pasos:

1. Arrancar MS Access, en este caso usaremos Microsoft Access 2010 para


mostrar el ejemplo siguiente.

2. En el menú Archivo seleccionamos Nuevo, a continuación, pulsaremos en


Base de datos en blanco:

- 358 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

3. En la pestaña Datos externos pulsaremos en Base de datos ODBC:

4. Marcaremos Vincular al origen de datos creando una tabla vinculada:

- 359 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Así, Microsoft Access creará una tabla que mantendrá un vínculo a los datos de
origen. Los cambios realizados en los datos en Microsoft Access se reflejarán
en el origen y viceversa.

Pulsamos "Aceptar". Después, hacemos clic en la pestaña Origen de datos de


equipo y seleccionaremos el origen de datos "CursoPHP5" creado
anteriormente, pulsaremos de nuevo Aceptar:

- 360 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

5. MS Access conectará con el servidor MySQL y obtendrá todas las tablas


del origen de datos seleccionado. En esta ventana bebemos seleccionar las
tablas que queramos vincular con MS Access. Una vez seleccionadas las
tablas del servidor MySQL pulsaremos el botón Aceptar:

- 361 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

6. Una vez vinculadas las tablas de MySQL Server, podremos usarlas como si
de tablas MS Access se tratara. Por ejemplo, si hacemos clic sobre la tabla
"libros", en la parte derecha aparecerán sus registros. Cualquier modificación
que hagamos en la tabla quedará reflejado en el servidor:

Queremos recordar que para poder modificar las tablas desde MS Access
hay que tener los permisos pertinentes como usuarios de MySQL.

Creación informe en MS Access a partir de una base de datos MySQL

La gran ventaja de vincular tablas de MySQL Server con MS Access es que


podemos aprovechar todas sus funcionalidades y posibilidades con los datos
de MySQL Server. Por ejemplo, de forma mucho más sencilla que con MySQL
workbench, podemos crear macros con VBA, crear consultas, modificar tablas,
crear informes, etcétera.

A continuación mostramos, a modo de ejemplo, cómo crear un sencillo informe


con datos de una tabla de MySQL Server en MS Access.

Una vez hemos vinculado las tablas con MS Access, pulsamos en la pestaña
"Crear" y seleccionaremos "Asistente para informes". En esta ventana
seleccionamos los campos que deseamos incluir en el nuevo informe:

- 362 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Después, pusalmos el botón “Siguiente” y, si hemos elegido campos de


diferentes tablas, aparecerá este mensaje de aviso:

Si pulsamos el botón “Aceptar” podremos indicar las relaciones entre las 3


tablas bis_libros, bis_prestados y bis_usuarios:

Una vez creada la relación entre los campos de las diferentes tabla volvemos a
crear el informe y pulsamos el botón Finalizar:

- 363 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Finalmente, aparecerá un informe sencillo con todos los libros prestados en la


biblioteca:

Como puedes observar, es muy sencillo integrar la información de una base de


datos en MS Access y sacarle más partido a este servidor de base de datos. El
objetivo de este apartado es enseñarte cómo integrarlo, no a utilizar MS
Access. Si deseas ampliar conocimientos sobre MS Access, Mentor dispone
del curso correspondiente.

- 364 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

Resumen

Objetivos

 Saber conectarse al servidor que contiene el gestor de bases de


datos MySQL.

 Aprender a crear una base de datos, a conectarse a ella y a


borrarla con sus tablas e información, sabiendo utilizar, además, las
funciones que controlan los posibles errores.

 Aprender a consultar una base de datos utilizando queries en las


que intervengan las principales funciones de PHP para acceder a
bases de datos de tipo MySQL y tratar su información.

 Saber insertar, actualizar y eliminar registros de una tabla,


haciendo uso, además, de formularios y de celdas de tablas para
mostrar su información, preguntarla o seleccionar campos.

 Aprender a instalar el controlador MyODBC para poder conectar


bases de datos de tipo MS Access con las de tipo MySQL, así como
saber importar o exportar tablas entre ambos gestores de bases de
datos.

 Saber mantener una base de datos realizando a través de


funciones de usuario las principales operaciones de este tipo: altas,
bajas, consultas, búsquedas, actualizaciones, etcétera.

- 365 -
Curso de Iniciación a PHP: Unidad 7
- PHP y las bases de datos -

- 366 -
MÓDULO 3

Utilidades prácticas

Unidad 8

Índice de la unidad:

1. Funciones matemáticas

2. Tratamiento de errores

3. Compresión de ficheros

4. Crear documentos PDF

5. Resumen
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Introducción
En esta Unidad vamos a saber aplicar las principales funciones
matemáticas de PHP a las diferentes situaciones en que deban emplearse:
trigonométricas, para hallar redondeos, máximos y mínimos, para calcular
exponentes y logaritmos, así como para generar números aleatorios.

Aprenderemos a detectar y corregir los principales errores de un script,


utilizando eficazmente las funciones de PHP que permiten conocer la severidad
del error mostrando al usuario un mensaje con el texto que sea adecuado a
cada situación.

Sabremos crear ficheros comprimidos, abrirlos, cerrarlos, leer su


contenido, total o en parte, así como mover el puntero de lectura-escritura por
sus diferentes bytes.

Finalmente, aplicaremos correctamente las funciones que permiten crear


documentos PDF en PHP.

Funciones matemáticas
A lo largo del curso hemos estudiado muchas funciones, si bien no ha sido
nuestra intención abarcar exhaustivamente todas las funciones de PHP. En
este apartado vamos a estudiar las funciones matemáticas de que dispone
PHP, al menos de una forma breve, para que así se conozca que existen y se
puedan utilizar cuando sea necesario.

El Manual de PHP aborda estas funciones y puede consultarse esta


información accediendo a este documento a través de la ayuda del Eclipse
PDT.

Funciones trigonométricas

Ejemplo de su
Función Devuelve
sintaxis
El arcocoseno del
acos(float) acos(120.678);
argumento en radianes
El arcoseno del
asin(float) asin(120.678);
argumento en radianes
El arcotangente del
atan(float) atan(120.678);
argumento en radianes
El coseno del argumento
cos(float) cos(120.678);
en radianes
El seno del argumento en
sin(float) sin(120.678);
radianes

- 369 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

El tangente del
tan(float) tan(120.678);
argumento en radianes

Redondeos, máximos y mínimos

Ejemplo de su
Función Devuelve
sintaxis
El valor absoluto (sin
abs(número) abs(-120);
signo) de un número
El valor entero
ceil(float) superior de un número ceil(120.678);
decimal
El valor entero
floor(float) inferior de un número floor(120.678);
decimal
max(120,240); Para
El valor mayor de los
max(números) tipos y argumentos
números dados
ver Manual.
min(120,240); Para
El valor menor de los
min(números) tipos y argumentos
números dados
ver Manual.
El valor de un decimal
round(120.678);
redondeado en la parte
round(float)
entera según lo
round(120.478);
habitual

Exponentes y logaritmos

Ejemplo de su
Función Devuelve
sintaxis
El valor de elevar e
(base del logaritmo
exp(número) natural= exp(3);
2.71828182845904) al
argumento número
El logaritmo del
log(número) log(120.678);
argumento número
El logaritmo en base 10
log10(número) Log10(120.678);
del argumento número
El valor de elevar num1
pow(num1,num2) pow(5,3);
a num2
El valor de la raíz
sqrt(número) sqrt(25);
cuadrada de número

- 370 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Generación de números aleatorios

Ejemplo de su
Función Devuelve
sintaxis
El mayor valor
getrandmax() getrandmax();
aleatorio generable
mt_rand();
Un valor aleatorio
mt_rand()
mejorado
mt_rand(100,500);
Introduce la
semilla del mt_srand((double)
mt_srand() generador de microtime()
números aleatorios *100000);
mejorado
El mayor valor
mt_getrandmax() aleatorio generable mt_getrandmax();
mejorado
rand();
rand() Un valor aleatorio
rand(500,1000);
Introduce la
srand((double)
semilla del
srand() microtime()
generador de
*1000000);
números aleatorios

Al generar números aleatorios, es conveniente seguir estos pasos:

1. Generar la semilla del número aleatorio, es decir, inicializar la búsqueda del


número aleatorio a partir de un valor. Para crear esta semilla, se usan las
funciones srand() y mt_srand(). Estas funciones llevan como argumento una
expresión que inicializa el buscador de números aleatorios. Las funciones
getrandmax() y mt_getrandmax() devuelven el número máximo posible en cada
caso, que es 32.767 y 2.147.483.647, respectivamente.

2. Crear el número aleatorio. Esto se hace con las funciones rand() y


mt_rand(). Si no se indica ningún argumento, el número generado estará
comprendido entre 0 y getrandmax() o mt_getrandmax(), respectivamente. Si
se especifican argumentos, han de ponerse los dos límites, inferior y superior,
entre los cuales debe buscarse el número aleatorio.

Formatear números

La función number_format() permite dar formato a un número en grupo de


miles. Tiene la siguiente sintaxis:

- 371 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

number_format(número,nº de decimales,separador de decimales,separador


de miles)

Si sólo se pone el primer parámetro, número se muestra sin decimales y con


una coma (,) entre cada grupo de miles.

Si se especifican dos parámetros, número se muestra con un punto (.) como


separador de los decimales y una coma (,) entre cada grupo de miles.

Si se especifican los cuatro parámetros, número se muestra con el carácter que


se indique en el tercer parámetro en lugar de con un punto (.) como separador
de los decimales y con el carácter que se indique en el cuarto parámetro en
lugar de con una coma (,) entre cada grupo de miles.

En el Ejemplo 1, dentro de Números aleatorios, se usa esta función


aplicándola a un número entero. Puede estudiarse su sintaxis en el mismo. De
la misma forma, se puede aplicar a un número decimal.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 1 (Funciones


matemáticas) de la Unidad 8. Estudia el código fuente y ejecútalo para
mostrar en el navegador su resultado.

- 372 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Tratamiento de errores
Al escribir el código de los programas es fácil cometer bastantes errores, sobre
todo cuando se está aprendiendo y no se conoce con exactitud la sintaxis de
los comandos. En este apartado vamos a enumerar los errores más frecuentes
para aprender a solucionar los problemas que se producen al ejecutar el código
de los scripts PHP. Además, estudiaremos algunas funciones de PHP que nos
ayudarán a detectar y a tratar los posibles errores de nuestros programas.

En la Unidad 7 ya hemos usado Excepciones que controlan los errores de la


ejecución del código que accede a la base de datos MySQL. Sin embargo, no
hemos usando las funciones de gestión de errores que estudiaremos a
continuación.

Si utilizamos acertadamente las funciones de que dispone PHP para manejar y


controlar los errores, se pueden conocer y detectar, antes de solucionarlos,
posibles problemas en el código PHP.

En el fichero de configuración php.ini se fijan, entre otras muchas cosas, las


condiciones de comportamiento de los mensajes de error que se generen al
ejecutarse un fichero script PHP.

Si abrimos el archivo php.ini con el Panel de Control de XAMPP:

Y buscamos concretamente, en la sección Error handling and logging se


contemplan los siguientes valores:

- 373 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

 display_errors=On. Se activa el envío de los mensajes de error a la


salida estándar, por defecto el monitor del cliente.

 error_reporting=E_ALL & ~E_DEPRECATED & ~E_STRICT. En el texto de


los mensajes de error se muestran todos los errores, avisos e
información disponible sobre ellos salvo los relacionados con funciones
obsoletas (DEPRECATED) y las recomendaciones de funciones y
estructuras mejorables (E_STRICT). En un entorno de desarrollo de PHP
es recomendable dejar la configuración así: error_reporting=E_ALL para
que aparezcan todos los errores PHP.

 log_errors=Off. Si se activara con el valor On entonces el envío de los


mensajes de error se haría al fichero al fichero indicado en la variable de
configuración error_log="C:\xampp\php\logs\php_error_log". Se trata
de un fichero de texto que podemos abrir y ver su contenido, que puede
ayudarnos mucho a solucionar un problema al depurar un programa. Ya
que puede llegar a ser muy grande, conviene eliminarlo de vez en
cuando, para que se inicie de nuevo ocupando menos y siendo más fácil
la localización de los errores que se citan.

En el propio fichero php.ini se explican, en inglés, los posibles valores de


configuración de los errores, así como lo que significa cada uno.

En el Manual de PHP se aborda este tema en el apartado Manejo y registro


de Errores. También puede consultarse esta información accediendo al
Manual desde de la ayuda de Eclipse PDT. En este apartado nosotros sólo
vamos a referirnos a los aspectos más importantes y sólo abordaremos las
funciones básicas.

Errores más frecuentes

A continuación, citamos los errores que se repiten con mayor frecuencia, según
nuestra experiencia:

1. Faltan las comillas.

Tanto en PHP como en HTML las comillas deben ir emparejadas. Si falta


alguna, la de apertura o la de cierre, en lugar de interpretarse el código, se
produce un error. En Eclipse PDT muestra un error y cambia a otro color el
texto próximo a este error, de forma que no es difícil apreciar cuándo falta
alguna de las dos comillas.

2. Comillas no protegidas.

Cuando dentro de una pareja de comillas necesitamos utilizar otras comillas o


bien, dentro de PHP, en las etiquetas HTML es preciso poner comillas, es
imprescindible proteger las interiores con el signo \, como hemos visto. De no
hacerlo así, PHP acabaría la pareja de comillas con la primera interior y se
produciría un error en la interpretación del resto. Por ejemplo, la instrucción

- 374 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

echo "Le llamó "gamberro"";

se interpreta como Le llamó . Hay que proteger las comillas interiores así:

echo "Le llamó \"gamberro\"";

o bien usar en la pareja interior comillas simples así:

echo "Le llamó 'gamberro'";

Este fallo es muy frecuente al incluir etiquetas HTML entre comillas dentro de
un literal PHP que va también entre comillas. No es correcto escribir

echo "<INPUT NAME="nombre" VALUE="$nombre"";

Hay que escribir

echo "<INPUT NAME=\"nombre\" VALUE=\"$nombre\"";

3. Falta el punto y coma (;) al final de una sentencia

Es un error bastante común. El colorido del Eclipse PDT también puede


ayudarnos a localizar dónde falta. Como PHP interpreta que la sentencia no ha
acabado, suele marcar el error en alguna de las líneas de código siguientes.

4. Falta uno o ambos códigos indicadores de PHP: <?php o ?>

Es otro error frecuente. No es habitual omitir alguno cuando en el script sólo


hay un indicador de inicio del código PHP y otro de cierre. Pero, cuando se
mezclan código HTML y PHP, sí puede omitirse uno con facilidad. Si se omite
el de apertura (<?php), no se interpreta como PHP el código que sigue y llega
al navegador del cliente tal cual, como si fuera HTML. Si se omite el segundo
(?>), se produce un error al tratar de interpretarse código HTML como si fuera
PHP.

5. Se omite el símbolo $ delante de una variable

Como esta característica no es propia de otros lenguajes de programación, no


es infrecuente quitar este símbolo que debe preceder a todos los
identificadores de variables y objetos. Si no se pone, se producirán diferentes
errores o bien el identificador será tomado como un literal dentro de una
cadena.

6. No aparece el símbolo $ en la pantalla

Cuando queremos mostrar el nombre de una variable dentro de una cadena, no


su valor, es preciso anteponer el signo \ delante del mismo para proteger el
símbolo y convertirlo en un carácter normal representable en la pantalla.

- 375 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

7. Variable sin definir

Como en PHP no es preciso declarar las variables, a veces es difícil saber si la


hemos creado o no. Si no lo está, se provoca un error en la ejecución del script.
O bien los resultados serán inesperados. Por eso, cuando se tiene duda, al
escribir el código, pueden usarse la funciones isset(), empty() u otras.

8. La página resultante aparece en blanco

Cuando ocurre esto, lo más probable es que el código HTML incluido en el


código PHP sea incorrecto. Por ejemplo, puede suceder que no se haya
cerrado alguna etiqueta, como <TABLE> con </TABLE>, o que se intente
cerrar una etiqueta que no tiene esta modalidad.

9. Confundir los operadores = y ==

Es un error también muy frecuente. Cuando se quiere comparar dos


expresiones para ver si son iguales, hay que utilizar el operador de
comparación ==. En cambio, para asignar el valor o resultado de la expresión
derecha a una variable que aparece a la izquierda, hay que utilizar el operador
de asignación =.

10. Omisión de uno de los dos elementos emparejados

Además de las comillas, hay otros componentes del lenguaje PHP que deben
abrirse y cerrarse, como las llaves {}, los paréntesis () y los corchetes []. Para
detectar esta posible omisión de uno de los dos elementos, generalmente el
segundo (cerrar), lo mejor es tabular (indentar) bien el código, de forma que
resulte fácil e intuitivo encontrar dónde se produce esta ausencia. El colorido
del texto en el Eclipse PDT también puede ayudarnos a detectar este error.

11. El intérprete PHP no lee el código del script

Este problema puede deberse a que Apache está mal configurado, que no es
nuestro caso, o a que la extensión del fichero en el que está archivado el
código no es php.

12. Sólo aparece la primera palabra al pasar un valor de un formulario

Si tenemos la instrucción

echo "<INPUT NAME=nombre dado VALUE=$nombre";

sólo aparece en el resultado la palabra nombre. Para que se vea nombre dado
es preciso escribir:

echo "<INPUT NAME=\"nombre dado\" VALUE='$nombre'";

13. El valor pasado a una URL llega incompleto

- 376 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Se produce este error cuando en la dirección que pasa a la URL aparece algún
espacio en blanco o una variable que lo contiene. Por ejemplo, la referencia

echo "<A REF='eje.php?nombre=$texto'>Enlace</A>";

puede producir un error si $texto contiene algún carácter no admitido, como un


espacio. Para evitar este error hay que poner

echo "<A HREF='eje.php?nombre=urlencode($texto)'>Enlace</A>";

14. Errores en la función checkdate()

Debemos tener en cuenta que en ésta y en otras funciones o expresiones que


lleven una fecha como argumento o parte de las mismas, el orden es
mes:día:año.

15. Alguna información aparece en inglés

Los días de la semana o los meses pueden aparecer en inglés si no se ha


especificado otra cosa mediante la función setlocale(). Puede mirarse cómo
se cambian estos valores en la Unidad 3, Tratamiento de fechas.

16. Al cargar una página nueva no pasan las variables de la anterior

Así se comporta PHP. Para que las variables de una página puedan pasar a
otra nueva es necesario que las pasemos explícitamente, sea como campo
(incluso oculto) de un formulario, sea como asignación dentro de una URL.

17. No se puede crear un fichero, escribir en él o eliminarlo

Debemos tener en cuenta que, para poder realizar operaciones de escritura, es


preciso tener los permisos adecuados. Éstos se consiguen a través de la
autentificación al entrar en un servidor. Si un cliente no se autentifica de forma
expresa e individual, en todo caso accederá al servidor como nobody, que es un
usuario de tipo genérico que, en el mejor de los casos, sólo puede ver
determinada información.

18. La variable $_SERVER["PHP_AUTH_USER"] aparece vacía dentro de


un script

El contenido de esta variable depende normalmente del tipo de autentificación


que el usuario consiga del servidor, externa o mediante PHP. Cuando un
usuario se identifica de manera externa usando un módulo de Apache entonces
es la variable $_SERVER["REMOTE_USER"] la que contiene la identificación,
mientras que la variable $_SERVER["PHP_AUTH_USER"] queda sin contenido y
sólo se rellena si se usan las funciones de PHP de autentificación. Nota: ver el
Ejemplo 4 de la Unidad 5.

19. El mensaje del error dice: Call undefined o Unsoported function

- 377 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Puede ocurrir este error cuando estamos llamando a una función no declarada
o declarada en otro fichero que no se incluye en el script actual. También
puede deberse a las opciones incluidas al compilarse los módulos de PHP. En
este caso, lo mejor es mirar qué librerías se han incluido en la versión de PHP
que estamos usando y con qué opciones explícitas se ha compilado.

Funciones de PHP para tratar errores

La función error_log() remite un mensaje de error al dispositivo que se


indique.

Ésta es su sintaxis:

error_log(mensaje,tipo de mensaje [,destino [,dirección de destino]])

Esta función envía un mensaje de error al fichero de tipo log de errores del
servidor web, a un puerto TCP o a un fichero diferente de log. El primer
parámetro (mensaje) contiene la cadena con el texto del mensaje de error. El
segundo parámetro (tipo de mensaje) indica el lugar al que debe dirigirse
mediante uno de estos cuatro valores:

1. 0 El mensaje se envía al registro de sistema de PHP, utilizando el


mecanismo de registro de sistema del Sistema Operativo o a un fichero,
dependiendo del valor de la directiva de configuración error_log de php.ini.

2. 1 El mensaje se envía por correo electrónico a la dirección del parámetro


destino. En tipo de mensaje hay que utilizar el cuarto parámetro (dirección de
destino).

3. 2 El mensaje se envía a depuración de PHP. En este caso el parámetro


destino especifica el nombre de host o la dirección IP.

4. El mensaje se envía al fichero destino.

La función () se usa para indicar el nivel de las incidencias que deben ser
registradas cuando se producen errores en la interpretación de un script.

Ésta es su sintaxis.

error_reporting([nivel])

El nivel se expresa mediante un número entero donde cada bit tiene su propio
significado. A continuación aparecen algunos de los valores posibles y su
significado:

Valor Tipo Error


Descripción de error
del bit interno
Error grave que impide seguir con la ejecución
1 E_ERROR
del script.
2 E_WARNING Aviso de error que no impide seguir con la

- 378 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

ejecución del script.


Aviso de error de sintaxis que impide seguir
4 E_PARSE
con la ejecución del script.
Aviso de un posible error que no impide seguir
8 E_NOTICE
con la ejecución del script.
Similar a E_ERROR, generado por el núcleo del
16 E_CORE_ERROR PHP. Una función no debe generar este tipo de
error
Similar a E_WARNING, generado por el núcleo
32 E_CORE_WARNING del PHP. Una función no debe generar este tipo
de error
Error generado por el script. Es como un
E_ERROR,
256 E_USER_ERROR excepto que es generado desde código PHP
usando la
función trigger_error().
Se muestran todos los errores y advertencias
2047 E_ALL
excepto los del nivel E_STRICT.
Advertencias en tiempo de ejecución que
indican sugerencias sobre cambios en tu código
2048 E_STRICT
para mejorar la interoperabilidad y mantener
la compatibilidad del mismo.

Notamos que en PHP 5 se ha aumentado esta lista para mostrar más tipos de
errores y poder encontrar los errores del código más fácilmente.

En la sección error_reporting del fichero de configuración php.ini aparece el


valor E_ALL, para que se muestren todos los errores. Si usamos la instrucción
echo error_reporting();, se devuelve el valor 32. Pero podemos cambiar este
valor indicando, por ejemplo, otro nivel de la forma siguiente:

error_reporting(7);

en cuyo caso se mostrarán los mensajes de error de los tres primeros niveles
(1+2+4). Si escribimos

error_reporting(15);

se mostrarán los mensajes de error de los cuatro primeros niveles (1+2+4+8).

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 2 (Errores PHP)


de la Unidad 8. Estudia el código fuente y ejecútalo para mostrar en el
navegador su resultado.

Si ejecutas este programa puedes ver una página que usa estas dos funciones
para detectar y controlar los errores de un programa estableciendo diferentes
niveles y procedimientos para mostrar y escribir los mensajes de error en
ficheros.

En este Ejemplo utilizamos la orden $ficheroLogs = ini_get('error_log')


para obtener el nombre del fichero de texto donde se almacenan los errores
que se define en el archivo php.ini.

- 379 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Es importante que estudies su código fuente y los ejecutes en Eclipse PDT


para ver el resultado que muestra:

- 380 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Compresión de ficheros
En este apartado vamos a estudiar la compresión y descompresión de ficheros
utilizando funciones de PHP.

Para poder comprimir y descomprimir ficheros necesitamos utilizar la librería


zlib de Jean-loup Gailly y Mark Adler, que permite leer y escribir archivos
comprimidos de tipo gz. Podemos recoger esta librería en la dirección
http://www.zlib.net/. En XAMPP esta librería ya viene compilada
internamente en PHP, por lo cual podemos servirnos de ella sin necesidad de
recogerla ni instalarla en nuestro ordenador.

El Manual de PHP aborda estas funciones en su apartado Compresión Zlib.


Los alumnos y alumnas que lo precisen pueden consultar esta información
accediendo a este documento a través de la ayuda de Eclipse PDT.

Recomendamos repasar las explicaciones dadas en la Teoría de la Unidad 4


sobre las funciones de PHP para realizar diferentes operaciones con ficheros.
Así se comprenderán mejor algunos conceptos abordados en este apartado

Funciones de PHP para comprimir y descomprimir ficheros

Para abrir y cerrar ficheros

La función gzopen() permite abrir un fichero gzip en el que se va a escribir de


forma comprimida.

Ésta es su sintaxis:

gzopen(nombre del fichero,modo[,incluir path])

La función gzopen() devuelve un puntero, que es un número entero, del archivo


abierto. Después, al realizar operaciones de lectura o de escritura relacionadas
con este fichero, hay que citar este descriptor de archivo. Si la apertura falla,
esta función devuelve el valor False.

El segundo parámetro indica si el fichero ha de abrirse en modo de sólo lectura


(“r”) o en modo de escritura (“w”). En este parámetro pueden usarse los
mismos valores que en la función fopen(). Además, en esta librería se puede
indicar el grado de compresión, de 1 a 9. Por ejemplo, el valor “wb9” indica que,
al escribir, se utilice la máxima compresión posible. También se puede
especificar la estrategia con la que se ha de comprimir: “f” para filtrado de
datos, “h” para comprimir usando sólo el método Huffman, etcétera. En la
página oficial sobre zlib puede hallarse más información sobre este parámetro
de estrategia. Por ejemplo, el valor “wb9f” indica que ha de escribirse con la
máxima compresión filtrando los datos.

Se puede usar también un tercer parámetro, que es opcional: si ponemos el


valor 1, estamos indicando que el fichero ha de buscarse también en la

- 381 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

trayectoria especificada en el parámetro include_path del fichero de


configuración php.ini.

La función gzclose() cierra un fichero gzip que se ha abierto correctamente


con la función gzopen().

Ésta es su sintaxis:

gzclose(puntero o descriptor válido del fichero abierto)

Devuelve True si la operación se realizó sin problemas y False si hubo errores.

Para saber dónde está el puntero o moverlo por el fichero

La función gzrewind() coloca el puntero de un archivo de tipo gzip al comienzo


del mismo. Al abrirse un fichero, el puntero queda situado al comienzo del
mismo, pero se mueve con las operaciones de lectura o escritura.

Ésta es su sintaxis:

gzrewind(puntero o descriptor válido del fichero abierto)

La función gzseek() busca una posición especificada y coloca el puntero de un


archivo de tipo gzip sobre la misma.

Ésta es su sintaxis:

gzseek(puntero o descriptor válido del fichero


abierto,número de bytes)

Por ejemplo, si el fichero tiene un tamaño de 1.024 bytes, la instrucción

gzseek ($id_fichero,850 );

coloca el puntero de lectura o escritura en el byte 850.

Si el archivo se ha abierto para lectura, la función se emula, ya que no se


comprime de hecho, si bien la operación es muy lenta. Si se ha abierto para
escritura, sólo se busca hacia delante y, en este caso, la función gzseek()
comprime el contenido saltado en una secuencia de ceros hasta que el puntero
alcanza la nueva ubicación.

Si la operación se completa sin problemas, esta función devuelve el valor 0; de


lo contrario, devuelve -1. Debemos tener en cuenta que no se produce ningún
error cuando la búsqueda alcanza la marca de final del fichero.

La función gzeof() comprueba si el puntero de un archivo de tipo gzip ha


alcanzado la marca de final de fichero.

Ésta es su sintaxis:

- 382 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

gzeof(puntero o descriptor válido del fichero abierto)

Devuelve True si el puntero está en la marca de fin del archivo o cuando ha


ocurrido un error. De lo contrario, devuelve False.

La función gztell() devuelve el número de bytes (desplazamiento del puntero


dentro del fichero) sobre el que está situado el puntero de un archivo de tipo
gzip.

Ésta es su sintaxis:

gztell(puntero o descriptor válido del fichero abierto)

Devuelve False cuando ha ocurrido un error al ejecutarse la función.

Para escribir dentro de un fichero en formato comprimido

Las funciones gzwrite() y gzputs(), que son idénticas en su funcionamiento,


escriben una cadena dada dentro de un fichero de tipo gzip en modo binario.

Ésta es su sintaxis:

gzputs(puntero o descriptor válido del fichero


abierto,cadena[,tamaño])

gzwrite(puntero o descriptor válido del fichero


abierto,cadena[,tamaño])

Si el parámetro opcional tamaño está presente, se detiene la escritura cuando


se alcanza el número de bytes (descomprimidos) indicado; o bien se deja de
escribir cuando se llega al final de cadena; lo que ocurra primero.

Para leer ficheros comprimidos

La función readgzfile() lee un fichero gzip, lo descomprime y lo escribe en la


salida estándar.

Ésta es su sintaxis:

readgzfile(nombre del fichero,[incluir path])

En realidad, devuelve sólo el número de bytes (descomprimidos) leídos del


archivo. Si ocurre algún error, devuelve False y muestra un mensaje de error, a
no ser que se use el operador @ delante.

Se puede usar también un segundo parámetro, que es opcional: si ponemos el


valor 1, estamos indicando que el fichero ha de buscarse también en la
trayectoria especificada en el parámetro include_path del fichero de
configuración php.ini.

- 383 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Las función gzfile() se comporta en la práctica como la función readgzfile()


anterior.

Las función gzread() lee un fichero de tipo gzip en modo binario.

Ésta es su sintaxis:

gzread(puntero o descriptor válido del fichero


abierto,tamaño)

La lectura se detiene cuando se alcanza el número de bytes indicado en el


parámetro tamaño; o bien finaliza cuando se llega al final del fichero, lo que
ocurra primero.

Las función gzgetc() lee un carácter de un fichero de tipo gzip. En concreto,


lee el carácter sobre el que esté el puntero de lectura-escritura.

Ésta es su sintaxis:

gzgetc(puntero o descriptor válido del fichero


abierto)

Las función gzgets() lee una línea de un fichero de tipo gzip.

Ésta es su sintaxis:

gzgets(puntero o descriptor válido del fichero


abierto,tamaño)

Devuelve una cadena (descomprimida) que tiene una longitud de tamaño-1


bytes, leída del archivo de tipo gzip apuntado por descriptor del fichero. La
lectura finaliza cuando se ha leído esta longitud o bien al encontrarse un salto
de línea o la marca de final de fichero, lo que ocurra antes.

Las función gzgetss() se comporta como la función gzgets() anterior, pero


intenta quitar cualquier etiqueta HTML o PHP del texto que se lee. Además,
permite usar un tercer parámetro, opcional, para indicar qué etiquetas en
concreto no deben ser extraídas.

Las función gzpassthru() lee desde la posición del puntero hasta el final de un
fichero de tipo gzip (el remanente) y escribe los resultados descomprimidos en
la salida estándar. Al acabar la lectura, el fichero leído queda cerrado.

Ésta es su sintaxis:

gzpassthru(puntero o descriptor válido del fichero abierto)

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 3 (Comprimir


ficheros) de la Unidad 8. Estudia el código fuente y ejecútalo para mostrar
en el navegador su resultado.

- 384 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Si ejecutas este programa puedes ver una página que, usado las funciones que
permiten crear ficheros comprimidos, así como descomprimirlos y leerlos. Fíjate
que, una vez ejecutado el proyecto, si lo actualizas con el atajo de teclas o [F5]
verás que aparece el fichero comprimido comprimido.txt.gz dentro de la
carpeta del proyecto que puedes abrir con cualquier programa de
descompresión de archivos:

- 385 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Crear documentos PDF


El lenguaje PHP dispone de funciones para crear documentos de tipo PDF
(Portable Document Format). En este apartado vamos a iniciarnos solamente
en el uso de las funciones más importantes para elaborar este tipo de
documentos.

PDF es un formato de archivo original de los sistemas de Adobe y sirve para


intercambiar documentos independientemente del software de la aplicación
original, del hardware y del sistema operativo. Puede contener documentos con
cualquier combinación de texto, gráficos e imágenes y visualizarse en cualquier
ordenador. Se necesita un lector, el Acrobat Reader, que puede bajarse desde:
www.adobe.es.

Así pues, para poder comprobar si el documento que hemos creado con las
funciones PDF de PHP está correctamente realizado, es preciso tener instalado
en nuestro ordenador alguna de las versiones del programa Acrobat Reader.
Hacemos notar que también existen otras aplicaciones gratuitas para abrir
documentos PDF en el mercado.

En el Manual de PHP se aborda este tema en detalle mediante la biblioteca


creada por Thomas Merz, que es gratuita si se utiliza con fines educativos y
puede bajarse de la dirección http://www.pdflib.com/. En el servidor XAMPP no
está instalada por defecto y es necesario que que el alumno o alumna tenga
que hacerlo previamente.

Instalación biblioteca PDFLIB en XAMPP

Para instalar la biblioteca PDFLib en XAMPP es necesario acceder a la página


anterior con el navegador y hacer clic en los enlaces que se muestran en la
siguiente imagen:

- 386 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

En la página anterior, debes descargar el fichero que corresponda a tu sistema


operativo (Windows, MAC o Linux) y guardarlo en tu ordenador.

A continuación, vamos a obtener información sobre la distribución de XAMPP


que estemos usando para, así, poder instalar la versión correcta. Abrimos el
Panel de Control de XAMPP y hacemos clic en el botón “Admin”:

- 387 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Seguidamente, se abrirá un navegador con la siguiente ventana:

Si hacemos clic sobre el enlace “phpinfo()” podemos ver la página siguiente


que da la información de la distribución PHP utilizada:

- 388 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Debemos anotar la siguiente información:

- Versión PHP: en la captura anterior es 5.5.1.


- Sistema operativo: Windows 7 en este caso.
- Compiler: vemos en la imagen que es MSVC11 (Visual C++ 2012) el
compilador utilizado en esta distribución de PHP.
- Thread Safety: enabled indica que está activado el control de hilo
seguro.
- extensión_dir: directorio donde debemos instalar las extensiones
(bibliotecas) de PHP. En este caso es C:\xampp\php\ext.

- 389 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Después, abrimos el fichero comprimido que hemos descargado de la página


que distribuye la biblioteca y accedemos al subdirectorio “php\bind” donde
podemos encontrar todas las versiones compiladas de esta biblioteca para este
sistema operativo (Windows):

En este caso, debemos seleccionar el subdirectorio que corresponda con la


versión que estamos utilizando de PHP (en el presente caso es la 5.5: php-
550*), el compilador (VS11 de MSVC11) y que sea Thread Safety, es decir, que
el nombre del subirectorio no contenga el texto “nozts” (ZTS quiere decir
ZendThread Safety). En este caso, corresponde abrir el subdirectorio php-
550_VS11.

En el caso de trabajar en un ordenador de tipo Linux/MAC encontrarás la


bilioteca en el subdirectorio siguiente del fichero comprimido: bind/php/php-
<versión_PHP>/php_pdflib.so.

Una vez identificado el fichero php_pdflib correspondiente a nuestro sistema


operativo y versión de PHP, lo copiamos a la carpeta de bibliotecas indicada en
el campo extension_dir del archivo PHP.ini que hemos obtenido
anteriormente. En este caso, es el directorio C:\xampp\php\ext (en el caso de
Windows).

- 390 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Finalmente, modificamos fichero php.ini para que incluya la biblioteca nueva:

extension=php_xmlrpc.dll
extension=php_xsl.dll
extension=php_pdflib.dll
// En el caso de Linux y MAC sería esta línea en lugar de la
anterior
extension=php_pdflib.so

Finalmente reiniciamos el servidor Apache y volvemos a acceder al Panel de


Control para ver en la página phpinfo() que la biblioteca está activa y
funcionando correctamente:

Solución a posibles errores

En Windows puede aparecer el siguiente error al reiniciar el servidor Apache:

- 391 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

En general, este error no aparecerá en un ordenaor Window ya que dispondrá


de la bibliotecas de ejecución de C++ de Microsoft. Si ocurre este error, será
necesario copiar el archivo “msvcp110.dll” que se encuentra en
“C:\xampp\php” al directorio C:\Windows para solucionar el problema.

Algunas versiones de Linux x86 puede mostrar el siguiente mensaje de error al


reiniciar el servidor Apache de XAMPP:

Warning: PHP Startup: Unable to load dynamic library


'/opt/lampp/htdocs/test/pdf/pdflib/bind/php/php-
530/php_pdflib.so' - /opt/lampp/lib/libgcc_s.so.1: version
`GCC_4.2.0' not found (required by /usr/lib/libstdc++.so.6) in
Unknown on line 0

En este caso, es necesario deshabilitar (comentando con el carácter #) en el


archivo "bin/envvars" las siguientes dos líneas:

#binbuild LD_LIBRARY_PATH="/opt/lampp/lib/:$LD_LIBRARY_PATH"
#binbuild export LD_LIBRARY_PATH

Notamos que, si usas un sistema operativo Linux x64, XAMPP sólo está
disponible para 32 bits y, por lo tanto, debes instalar la versión de 32 bits de la
biblioteca PDFLib.

Incluso haciendo esto, puede aparecer el siguiente error sin consecuencias:

- 392 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Warning: PHP Startup: Unable to load dynamic library


'/opt/lampp/htdocs/test/pdf/PDFlib-8.0.4-Linux-php/bind/php/php-
530/php_pdflib.so' - libstdc++.so.6: wrong ELF class: ELFCLASS64
in Unknown on line 0

Si usas el sistema operativo Apple OS X (MAC) en un ordenador de tipo Intel


con XAMPP instalado, aparece este mensaje de error al ejecutar el servidor
Apache:

dyld: NSLinkModule() error


dyld: Symbol not found: __cg_jpeg_resync_to_restart
Referenced from:
/System/Library/Frameworks/ApplicationServices.framework/Version
s/A/Frameworks/ImageIO.framework/Versions/A/ImageIO
Expected in: /Applications/xampp/xamppfiles/lib/libjpeg.62.dylib

En este caso, es necesario deshabilitar (comentando con el carácter #) en el


archivo "xamppfiles/bin/envvars" la siguiente línea:

#DYLD_LIBRARY_PATH

Uso de biblioteca PDFLib en PHP

Veamos a continuación las principales funciones de PHP para crear


documentos de tipo PDF.

Abrir y cerrar un fichero de tipo PDF

Para utilizar ficheros PDF en php usando esta librería es necesario definir
primero un objeto que será el que, con sus propiedades y funciones, nos
permita crear y abrir este tipo de ficheros. La clase en cuestión se llama
pdf_new, y para usarla debemos escribir:

$pdf = new PDFlib();

El método begin_document de la clase PDFlib permite abrir un nuevo


documento de tipo PDF. Tiene esta sintaxis:

begin_document(nombre del fichero pdf, listado de opciones)

Esta función devuelve TRUE o FALSE dependiendo de si se ha conseguido crear


el fichero o no.

Así pues, si queremos crear un nuevo documento PDF y archivarlo en el


fichero “prueba.pdf”, por ejemplo, debemos escribir las siguientes instrucciones:

$fichero_pdf= getcwd() . "\\prueba.pdf";


$pdf = new PDFlib();

- 393 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

if ($pdf->begin_document($fichero_pdf, "") == 0) {
die("<b>No se puede crear el fichero pdf: '$fichero_pdf'.
<br>Compruebe que no lo tiene abierto con otra
aplicación.</b> Error: ".$pdf->get_errmsg());
}

A partir de aquí el identificador del documento PDF que estamos elaborando es


el representado por el objeto $pdf.

El método end_document() permite cerrar un documento de tipo PDF. Tiene


esta sintaxis:

end_document(lista opciones)

Es imprescindible utilizarlo al acabar la creación del documento PDF, pues el


sistema no da por concluido el documento hasta que no se encuentra esta
orden.

Así pues, al final de nuestro script de creación de un documento PDF hemos de


incluir las instrucciones siguientes:

end_document("");

Si abres el código fuente de éste y de los siguientes ejemplos verás que


aparece la siguiente sentencia al crear el objeto del tipo PDFlib:

$pdf->set_parameter("textformat", "utf8");

Con esta orden indicamos que el formato del documento crear es UTF8. Hay
que tener en cuenta que el código fuente de los ejemplos del curso está
guardado con el juego de caracteres UTF8 para que sea compatible con los
diferentes sistemas operativos disponibles en el mercado. Por lo tanto, para
que los caracteres especiales como tildes y la letra “ñ” aparezcan
correctamente en el fichero final, es necesario configurarlo de esta manera.

Asignar información a un documento

Podemos asignar a un documento PDF algunas informaciones que después


podrán verse con Acrobat Reader.

El método set_info() permite asignar al documento PDF diversas


informaciones. Tiene esta sintaxis:

set_info(nombre del apartado, texto del apartado);

De esta forma podemos asignar al documento los campos Author (Autor),


Creator (Creador), Title (Título), Subject (Asunto), Keywords (Palabras clave)
y CustomField (Campo de usuario). Por ejemplo, escribiendo las instrucciones
siguientes

- 394 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

$pdf->set_info("Author", "Clodoaldo y David Robledo");


$pdf->set_info("Creator", "Mentor - CNICE - MECD - 2014");
$pdf->set_info("Title", "Confeccionar un documento PDF");
$pdf->set_info("Subject", "Prueba");
$pdf->set_info("Keywords", "Palabras de búsqueda");
$pdf->set_info("CustomField", "Ejemplo 4 - Unidad 8 - Curso Iniciación
de PHP 5");

podemos ver esta información abriendo el documento con Acrobat Reader,


fuera del navegador, en la opción Archivo – Propiedades. Aparece así:

Abrir y cerrar una página del documento

Antes de poder escribir en el documento, es preciso ir abriendo y cerrando


cada página en la que escribamos.

- 395 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

La función pdf_begin_page() señala el inicio de una nueva página en la que se


va a escribir fijando a la vez su tamaño. Tiene esta sintaxis:

begin_page_ext(ancho, alto, lista opciones)

Hay que tener en cuenta que los valores ancho (width) y alto (height) de la
página determinan el tamaño de la misma, que tendrá una anchura desde 0
hasta x y una altura desde 0 hasta y. Cuando queramos escribir, colocar una
imagen o dibujar una figura en una posición determinada dentro de una página,
será necesario indicar las coordenadas x,y dentro de estos límites. Además,
hay que tener en cuenta que al situar algo (texto, imagen, gráfico, etcétera) en
una página se empieza a contar como en la pantalla del ordenador: de abajo
arriba y de izquierda a derecha.

Por ejemplo, si abrimos una página con la instrucción

$pdf->begin_page_ext(0, 0, "width=a4.height height=a4.width");

tendrá la anchura y la altura de una hoja DINA4 (210 mm x 297 mm). Es este
caso hemos usado el parámetro “lista opciones” para incluir el tamaño de la
página.

Al crear el documento, podemos hacerlo todo lo grande o lo pequeño que


queramos, pues en la pantalla se puede ver con Acrobat Reader con el tamaño
que lo hayamos creado, hasta ciertos límites, claro. Ahora bien, si queremos
imprimirlo, debemos pensar en el tamaño del papel. Las medidas anteriores
definen una página de tamaño DINA4 (210 mm x 297 mm) que tendrán una
anchura de 595 y una altura de 842. Estos valores están expresados en
centésimas de pulgada (1 pulgada=2,54 cm).

Así pues, si tomamos como modelo el tamaño de página fijado anteriormente,


las coordenadas x,y de las esquinas son éstas: inferior izquierda = 0,0; inferior
derecha = 595,0; superior izquierda =0,842; superior derecha =595,842. Dentro
de ellas se puede incluir texto, gráficos, imágenes, etcétera. Los tamaños
estándar de página en puntos por pulgada se pueden ver en la siguiente tabla:

Tamaños de Página Comunes en Puntos por pulgada


Nombre Tamaño
A0 2380 x 3368
A1 1684 x 2380
A2 1190 x 1684
A3 842 x 1190
A4 595 x 842
A5 421 x 595
A6 297 x 421
B5 501 x 709
letter (8.5" x 11") 612 x 792
legal (8.5" x 14") 612 x 1008
ledger (17" x 11") 1224 x 792

- 396 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

11" x 17" 792 x 1224

La función end_page_ext() señala el final de una página. Tiene esta sintaxis:

end_page_ext(lista opciones)

Las dos funciones anteriores tienen que preceder y seguir, respectivamente, al


contenido de toda página que se incorpore al documento. En su interior se
escribirán las demás funciones que completen el contenido de la página, su
formato, tipo y tamaño de letra, gráficos, imágenes, etcétera.

Por ejemplo, con las dos instrucciones siguientes abrimos una página y la
cerramos:

$pdf->begin_page_ext(0, 0, "width=a4.width height=a4.height");


$pdf->end_page_ext("");

Escribir texto en un documento PDF

Para escribir un texto en un documento, en primer lugar, hay que especificar la


fuente con que debe aparecer el texto y su tamaño.

La función load_font() permite buscar la fuente que queremos usar. Tiene


esta sintaxis:

load_font(nombre de la fuente, código de la fuente, lista opciones)

El nombre de la fuente es una cadena, el código, a partir de la versión 2 de


pdflib, es también una cadena. Ésta puede tener los valores siguientes:
“builtin”, “pdfdoc”, “macroman”, “macexpert” y “winansi”. En el ejemplo de este
apartado usaremos este último, por ser el más apropiado para Windows. Esta
función devuelve un entero que identifica un tipo de fuente.

La función setfont() permite establecer la fuente y su tamaño. Tiene esta


sintaxis:

setfont(identificador de la fuente, tamaño de la fuente )

Por ejemplo, podemos fijar así la fuente y el tamaño:

$fuente = $pdf->load_font( "Times-Roman", "winansi", "");


$pdf->setfont( $fuente, 16);

También podemos cambiar el color de la fuente con la función setcolor(), que


tiene esta sintaxis:

setcolor(tipo, valor para el color rojo, valor para el color verde,


valor para el color azul, valor extra de color )

Por ejemplo, con los siguientes valores establecemos el color azul:

- 397 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

$pdf->setcolor("both", "rgb", 0.0, 0.0, 1.0, 0.0);

Si queremos escribir con el color negro, debemos poner la instrucción así:

$pdf->setcolor("both", "rgb", 0.0, 0.0, 0.0, 0.0);

Así pues, esta función controla el color mediante combinación rgb (red=rojo,
green=verde y blue=azul). Si se pone 0.0 en los tres argumentos, se obtiene el
color negro. Si se pone 1.0 en uno solo de los tres argumentos, se consigue el
rojo, el verde o el azul, respectivamente. El valor de cada argumento, si no es
0, puede estar comprendido entre 0.000001 y 1.0. Además, se pueden
combinar los tres colores básicos para obtener los colores complementarios.

Veamos ya cómo escribir un texto en el documento PDF.

La función pdf_show() permite escribir un texto en la posición actual del


puntero de escritura. Tiene esta sintaxis:

pdf_show(texto);

A abrirse un documento PDF, el puntero queda colocado en la posición 0,0


(coordenadas x,y). Por tanto, si ejecutamos esta función seguidamente, el texto
se escribe a partir de aquí. Pero, según vayamos elaborando el documento, el
puntero de escritura se irá desplazando, por lo que no sabremos muy bien
dónde va a aparecer el texto utilizando esta función. Así pues, no resulta
demasiado cómoda.

La función continue_text(), que hemos mencionado poco antes, es


prácticamente igual que la anterior. También permite escribir un texto en la
posición actual del puntero de escritura. Tiene esta sintaxis:

continue_text(texto);

Si bien tiene los mismos inconvenientes que pdf_show(), en cambio resulta


cómoda cuando tenemos que escribir un texto que ocupa varias líneas, pues
podemos fijar el espacio entre las líneas y luego utilizando esta función
consecutivamente escribiremos cada línea con la separación establecida.

La función que permite fijar varias de las características que va a tener el


documento es set_value. Por ejemplo, si queremos cambiar el espaciado entre
las líneas su sintaxis es:

set_value("leading", espaciado);

La distancia es un número entero entre 0 y el máximo asignado a la


coordenada y. En nuestro ejemplo, hemos creado una página de 842 de alto.

Hemos visto que es necesario controlar la posición del puntero si no queremos


que nuestra página PDF sea un verdadero galimatías y máximo exponente de
la pintura abstracta. La función que nos permite situar el puntero de escritura

- 398 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

en la posición en que necesitemos escribir es set_text_pos(). Su sintaxis


también es sencilla:

set_text_pos(coordenada x,coordenada y)

Una vez dada esta orden, ya podemos estar seguros de que la siguiente
escritura se producirá a partir de este punto.

La función show_xy() permite escribir un texto en la posición especificada por


las coordenadas x,y. Tiene esta sintaxis:

pdf_show_xy(texto, coordenada x, coordenada y)

Esta orden resulta más cómoda que las anteriores, pues permite a la vez
escribir un texto e indicar dónde debe aparecer. Ya hemos indicado que los
valores de las coordenadas deben estar dentro del rango asignado a la
anchura y a la altura de la página.

Otras funciones permiten adornar el texto usando la función set_value(), como


las siguientes:

 set_value("textrendering", modo) especifica cómo debe aparecer el texto.


Su segundo parámetro es el modo como debe presentarse cada letra. Los
valores más relevantes son: 0=compactas; 1=vacías con borde; 2=llenas con
borde; 3=invisibles.

 set_value("textrise", puntos) resalta el texto. El realce se indica en el


segundo parámetro con un número entero que especifica el número de puntos
que debe sobresalir el texto.

 set_value("charspacing", puntos) fija la separación entre las letras de un


texto. El segundo parámetro es un número entero que indica el número de
puntos con que deben separarse los caracteres del texto entre sí.

 set_value("wordspacing", puntos) fija la separación entre las palabras de


un texto. El segundo parámetro es un número entero que indica el número de
puntos con que deben separarse las palabras del texto entre sí. Si ponemos 0
en estas dos última funciones, se restablece el paso por defecto.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 4 (Funciones


PDF) de la Unidad 8. Estudia el código fuente y ejecútalo para mostrar en el
navegador su resultado.

Si ejecutas este programa puedes ver una página que muestra un enlace al
documento creado:

- 399 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Si haces clic en el enlace se abrirá el archivo PDF creado en el servidor:

En este Ejemplo puedes estudiar el código comentado para ver cómo hemos
usado las funciones que permiten crear este tipo de documentos.

Nota: al tratarse de una biblioteca de libre de uso para aprendizaje, se añade


automáticamente el texto “pdflib.com” en diagonal en la página. Para que
desaparezca este texto es necesario pagar una licencia de uso profesional.

Dibujar en un documento PDF

PHP nos permite también dibujar algunas figuras sencillas dentro de un


documento de tipo PDF. Veamos las principales funciones para hacerlo.

- 400 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

La función setlinecap() especifica cómo deben ser los extremos de una línea.
Tiene esta sintaxis:

setlinecap(valor)

El parámetro valor puede tener los valores siguientes: 0=unidos al final,


1=redondeados, 2=con su esquina proyectada.

La función setlinejoin() especifica cómo deben ser las esquinas de una línea.
Tiene esta sintaxis:

setlinejoin(valor)

El parámetro valor puede tener los valores siguientes: 0=en forma de ingletes,
1=redondeadas, 2=en ángulo oblicuo.

La función setlinewidth() especifica la anchura de una línea. Tiene esta


sintaxis:

setlinewidth(valor)

La función setlinedash() especifica el patrón de una línea. Tiene esta sintaxis:

setlinedash(unidades blancas, unidades negras)

Si ponemos 0 en los dos parámetros unidades, se dibuja una línea sólida.

La función que moveto() permite situar el puntero en la posición donde debe


aparecer el dibujo. Su sintaxis es sencilla:

moveto(coordenada x, coordenada y)

La función que rotate() permite hacer rotar el puntero. Ésta es su sintaxis:

rotate(grados que debe rotar)

Veamos ahora las figuras que se pueden dibujar dentro de un documento


PDF.

La función curveto() dibuja una línea curva según los puntos indicados. Tiene
esta sintaxis:

pdf_curveto(coordenada x1,coordenada y1,


coordenada x2,coordenada y2,
coordenada x3,coordenada y3)

La línea curva se inicia en el punto donde esté el puntero y acaba en x3,y3,


pasando por los puntos x1,y1 y x2,y2.

La función lineto() dibuja una línea recta según los puntos indicados. Tiene
esta sintaxis:

- 401 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

lineto(coordenada x, coordenada y)

La línea recta se inicia en el punto donde esté el puntero y acaba en las


coordenadas x,y.

La función circle() dibuja un círculo. Tiene esta sintaxis:

circle(coordenada x, coordenada y, radio)

El círculo tiene su centro en las coordenadas x,y y el radio que se especifica


en el parámetro radio.

La función arc() dibuja un arco. Tiene esta sintaxis:

arc(coordenada x, coordenada y, radio, inicio, final)

El arco tiene su centro en las coordenadas x,y y el radio que se especifica en


el parámetro radio. Se inicia en el ángulo señalado en inicio y termina en el
ángulo final.

La función rect() dibuja un rectángulo. Tiene esta sintaxis:

rect(coordenada x, coordenada y, anchura,altura)

El rectángulo tiene su esquina inferior izquierda en las coordenadas x,y.

La función closepath() cierra el camino actual. Tiene esta sintaxis:

closepath()

La operación “cerrar el camino actual” significa que se dibuja una línea desde el
punto actual hasta el punto donde se inició la primera línea.

La función stroke() dibuja una línea a lo largo de un camino. Tiene esta


sintaxis:

pdf_ stroke()

“Dibujar una línea a lo largo de un camino” significa que la línea tendrá la


longitud que se haya fijado antes con la función lineto().

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 5 (Reloj) de la


Unidad 8. Estudia el código fuente y ejecútalo para mostrar en el navegador
su resultado.

Si ejecutas este programa puedes ver que el navegador carga directamente el


fichero PDF creado:

- 402 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

En este Ejemplo 5 hemos añadido un reloj creando un documento de sólo dos


páginas, para que pueda verse cómo se usan las funciones de dibujo y los
efectos que producen.

Si abres el código fuente verás que usamos la excepción del tipo


PDFlibException que controla los errores que se puedan producir a la hora de
crear el archivo PDF.

Además, es interesante ver cómo hemos utilizado las cabeceras en PHP para
volcar al navegador del usuario con las siguientes sentencias:

// Obtenemos en un bufer el contenido del fichero PDF creado


$bufer=$pdf->get_buffer();
// Leemos el tamaño de este contenido
$len=strlen($bufer);
// Creamos una cabecera de tipo PDF y longitud len
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=reloj.pdf");

// Presentamos en la pantalla el resultado volcando el bufer. Como se


// trata de un documento PDF, se arranca el programa Acrobat Reader.
print $bufer;

- 403 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Incluir imágenes en un documento PDF

PHP dispone también de algunas funciones que permiten incorporar imágenes


de diferentes formatos en un documento PDF. Veamos brevemente cuáles son.

La función delete() libera los recursos reservados a un documento PDF. Se


comporta igual que la función end_document() salvo que libera de la memoria
del ordenador los recursos reservados antes de que el script finalice.

La función load_image() abre en el documento PDF un fichero de imagen. Esta


función lleva como argumentos, al menos, el tipo (formato) de imagen, el
nombre del fichero que contienen la imagen y la lista de opciones. Se utiliza de
la forma siguiente:

<?
$imagen=$pdf->load_image("jpeg",$fic_imagen,"");
if (!$imagen) {
die("No existe el fichero de la imagen ".$fic_imagen);
}
...
$pdf->fit_image($imagen,0,0, "");
$pdf->close_image($imagen);
?>

La función close_image() cierra una imagen abierta.

La función get_value() obtiene determinados valores numéricos. En el


Ejemplo 6 hemos obtenido la altura (imageheight) y la anchura (imagewidth)
de la imagen que hemos incorporado en el documento. Esta función lleva como
primer argumento el parámetro que buscamos, y como segundo, el
identificador de la imagen.

La función fit_image() sitúa una imagen en la posición especificada de una


página. Esta función lleva cuatro argumentos: el identificador de la imagen, la
coordenada x, la coordenada y, y como quinto, la lista de opciones.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 6 (Imagen PDF)


de la Unidad 8. Estudia el código fuente y ejecútalo para mostrar en el
navegador su resultado.

En el Ejemplo 6 de esta Unidad presentamos una imagen en un documento


PDF usando las funciones del lenguaje PHP. De nuevo en este caso, no
guardamos el documento en un fichero, sino que sólo mostramos la imagen
incluida en el documento con el Acrobat Reader. En el mismo puede estudiarse
el código comentado para ver cómo hemos usado las funciones que permiten
incorporar imágenes dentro de los documentos PDF.

- 404 -
Curso de Iniciación a PHP: Unidad 8
- Utilidades prácticas -

Resumen

Hay que saber al final de esta unidad

 Aplicar las principales funciones matemáticas de


PHP a las diferentes situaciones en que deban
emplearse: trigonométricas, para hallar
redondeos, máximos y mínimos, para calcular
exponentes y logaritmos, así como para generar
números aleatorios.

 Detectar y corregir los principales errores de un


script, utilizando eficazmente las funciones de
PHP que permiten conocer su nivel y enviar a un
dispositivo un mensaje de error con el texto que
sea adecuado a cada situación.

 Crear ficheros comprimidos, abrirlos, cerrarlos,


leer su contenido, total o en parte, así como
mover el puntero de lectura-escritura por sus
diferentes bytes.

 Crear documentos en formato PDF sirviéndose de


las principales funciones de PHP para escribir
texto, dibujar figuras e incorporar imágenes.

- 405 -