Está en la página 1de 75

PHP

PHP es un lenguaje de programación dirigido a la creación de páginas web. Es un lenguaje de programación


procedural, interpretado y no tipificado, actualmente puede utilizarse una sintaxis de programación orientada
a objetos.

Páginas web, lenguajes de programación y bases de datos

La World Wide Web (o simplemente, la web) fue ideada por Tim Berners Lee en 1990, empezó a funcionar en
el CERN en 1991 y se extendió rápidamente por las Universidades del mundo (en aquel entonces Internet era
una red a la que sólo tenían acceso entidades gubernamentales, particularmente entidades educativas). En
1992 algunos proveedores comerciales empezaron a dar acceso a particulares y empresas, lo que convirtió la
web en una red de comunicación universal que ha transformado nuestras vidas.
En sus primeros años, las páginas web solían ser documentos de texto guardado en algún directorio de un
servidor y a las que se accedía mediante los primeros navegadores web. Cada página web que se veía en el
navegador correspondía a un fichero en el servidor.
La imagen siguiente ilustra de forma simplificada el esquema de funcionamiento:

 El usuario escribe la dirección de la página web en su navegador


 (1) El navegador la solicita al servidor web correspondiente (este paso requiere la participación de
máquinas intermedias que no se comentan aquí)
 (2) El servidor lee el fichero que corresponde a esa página web
 (3) El servidor envía el fichero al navegador
 El navegador muestra la página web al usuario

Este esquema de funcionamiento es suficiente para sitios web pequeños creados por una sola persona, pero
en cuanto un sitio web empieza a crecer, empiezan a surgir los problemas. Por ejemplo:
 si el sitio contiene muchas páginas es necesario crear menús que permitan orientarse por el sitio.
Como cada página debe contener el menú, cualquier cambio en el menú obliga a modificar todas las
páginas.
 si el sitio modifica a menudo su contenido (por ejemplo, la web de un periódico), tener que editar
manualmente los ficheros ralentiza el proceso.
 si el sitio es creado por varias personas, cualquiera puede modificar por error los ficheros de otras
personas y si varias personas quieren modificar el mismo fichero se pueden producir conflictos.
 si se quiere permitir la participación del público (foros, comentarios en blogs, etc), esta participación
depende de que uno de los autores modifique los ficheros, lo que ralentiza el proceso.
 si personas sin conocimientos técnicos quieren participar en la creación del sitio, pueden cometer
errores editando los ficheros.

La solución es que las páginas no sean ficheros estáticos guardados en el disco, sino que las páginas se
generen automáticamente cuando el usuario las solicite.
Por ejemplo, para resolver el problema de los menús comentado anteriormente, una solución sería que el
menú estuviera en un fichero aparte y cuando el usuario solicitara una página, el menú se añadiera al
principio de cada página (nota: no me refiero a la composición de páginas mediante frames, una solución
desaconsejada hace muchos años, sino a componer la página web a partir de varios ficheros).
Esa generación de las páginas se puede hacer de varias maneras. Una de ellas es recurrir a lenguajes de
programación generales o específicos (como PHP). Desde sus inicios, los servidores web permiten recurrir a
lenguajes de programación para generar las páginas web.
La imagen siguiente ilustra de forma simplificada el esquema de funcionamiento:

 El usuario escribe la dirección de la página web en su navegador


 (1) El navegador la solicita al servidor web correspondiente (este paso requiere la participación de
máquinas intermedias que no se comentan aquí)
 (2) El servidor detecta que es un programa PHP y lo envía al intérprete del lenguaje
 (3) El intérprete del lenguaje completa la ejecución del programa.
 (4) El resultado final del programa (por ejemplo, el código fuente de una página web) se envía al
servidor
 (5) El servidor envía el fichero al navegador
 El navegador muestra la página web al usuario

Es importante señalar que el usuario no puede saber si la página web estaba guardada en el disco duro o se ha
generado en ese momento, de la misma manera que no puede saber qué lenguaje de programación que ha
generado el documento. El navegador recibe el documento en ambos un documento de texto que contiene
etiquetas html y lo muestra al usuario.
A veces, el usuario puede suponer que la página que se le está sirviendo se ha generado mediante PHP ya que
la dirección de la página termina por .php en vez del habitual .html, aunque no se puede estar seguro de que
sea realmente así.

Pero el uso de lenguajes de programación no suele ser suficiente. Si la información está diseminada en
multitud de trozos para organizar y acceder fácilmente a toda esa información, es conveniente utilizar algún
sistema gestor de bases de datos. Existen muchos sistemas gestores de bases de datos y los lenguajes de
programación pueden conectarse a ellas y realizar consultas.
La imagen siguiente ilustra de forma simplificada el esquema de funcionamiento:

 El usuario escribe la dirección de la página web en su navegador


 (1) El navegador la solicita al servidor web correspondiente (este paso requiere la participación de
máquinas intermedias que no se comentan aquí)
 (2) El servidor detecta que es un programa PHP y lo envía al intérprete del lenguaje
 (3) El intérprete del lenguaje ejecuta el programa. Si el programa incluye consultas a la base de datos,
estas se realizan.
 (4) La base de datos entrega al intérprete el resultado de las consultas
 (5) El intérprete del lenguaje completa la ejecución del programa.
 (6) El resultado final del programa (por ejemplo, el código fuente de una página web) se envía al
servidor
 (7) El servidor envía el fichero al navegador
 El navegador muestra la página web al usuario

Como antes, el usuario no puede saber si se ha accedido o no a un sistema gestor de bases de datos. El
navegador recibe el documento en ambos un documento de texto que contiene etiquetas html y lo muestra al
usuario.
Fragmentos PHP

Los fragmentos de código PHP están delimitados por las etiquetas <?php (etiqueta inicial) y ?> (etiqueta final)
y contienen las instrucciones de PHP. Más adelante se comentan otros posibles delimitadores de fragmentos
de código PHP.
<?php
print "<p>Hola</p>\n";
?>

<p>Hola</p>

Los fragmentos de PHP no pueden anidarse, es decir, no puede haber un fragmento dentro de otro.
Si en una misma página hay varios fragmentos PHP, se tratan como un único programa.

Fragmentos PHP y fragmentos HTML

En una página PHP todo lo que no son fragmentos PHP son fragmentos HTML. Los fragmentos de código
HTML no están delimitados por ninguna etiqueta.
<?php
print "<p>Hola</p>\n";
?>
<p>¿Cómo estás?</p>
<p>Hola</p>
<p>¿Cómo estás?</p>

Cuando un navegador solicita una página PHP a un servidor, el servidor lee el archivo secuencialmente y va
generando el resultado:
 si la página contiene fragmentos HTML, el código HTML se incluye sin modificaciones en el resultado.
 si la página contiene fragmentos PHP, se ejecutan las instrucciones que se encuentran en los
fragmentos de código PHP. Si esas instrucciones generan texto, el texto se incluye en el resultado.

Cuando el servidor termina de leer el archivo y procesarlo, el servidor envía al navegador el resultado.
Es importante señalar que:
 El navegador recibe una página web (es decir, únicamente código HTML), no recibe código PHP.
 Los fragmentos PHP tiene que generar las etiquetas HTML que se necesiten para una correcta
visualización de la página web en el navegador.
 El navegador no puede distinguir en la página recibida, qué parte ha sido generada en un fragmento
PHP y qué parte se encontraba ya en un fragmento HTML.
 Como la página PHP se lee secuencialmente, el código HTML generado por los fragmentos PHP y el
incluido en los fragmentos HTML se encuentran en el mismo orden en que se encontraban los
fragmentos en la página PHP.
Los ejemplos siguientes muestran diferentes programas PHP que generan el mismo resultado:

Programa con un único fragmento PHP

<?php
print "<p>Hola</p>\n";
print "<p>¿Cómo estás?</p>\n";
print "<p>Adios</p>\n";
?>
<p>Hola</p>
<p>¿Cómo estás?</p>
<p>Adios</p>

Programa con un fragmento PHP y un fragmento HTML

<p>Hola</p>
<?php
print "<p>¿Cómo estás?</p>\n";
print "<p>Adios</p>\n";
?>
<p>Hola</p>
<p>¿Cómo estás?</p>
<p>Adios</p>

Programa con dos fragmentos PHP y un fragmento HTML

<?php
print "<p>Hola</p>\n";
?>
<p>¿Cómo estás?</p>
<?php
print "<p>Adios</p>\n";
?>
<p>Hola</p>
<p>¿Cómo estás?</p>
<p>Adios</p>

En un fragmento PHP no pueden escribirse etiquetas HTML sueltas; el código HTML debe generarse siempre
con instrucciones de PHP. El programa siguiente no puede ni siquiera ejecutarse y produce un error de
sintaxis:

<?php
<p>Hola</p>
?>
Parse error: syntax error, unexpected '<' in ejemplo.php on line 2

Comentarios en páginas PHP

En un fragmento PHP se pueden comentar líneas de código utilizando:


 // para comentar el resto de la línea (como en C++)
 # para comentar el resto de la línea (como en la shell de Unix o en Perl)
 /* */ para delimitar varias líneas (como en C)

Estos comentarios no se añaden al código HTML generado por la página, por lo que no pueden verse en el
navegador.
<p><strong>
<?php
// La instrucción print escribe texto en la página web
print "Hola"; // El comentario se puede escribir al final de la línea
?>
</strong></p>
<p><strong>Hola</strong></p>
<p><strong>
<?php
# La instrucción print escribe texto en la página web
print "Hola"; # El comentario se puede escribir al final de la línea
?>
</strong></p>
<p><strong>Hola</strong></p>
<?php
print "<p><strong>";
/* Dentro de un fragmento PHP no se pueden escribir
etiquetas html sueltas, tienen que estar siempre
incluidas en instrucciones print
*/
?>
Hola
<?php
print "</strong></p>";
?>
<p><strong>Hola</strong></p>

Cadenas
En PHP, las cadenas de texto se delimitan por comillas (dobles o simples).
<?php
print "<p>Esto es una cadena.</p>\n";
?>
<p>Esto es una cadena.</p>
<?php
print '<p>Esto es otra cadena.</p>';
?>
<p>Esto es otra cadena.</p>

Diferencias entre comillas simples y dobles

Aunque en los ejemplos anteriores las comillas simples o dobles son equivalentes, en otras situaciones no lo
son. Por ejemplo, PHP no sustituye las variables que se encuentran dentro de cadenas delimitadas con
comillas simples, mientras que sí que lo hace (pero no siempre) si se utilizan comillas dobles, como se ve en el
siguiente ejemplo:
<?php
$cadena = "Hola";
print "<p>La variable contiene el valor: $cadena</p>";
?>
<p>La variable contiene el valor: Hola</p>
O también:

<?php
$cadena = "Hola";
print "<p>La variable contiene el valor: {$cadena}</p>";
?>
<p>La variable contiene el valor: Hola</p>

<?php
$cadena = "Hola";
print '<p>La variable contiene el valor: $cadena</p>';
?>
<p>La variable contiene el valor: $cadena</p>
PHP tampoco sustituye algunos caracteres especiales (por ejemplo, el salto de línea \n)
dentro de las comillas simples, como se ve en el siguiente ejemplo:
<?php
print "<pre>Esto está en\ndos líneas.</pre>";
?>
<pre>Esto está en
dos líneas</pre>

<?php
print '<pre>Esto está en\ndos líneas.</pre>';
?>
<pre>Esto está en\ndos líneas</pre>

Para poder escribir caracteres especiales en una cadena en PHP, se empieza por el carácter contrabarra (\).
Los caracteres especiales más utilizados son los siguientes:
Carácter Significado

\\ Carácter contrabarra

\$ Carácter dólar

\" Carácter comilla doble (en una cadena delimitada por comillas dobles)

\' Carácter comilla simple (en una cadena delimitada por comillas simples)

\n Salto de línea

\t Tabulador horizontal

Además, existen también estos caracteres especiales, menos utilizados que los anteriores:

Carácter Significado

\XXX Carácter de código XXX en octal

\xXX Carácter de código XX en hexadecimal

\r Retorno de carro

\v Tabulador vertical

\e Escape

\f Salto de página (en impresoras antiguas)

Los ejemplos anteriores se podrían escribir así:


<?php
print "<p>Los nombres de variables empiezan por $. Por ejemplo \$edad.</p>";
?>
<p>Los nombres de variables empiezan por $. Por ejemplo $edad.</p>
<?php
print "<p>Las cadenas se delimitan con comillas (\" o ').</p>";
?>
<p>Las cadenas se delimitan con comillas (" o ').</p>

Concatenar cadenas

El operador . (punto) permite concatenar dos o más cadenas.


<?php
print "<p>Pasa" . "tiempos</p>\n";
?>
<p>Pasatiempos</p>
Concatenar cadenas de texto como en el ejemplo anterior no sirve para mucho, ya que se podría escribir una
única cadena en vez de varias cadenas concatenadas. El interés de la concatenación es que podemos
concatenar cadenas con cosas que no son cadenas: variables, funciones, en general, expresiones. Por ejemplo
 concatenar el resultado de un cálculo numérico:

<?php
print "<p>3 * 5 + 12 = " . (3 * 5 + 12) . "</p>\n";
?>
<p>3 * 5 + 12 = 27</p>
 concatenar el valor devuelto por una función:

<?php
print "<p>Número al azar entre 1 y 10: " . rand(1, 10) . "</p>\n";
?>
<p>Número al azar entre 1 y 10: 8</p>
 El uso más habitual es concatenar variables.

El operador combinado de asignación con concatenación (.=) permite modificar una variable concatenándole
una cadena o expresión:
<?php
$cadena = "Pasa";
print "<p>$cadena</p>\n";
$cadena .= "tiempos";
print "<p>$cadena</p>\n";
?>
<p>Pasa</p>
<p>Pasatiempos</p>

Variables
En PHP el programador puede dar el nombre que quiera a las variables, con algunas restricciones:
 Los nombres de las variables tienen que empezar por el carácter $.
 A continuación tiene que haber una letra (mayúscula o minúscula) o un guion bajo (_).
 El resto de caracteres del nombre pueden ser números, letras o guiones bajos.

<?php
// Ejemplos de nombres de variables:
$edad = 16;
$edad1 = 17;
$edad_1 = 18;
?>

PHP es de tipado débil y dinámico.


Arreglos (arrays, vectores o matrices)

Arreglos asociativos

Los arreglos de PHP son arreglos asociativos, es decir, que los índices no tienen por qué ser correlativos, ni
siquiera tienen por qué ser números.
Al crear arreglos asociativos, debemos indicar el valor de los índices, utilizando la notación $indice => $valor:
<?php
$cuadrados = [3 => 9, 5 => 25, 10 => 100];

print "<p>El cuadrado de 3 es $cuadrados[3]</p>\n";


?>
El cuadrado de 3 es 9

PHP sustituye las referencias a valores de matrices de una dimensión dentro de las cadenas, por lo que no es
necesario concatenar cadenas y referencias a matrices, pero los índices deben escribirse sin comillas, aunque
sean cadenas.

<?php
$edades = ["Andrés" => 20, "Bárbara" => 19, "Camilo" => 17];

print "<p>Bárbara tiene $edades["Bárbara"] años</p>\n";


?>
Parse error: syntax error, unexpected '"', expecting identifier (T_STRING) or variable (T_VARIABLE) or number
(T_NUM_STRING) in ejemplo.php on line 4

<?php
$edades = ["Andrés" => 20, "Bárbara" => 19, "Camilo" => 17];

print "<p>Bárbara tiene $edades[Bárbara] años</p>\n";


?>
Bárbara tiene 19 años
Si la referencia a un valor de una matriz está fuera de una cadena o entre llaves, los índices que son cadenas
deben escribirse con comillas.

<?php
$edades = ["Andrés" => 20, "Bárbara" => 19, "Camilo" => 17];

print "<p>Bárbara tiene " . $edades[Bárbara] . " años</p>\n";


print "\n";
print "<p>Camilo tiene {$edades[Camilo]} años</p>\n";
?>
Notice: Use of undefined constant Bárbara - assumed 'Bárbara' in ejemplo.php on line 4

Bárbara tiene 19 años

Notice: Use of undefined constant Camilo - assumed 'Camilo' in ejemplo.php on line 6

Camilo tiene 17 años

<?php
$edades = ["Andrés" => 20, "Bárbara" => 19, "Camilo" => 17];

print "<p>Bárbara tiene " . $edades["Bárbara"] . " años</p>\n";


print "\n";
print "<p>Camilo tiene {$edades["Camilo"]} años</p>\n";
?>

Contar elementos de un arreglo

La función count($arreglo) permite contar los elementos de un arreglo.


<?php
$nombres[1] = "Ana";
$nombres[10] = "Bernardo";
$nombres[25] = "Carmen";

$elementos = count($nombres);

print "<p>La matriz tiene $elementos elementos.</p>\n";


print "\n";
print "<pre>\n"; print_r($nombres); print "</pre>\n";
?>
La matriz tiene 3 elementos.
Array
(
[1] => Ana
[10] => Bernardo
[25] => Carmen
)

Variables Predefinidas

PHP genera automáticamente una serie de variables con diversa información sobre el cliente y el servidor.

$_REQUEST
$_REQUEST es una matriz asociativa que contiene los datos enviado por los formularios y las cookies
guardadas en el ordenador del cliente.

$_SERVER

$_SERVER es una matriz asociativa que contiene información sobre cabeceras, rutas y ubicaciones de scripts
suministrada por el servidor (pero hay que tener en cuenta que no todos los servidores suministran todos los
datos).

$_SERVER[PHP_SELF]

$_SERVER[PHP_SELF] contiene la dirección de la página (relativo a la raíz, es decir, sin el nombre del servidor).

URL $_SERVER[PHP_SELF]

http://www.example.com/ejemplo.php /ejemplo.php

http://www.example.com/ejercicios/ejemplo.php /ejercicios/ejemplo.php

El ejemplo siguiente muestra el valor de $_SERVER[PHP_SELF] de una página real:


<?php
print "<p>\$_SERVER[PHP_SELF]: $_SERVER[PHP_SELF]</p>\n";
?>

Esta variable se puede utilizar en las páginas que enlazan consigo mismas. Por ejemplo, una página puede
contener un formulario que envíe los datos a esa misma página. Para ello, el atributo action del formulario
debe contener el nombre de la página. En vez de poner el nombre de la página, se puede utilizar
$_SERVER[PHP_SELF]. La ventaja es que aunque se cambie el nombre del fichero, el enlace seguirá
funcionando.
El ejemplo siguiente muestra cómo se escribiría un enlace que apunta a la misma página que contiene el
enlace:
<?php
print "<p><a href=\"$_SERVER[PHP_SELF]\">Enlace a esta misma página</a>\n";
?>

Definir constantes

La función define(nombre_constante, valor_constante) permite definir constantes.


<?php
define("PI", 3.14);
print "<p>El valor de pi es " . PI . "</p>\n";
?>
<p>El valor de pi es 3.14</p>
<?php
define("AUTOR", "Bartolomé Sintes Marco");
print "<p>Autor: " . AUTOR . "</p>\n";
?>
<p>Autor: Bartolomé Sintes Marco</p>
También se pueden definir constantes mediante la palabra reservada const.
<?php
const PI = 3.14;
print "<p>El valor de pi es " . PI . "</p>\n";
?>
<p>El valor de pi es 3.14</p>
<?php
const AUTOR = "Bartolomé Sintes Marco";
print "<p>Autor: " . AUTOR . "</p>\n";
?>
<p>Autor: Bartolomé Sintes Marco</p>

La costumbre es escribir los nombres de las constantes en mayúsculas. Los nombres de las constantes deben
empezar por una letra y tener sólo letras (acentos, etc), números y guiones bajos.

Las constantes no se sustituyen dentro de una cadena (ni siquiera escribiéndolas entre llaves), por lo que es
necesario concatenarlas para mostrar su valor.
<?php
define("PI", 3.14);
print "<p>El valor de pi es PI</p>\n"; // El valor NO se sustituye
print "<p>El valor de pi es {PI}</p>\n"; // El valor NO se sustituye
print "<p>El valor de pi es " . PI . "</p>\n"; // El valor SÍ se sustituye
?>
<p>El valor de pi es PI</p>
<p>El valor de pi es {PI}</p>
<p>El valor de pi es 3.14</p>

Constantes Predefinidas

Tanto PHP como los módulos cargados definen automáticamente una serie de constantes predefinidas

Operaciones aritméticas

Son los mismos operadores que aprendimos en Javascript.

Operaciones lógicas

Son los mismos operadores que aprendimos en Javascript.


Alternativa Condicional
If elseif else
if (condición_1) {
bloque_de_sentencias_1
} elseif (condición_2) {
bloque_de_sentencias_2
} elseif (condición_3) {
bloque_de_sentencias_3
...
} elseif (condición_n) {
bloque_de_sentencias_n
} else {
bloque_de_sentencias_n+1
}

? : (el equivalente a operador ternario de Javascript)

$variable = (condición_1) ? expresión_1 : expresión_2;

Sentencia condicional Switch


switch (expresión_1) {
case valor_1:
bloque_de_sentencias_1;
break;
case valor_2:
bloque_de_sentencias_2;
break;
...
case valor_n:
bloque_de_sentencias_n;
break;
}

Bucle for

for (expresión_inicial; condición_continuación; expresión_paso) {


bloque_de_sentencias
}

<?php
for ($i = 0; $i < 5; $i++) {
print "<p>$i</p>\n";
}
?>
<p>0</p>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>

Bucle while

while (condición) {
bloque_de_sentencias
}

Bucle do ... while

do {
bloque_de_sentencias
} while (condición)

Bucle foreach

El bucle foreach es muy útil para recorrer matrices cuyo tamaño se desconoce o matrices cuyos índices no son
correlativos o numéricos (matrices asociativas).
La sintaxis del bucle foreach más simple es la siguiente:
foreach ($matriz as $valor) {
bloque_de_sentencias
}
El bucle ejecuta el bloque de sentencias tantas veces como elementos contenga la matriz $matriz y, en cada
iteración, la variable $valor toma uno de los valores de la matriz.
En el ejemplo siguiente se define una matriz y se imprimen sus valores:
<?php
$matriz = [0, 1, 10, 100, 1000];
foreach ($matriz as $valor) {
print "<p>$valor</p>\n";
}
?>
<p>0</p>
<p>1</p>
<p>10</p>
<p>100</p>
<p>1000</p>
La sintaxis del bucle foreach puede también ser la siguiente:
foreach ($matriz as $indice => $valor) {
bloque_de_sentencias
}
El bucle ejecuta el bloque de sentencias tantas veces como elementos contenga la matriz $matriz y, en cada
iteración, la variable $valor toma uno de los valores de la matriz y la variable $indice toma como valor el
índice correspondiente. Esta construcción es muy útil
En el ejemplo siguiente se define una matriz asociativa y se imprimen sus valores:
<?php
$matriz = ["red" => "rojo", "green" => "verde", "blue" => "azul"];
foreach ($matriz as $indice => $valor) {
print "<p>$indice : $valor</p>\n";
}
?>
<p>red : rojo</p>
<p>green : verde</p>
<p>blue : azul</p>

Controles en formularios
Para que un control envíe información es necesario:
 que el control esté incluido en un formulario (<form>).
 que el formulario tenga establecido el atributo action, con la dirección absoluta o relativa del fichero
php que procesará la información
 que el control tenga establecido el atributo name
 que el formulario contenga un botón de tipo submit

El siguiente ejemplo muestra un formulario válido (ejemplo.html):


<form action="ejemplo.php">
<p>Nombre: <input type="text" name="nombre"></p>
<p><input type="submit" value="Enviar"></p>
</form>
Pepito Conejo
Nombre:

Enviar

El programa que recibe los datos los guarda automáticamente en la matriz $_REQUEST. Mediante la
orden print_r($_REQUEST) se puede mostrar el contenido de la matriz $_REQUEST.
El siguiente ejemplo muestra lo que escribiría el programa PHP (ejemplo.php) si recibiera la información del
formulario anterior (ejemplo.html).
<?php
print "<pre>";
print_r($_REQUEST);
print "</pre>\n";
?>
Array
(
[nombre] => Pepito Conejo
)
El nombre del elemento de la matriz $_REQUEST coincide con el nombre del control (atributo name)en el
formulario (excepto en el control de tipo imagen).
Atributo method

El atributo method de la etiqueta <form> permite elegir si la información de los controles se incluye en la
llamada a la página (method="get") o se proporciona posteriormente (method="post"). Si el atributo no está
definido, la información se incluye. Desde el punto de vista de la seguridad ambos métodos son equivalentes.
La diferencia es que con el valor get se pueden ver en la barra de dirección los nombres de los controles y los
valores introducidos por el usuario, mientras que con el valor post no, pero los datos recibidos son idénticos.
Formulario con get

<form action="ejemplo.php" method="get">


<p>Nombre: <input type="text" name="nombre"></p>
<p><input type="submit" value="Enviar"></p>
</form>

print "<pre>";
print_r($_REQUEST);
print "</pre>";

Formulario con post

<form action="ejemplo.php" method="post">


<p>Nombre: <input type="text" name="nombre"></p>
<p><input type="submit" value="Enviar"></p>
</form>
print "<pre>";
print_r($_REQUEST);
print "</pre>";

En caso de que haya varios controles que envíen información en un formulario con get, los nombres y valores
aparecen en la barra de dirección separados por el carácter ampersand (&), como
nombre1=valor1&nombre2=valor2&...
<form action="ejemplo.php" method="get">
<p>Nombre: <input type="text" name="nombre"></p>
<p>Apellidos: <input type="text" name="apellidos"></p>
<p><input type="submit" value="Enviar"></p>
</form>

print "<pre>";
print_r($_REQUEST);
print "</pre>";
Botón Enviar (input submit, button)

Este control se puede crear con la etiqueta <input> o con la etiqueta <button>. En ambos casos, este control
se envía siempre que esté definido el atributo name y que se haya hecho clic en el botón. El valor enviado es
el valor del atributo value o el contenido de la etiqueta.
Código fuente

<input type="submit" value="Submit">


Control

Submit

$_REQUEST

Array
(
)
<input type="submit" value="Enviar" name="boton2">
Enviar

Array
(
[boton2] => Enviar
)
<button type="submit">Submit</button>
Submit

Array
(
)
<button type="submit" name="boton3">Enviar</button>
Enviar

Array
(
[boton3] => Enviar
)
<button type="submit" name="boton4" value="enviado">Enviar</button>
Enviar

Array
(
[boton4] => enviado
)
Normalmente no se suele dar el atributo name al botón enviar ya que la información se envía cuando se hace
clic en el botón. pero en algunos casos si que puede ser conveniente. Por ejemplo cuando el formulario
contiene varios botones y queremos saber cuál se ha pulsado, como en el ejemplo siguiente, en el que los
atributos name son iguales, pero los atributos value son distintos:
ejemplo.html
<form action="ejemplo.php" method="get">
<p>¿Sí o no?</p>
<p>
<input type="submit" name="respuesta" value="Sí">
<input type="submit" name="respuesta" value="No">
</p>
</form>

ejemplo.php
print "<pre>";
print_r($_REQUEST);
print "</pre>";

Caja de texto, caja de contraseña y área de texto (input text, input password, textarea)

Este control se envía siempre. El valor enviado es el contenido de la caja o área.


<input type="text" name="cajatexto1">

Array
(
[cajatexto1] =>
)
<input type="text" name="cajatexto2" value="Cualquier cosa">
Cualquier c

Array
(
[cajatexto2] => Cualquier cosa
)
<input type="password" name="cajapassword1">

Array
(
[cajapassword1] =>
)
<input type="password" name="cajapassword2" value="pezespada">
*********

Array
(
[cajapassword2] => pezespada
)
<textarea rows="4" cols="20" name="areadetexto1"></textarea>

Array
(
[areadetexto1] =>
)
<textarea rows="4" cols="20" name="areadetexto2">Cualquier cosa</textarea>
Cualquier cosa

Array
(
[areadetexto2] => Cualquier cosa
)

Casilla de verificación (input checkbox)

Este control se envía solamente si se marca la casilla. El valor enviado es "on" si la casilla no tiene definido el
atributo value o el valor del atributo value si éste está definido.
<input type="checkbox" name="casilla1">
(sin marcar)

Array
(
)
<input type="checkbox" name="casilla2">
(marcada)

Array
(
[casilla2] => on
)
<input type="checkbox" name="casilla3" value="Tres">
(marcada)

Array
(
[casilla3] => Tres
)

Botón radio (input radio)

Este control se envía solamente si se marca alguno de los botones radio que forman el control. El valor
enviado es "on" si el botón marcado no tiene definido el atributo value o el valor del atributo value si éste
está definido.
<input type="radio" name="radio1">
<input type="radio" name="radio1">
(sin marcar)

Array
(
)
<input type="radio" name="radio2">
<input type="radio" name="radio2">
(marcado uno)

Array
(
[radio2] => on
)
<input type="radio" name="radio2">
<input type="radio" name="radio2">
(marcado otro)

Array
(
[radio2] => on
)
<input type="radio" name="radio3" value="Uno">
<input type="radio" name="radio3" value="Dos">
(marcado uno)

Array
(
[radio3] => Uno
)
<input type="radio" name="radio3" value="Uno">
<input type="radio" name="radio3" value="Dos">
(marcado otro)

Array
(
[radio3] => Dos
)

Menú (select)

Este control envía siempre la opción elegida. El valor enviado es el contenido de la etiqueta option elegida si la
opción elegida no tiene definido el atributo value o el valor del atributo value si éste está definido.
Si el menú admite selección múltiple, entonces el nombre del menú debe acabar con corchetes ([]) y se envía
como una matriz, de tantos elementos como opciones se hayan elegido.
<select name="menu1">
<option></option>
</select>

Array
(
[menu1] =>
)
<select name="menu2">
<option>Opción 1</option>
<option>Opción 2</option>
</select>

Array
(
[menu2] => Opción 1
)
<select name="menu3">
<option value="Uno">Opción 1</option>
<option value="Dos">Opción 2</option>
</select>

Array
(
[menu3] => Uno
)
<select name="menu4[]" size="3" multiple>
<option>Opción 1</option>
<option>Opción 2</option>
<option>Opción 3</option>
<option>Opción 4</option>
</select>
Opción 1
Opción 2
Opción 3

(Marcados 1 y 3)

Array
(
[menu4] => Array
(
[0] => Opción 1
[1] => Opción 3
)
)

Control oculto (input hidden)

Este control se envía siempre y el valor enviado es el valor del atributo value.
<input type="hidden" name="oculto1">
Array
(
[oculto1] =>
)
<input type="hidden" name="oculto2" value="Cualquier cosa">
Array
(
[oculto2] => Cualquier cosa
)
Imagen (input image)

El control de tipo imagen inserta una imagen que funciona como un botón (aunque ni Firefox ni Internet
Explorer le da relieve como a los botones). Al hacer clic en un punto de la imagen es como si se hubiera
pulsado a un botón submit y se envían las coordenadas del punto en el que se ha hecho clic (junto con los
valores de los otros controles del formulario).
El origen de las coordenadas es el extremo superior izquierdo de la imagen. El valor X aumenta a medida que
nos desplazamos a la derecha y el valor Y aumenta a medida que nos desplazamos hacia abajo.
<input type="image" name="gnu" src="gnu.jpg" alt="Logotipo GNU">

Array
(
[gnu_x] => 89
[gnu_y] => 111
)
Las coordenadas se reciben en $_REQUEST en dos elementos que añaden al nombre del control el sufijo _x e
_y. En la barra de dirección el nombre aparece con el sufijo .x e .y.

Archivo (input file)

El selector de archivo permite enviar un archivo desde el ordenador del cliente al servidor.
En un formulario "normal", este control se envía siempre y el valor enviado es el nombre del archivo elegido.
<input type="file" name="archivo1">
Array
(
[archivo1] => loquesea.txt
)
Para que este control envíe toda la información, el formulario debe tener el atributo enctype con el
valor multipart/form-data y ser enviado con el método POST. La información se almacena entonces en la
matriz $_FILES (pero no en la variable $_REQUEST).
<form enctype="multipart/form-data" action="ejemplo.php" method="post" >
<input type="file" name="archivo2">
Array
(
[archivo2] => Array
(
[name] => loquesea.txt
[type] => text/plain
[tmp_name] => C:\ejemplos\loquesea.txt
[error] => 0
[size] => 27890
)
)
Antes de utilizar este control, hay que configurar en el archivo php.ini el tamaño máximo de los archivos que
se pueden enviar (mediante la directiva post_max_size) y es conveniente leer el capítulo correspondiente a
la subida de archivos del manual de PHP para conocer la manera de evitar los posibles riesgos de seguridad.

Recogida de datos

Matriz $_REQUEST

Cuando se envía un formulario, PHP almacena la información recibida en una matriz llamada $_REQUEST. El
número de valores recibidos y los valores recibidos dependen tanto del formulario como de la acción del
usuario.
Cualquier control se envía solamente si está establecido su atributo name. El atributo name del control puede
contener cualquier carácter (números, acentos, guiones, etc), pero si contiene espacios, los espacios se
sustituyen por guiones bajos (_). Cada control crea un elemento de la matriz $_REQUEST, que se identifica
como $_REQUEST[valor_del_atributo_name] y que contiene el valor entregado por el formulario (en su caso).
El siguiente ejemplo muestra un ejemplo de formulario:
<form action="ejemplo.php">
<p>Nombre: <input type="text" name="nombre"></p>
<p><input type="submit" value="Enviar"></p>
</form>

Nombre:

Enviar

Mientras se está programando, para comprobar que el fichero php está recibiendo la información enviada por
el control, lo más fácil es utilizar la función print_r($matriz) para mostrar el contenido de la matriz
$_REQUEST. Una vez se ha comprobado que la información llega correctamente, la línea se debe comentar o
eliminar.
El siguiente ejemplo muestra lo que escribiría el programa PHP si recibiera la información del formulario
anterior.
Pepito Conejo
Nombre:

Enviar

<?php
print "<pre>"; print_r($_REQUEST); print "</pre>\n";

print "<p>Su nombre es $_REQUEST[nombre]</p>\n";


?>
Array
(
[nombre] => Pepito Conejo
)
Su nombre es Pepito Conejo
Conviene colocar etiquetas <pre> alrededor del print_r($_REQUEST) para facilitar la visualización de los
valores.

Referencia a $_REQUEST dentro y fuera de cadenas

Al hacer referencia a los elementos de la matriz $_REQUEST, hay que tener en cuenta si la referencia se
encuentra dentro de una cadena o fuera de ella.
Si se hace referencia dentro de una cadena, el índice se debe escribir sin comillas. Si se escribe cualquier tipo
de comillas (simples o dobles) se produce un error.

<?php
print "<p>Su nombre es $_REQUEST[nombre]</p>\n";
?>
Si se hace referencia fuera de una cadena, el índice se debe escribir con comillas dobles o simples. Si se
escribe sin comillas, se produce un aviso.

<?php
print "<p>Su nombre es " . $_REQUEST["nombre"] . "</p>\n";
?>

Comprobación de existencia

Un programa PHP no debe suponer que los controles le van a llegar siempre porque cuando eso no ocurra, el
programa no funcionará correctamente.

Controles vacíos

La primera situación que los programas deben tener en cuenta es que los controles no contengan ningún
valor.
En el programa de ejemplo del principio de esta lección, si el usuario ha utilizado el formulario y ha escrito un
dato, el programa PHP recibe el control y funciona correctamente:
Pepito Conejo
Nombre:

Enviar

<?php
print "<pre>"; print_r($_REQUEST); print "</pre>\n";

print "<p>Su nombre es $_REQUEST[nombre]</p>\n";


?>
Array
(
[nombre] => Pepito Conejo
)
Su nombre es Pepito Conejo
Pero si el usuario no escribe nada en el formulario, aunque el programa funcione correctamente, la respuesta
del programa puede confundir al usuario:

Nombre:

Enviar

<?php
print "<pre>"; print_r($_REQUEST); print "</pre>\n";

print "<p>Su nombre es $_REQUEST[nombre]</p>\n";


?>
Array
(
[nombre] =>
)
Su nombre es
Este problema se puede resolver incluyendo una estructura if ... else ... que considere la posibilidad de que no
se haya escrito nada en el formulario:

Nombre:

Enviar

<?php
print "<pre>"; print_r($_REQUEST); print "</pre>\n";

if ($_REQUEST["nombre"] == "") {
print "<p>No ha escrito ningún nombre</p>";
} else {
print "<p>Su nombre es $_REQUEST[nombre]</p>\n";
}
?>
Array
(
[nombre] =>
)
No ha escrito ningún nombre

Controles inexistentes: isset()

Un problema más grave es que el programa suponga que existe un control que en realidad no le ha llegado.
Eso puede ocurrir, por ejemplo, en el caso de las casillas de verificación y los botones radio, ya que los
formularios envían el control solamente cuando se han marcado.
<form action="ejemplo.php">
<p>Deseo recibir información: <input type="checkbox" name="acepto"></p>
<p><input type="submit" value="Enviar"></p>
</form>

Deseo recibir información:

Enviar

Si en el formulario anterior el usuario marca la casilla, el siguiente programa funciona perfectamente:

Deseo recibir información:

Enviar

<?php
print "<pre>"; print_r($_REQUEST); print "</pre>\n";

if ($_REQUEST["acepto"] == "on") {
print "<p>Desea recibir información</p>\n";
} else {
print "<p>No desea recibir información</p>\n";
}
?>
Array
(
[acepto] => on
)
Desea recibir información
Pero si el usuario no marca la casilla, la matriz $_REQUEST no contiene el dato y el programa genera un aviso
por hacer referencia a un índice no definido, aunque se haya incluido la estructura if ... else ... :

Deseo recibir información:

Enviar
<?php
print "<pre>"; print_r($_REQUEST); print "</pre>\n";

if ($_REQUEST["acepto"] == "on") {
print "<p>Desea recibir información</p>\n";
} else {
print "<p>No desea recibir información</p>\n";
}
?>
Array
(
)
Notice: Undefined index: acepto in ejemplo.php on line 4
No desea recibir información
Esto puede ocurrir en realidad en cualquier formulario (incluso en formularios con cajas de texto que en
principio envían siempre el control) ya que el usuario puede escribir directamente la dirección del programa
PHP en el navegador y ejecutar el programa PHP sin pasar por el formulario. En ese caso, el programa no
recibe ningún control y el programa genera un aviso por hacer referencia a un índice no definido:
Pepito Conejo
Nombre:

Enviar

<?php
print "<pre>"; print_r($_REQUEST); print "</pre>\n";

if ($_REQUEST["nombre"] == "") {
print "<p>No ha escrito ningún nombre</p>";
} else {
print "<p>Su nombre es $_REQUEST[nombre]</p>\n";
}
?>
Array
(
)
Notice: Undefined index: nombre in ejemplo.php on line 4
No ha escrito ningún nombre
Estos problemas se pueden resolver comprobando que el índice está definido antes de hacer referencia a él,
utilizando la función isset($variable), que admite como argumento una variable y devuelve true si existe

Deseo recibir información:

Enviar

<?php
if (isset($_REQUEST["acepto"])) {
print "<p>Desea recibir información</p>\n";
} else {
print "<p>No desea recibir información</p>\n";
}
?>
Desea recibir información

Deseo recibir información:

Enviar

<?php
if (isset($_REQUEST["acepto"])) {
print "<p>Desea recibir información</p>\n";
} else {
print "<p>No desea recibir información</p>\n";
}
?>
No desea recibir información
Es conveniente efectuar siempre la verificación de existencia para prevenir los casos en que un usuario
intente acceder a la página PHP sin pasar por el formulario.

Funciones is_

Las funciones is_ son un conjunto de funciones booleanas que devuelven true si el argumento es de un tipo
de datos determinado y false si no lo son.

Función Tipo de datos

isset($valor) devuelve si el dato está definido o no


existencia
is_null($valor) null

is_bool($valor) booleano

número (puede tener signo, parte decimal y estar expresado en notación


decimal u otra; si el argumento es una cadena la función devuelve true si los
is_numeric($valor) números están expresados en notación decimal, exponencial u octal, pero
números devuelve false si los números están expresados en notación hexadecimal o
binaria).

is_int($valor) entero

is_float($valor) float

cadenas is_string($valor) cadena


is_scalar($valor) escalar (entero, float, cadena o booleano)

is_array($valor) matriz

is_callable($valor) función

otros is_object($valor) object

is_resource($valor) recurso

is_countable($valor) contable (matriz u objeto que implementa Countable)

is_iterable($valor) iterable (matriz u objeto que implementa Traversable)

Sesiones

Introducción

Una de las limitaciones de las páginas web es que cada página web es un documento independiente. Eso hace
que dos programas PHP no puedan, en principio, compartir información.
En principio, la única manera de enviar información de una página a otra es a través de un formulario y se
trata de la información que ha introducido el usuario en ese formulario. Como mucho podemos enviar
información adicional mediante controles ocultos, pero esto no puede considerarse compartir información,
puesto que la página que recibe la información no puede saber si la información ha sido manipulada por el
camino ni quién se la envía.
Por compartir información nos estamos refiriendo a utilizar variables comunes en programas distintos, sin que
la información salga del servidor.
El ejemplo siguiente muestra dos páginas: en la primera se crea una variable, que se puede utilizar en esa
misma página. La segunda página, que se encuentra en el mismo servidor, no tiene acceso a la variable creada
en el primer programa y por eso se produce un aviso al ejecutarla.
<?php
$nombre = "Pepito Conejo";
print "<p>El nombre es $nombre</p>";
El nombre es Pepito Conejo
<?php
print "<p>El nombre es $nombre</p>";
Notice: Undefined variable: nombre in ejemplo.php on line 2

El nombre es
PHP puede superar esta limitación mediante las sesiones. Las sesiones permiten que páginas distintas puedan
acceder a una variable común, la matriz $_SESSION.
El ejemplo siguiente muestra dos páginas: en la primera se crea la variable en la matriz $_SESSION, que se
puede utilizar en esa misma página. La segunda página, que se encuentra en el mismo servidor, tiene acceso a
la variable creada en el primer programa (si se ha ejecutado antes el primer programa, obviamente).
<?php
session_start();

$_SESSION["nombre"] = "Pepito Conejo";


print "<p>El nombre es $_SESSION[nombre]</p>";
El nombre es Pepito Conejo
<?php
session_start();

print "<p>El nombre es $_SESSION[nombre]</p>";


El nombre es Pepito Conejo

Las sesiones no deben confundirse con las cookies. Las cookies es un método que permite guardar
información en el ordenador del cliente para recuperarla en el futuro, mientras que en las sesiones la
información se mantiene en el servidor hasta que se cierra la sesión (por intervención del usuario o por
tiempo). En el manual de PHP se ofrece un capítulo dedicado a las sesiones.
El trabajo con sesiones tiene tres partes:
 Creación o apertura de la sesión

Cuando alguna página crea una sesión utilizando la función correspondiente, el servidor asocia al
navegador del usuario un identificador de usuario único. El identificador se guarda en el usuario en
forma de cookie o, si el navegador del usuario no permite la creación de cookies, añadiendo el
identificador en la dirección de la página.
 Utilización de la sesión

Si ya se ha creado la sesión, las páginas solicitadas por el mismo navegador pueden guardar y
recuperar información en el servidor, información que se asocia al identificador de usuario, por lo que
no es accesible a otros usuarios. La información se conserva hasta que el usuario o el servidor
destruyan la sesión.
 Destrucción o cierre de la sesión

Tanto el usuario como el servidor pueden cerrar la sesión. El usuario puede destruir la sesión cerrando
el navegador. El servidor puede destruir la sesión cuando alguna página utilice la función
correspondiente o al cabo de un tiempo determinado (definido mediante la
función session_set_cookie_params()).

Crear la sesión

En PHP, las sesiones se crean mediante la función session_start(). Si la sesión no existía, esta función crea la
sesión y le asocia un identificador de sesión único. Si la sesión ya existía, esta función permite que la página
tenga acceso a la información vinculada a la sesión. Es decir, todas las páginas que quieran guardar datos en
$_SESSION o leer datos de $_SESSION deben comenzar con la función session_start().
<?php
session_start();

$_SESSION["nombre"] = "Pepito Conejo";


print "<p>El nombre es $_SESSION[nombre]</p>";
El nombre es Pepito Conejo
<?php
session_start();

print "<p>El nombre es $_SESSION[nombre]</p>";


El nombre es Pepito Conejo
La creación de sesiones requiere el envío de cabeceras HTTP, por lo que la función session_start() debe
utilizarse antes de empezar a escribir el contenido de la página. En caso contrario PHP producirá un aviso y no
se creará la sesión.
El ejemplo siguiente es incorrecto, ya que utiliza la función session_start() después de haber escrito texto.

<?php
// Este código es incorrecto, la sesión se crea después de crear texto
print "<p>Hola</p>\n";
session_start();
Hola
Warning: session_start(): Cannot send session cache limiter - headers already sent (output started at
ejemplo.php:3) in ejemplo.php on line 4

Utilizar la sesión

Cuando una página ha creado una sesión o ha accedido a una sesión ya existente mediante session_start(), la
página tiene acceso a la matriz $_SESSION que contiene las variables de esa sesión.
La matriz $_SESSION es una matriz asociativa en la que se pueden definir valores como en cualquier otra
matriz. La diferencia es que $_SESSION es accesible desde páginas diferentes (siempre que esas páginas
tengan asociada la misma sesión), manteniéndose los valores de una página a otra.
El ejemplo siguiente muestra dos páginas. La primera página guarda información en $_SESSION y la segunda la
utiliza.
<?php
session_start();

$_SESSION["nombre"] = "Pepito Conejo";


print "<p>Se ha guardado su nombre.</p>\n";
<p>Se ha guardado su nombre.</p>
<?php
session_start();

print "<p>Su nombre es $_SESSION[nombre].</p>\n";


<p>Su nombre es Pepito Conejo.</p>
Los nombres de los primeros índices de la matriz $_SESSION tienen que cumplir las mismas reglas que los
nombres de las variables, es decir, que el primer carácter debe ser una letra o un guion bajo (_). En particular,
no deben ser números ni contener caracteres no alfanuméricos.
<?php
session_start();

// Este código es incorrecto, ya que PHP no puede crear un índice numérico en


$_SESSION
$_SESSION[] = "Pepito Conejo";
print "<p>Se ha guardado su nombre.</p>\n";
print "<pre>"; print_r($_SESSION); print "</pre>\n";
Se ha guardado su nombre.
Notice: Unknown: Skipping numeric key 0 in Unknown on line 0

Array
(
)
<?php
session_start();

// Este código es correcto, ya que el primer índice no es numérico


$_SESSION["nombres"][] = "Pepito Conejo";
print "<p>Se ha guardado su nombre.</p>\n";
print "<pre>"; print_r($_SESSION); print "</pre>\n";
Se ha guardado su nombre.
Array
(
[nombres] => Array
(
[0] => Pepito Conejo
)

Cerrar la sesión

Cerrar una sesión es destruir la matriz $_SESSION y el identificador de la sesión.


Las sesiones se pueden cerrar de varias maneras:
 El usuario puede cerrar la sesión simplemente cerrando el navegador (no basta con cerrar las
pestañas).
 Un programa puede cerrar la sesión mediante la función session_destroy().
 En general, las cookies tienen una duración establecida en la directiva session.cookie_lifetime (y el
servidor puede borrar la información cuando ha pasado el tiempo indicado en segundos en la
directiva session.gc_maxlifetime), pero la duración de una sesión en particular puede establecerse en
el momento de su creación mediante la función session_set_cookie_params() (tiempo que se puede
modificar posteriormente).

Cuando se destruye una sesión, el programa que ha destruido la sesión sigue teniendo acceso a los valores de
$_SESSION creados antes de la destrucción de la sesión, pero las páginas siguientes no. Si se ejecuta el
primero de los ejemplos siguientes y después el segundo, se obtienen los resultados indicados:
<?php
session_start();

$_SESSION["nombre"] = "Pepito Conejo";


session_destroy();

if (isset($_SESSION["nombre"])) {
print "<p>Su nombre es $_SESSION[nombre].</p>\n";
} else {
print "<p>No sé su nombre.</p>\n";
}
<p>Su nombre es Pepito Conejo.</p>
<?php
session_start();

if (isset($_SESSION["nombre"])) {
print "<p>Su nombre es $_SESSION[nombre].</p>\n";
} else {
print "<p>No sé su nombre.</p>\n";
}
<p>No sé su nombre.</p>

Nombre de sesión

En principio, cuando el navegador se conecta a un servidor, la sesión es única, es decir, todas las páginas del
mismo dominio compartirán la misma matriz $_SESSION. La función session_name() permite establecer un
nombre de sesión específico, de manera que todas las páginas que declaren el mismo nombre de sesión
accederán a la misma matriz $_SESSION y las que tengan nombres de sesión distintos accederán a matrices
$_SESSION diferentes.
En el ejemplo siguiente, los dos primeros programas crean la misma variable en $_SESSION, pero como se ha
utilizado la función session_name() con nombres diferentes, realmente lo hacen en matrices $_SESSION
distintas.
<?php
session_name("ejemplo1");
session_start();

$_SESSION["nombre"] = "Pepito Conejo";


print "<p>El nombre es $_SESSION[nombre]</p>";
El nombre es Pepito Conejo
<?php
session_name("ejemplo2");
session_start();
$_SESSION["nombre"] = "Juan Fulánez";
print "<p>El nombre es $_SESSION[nombre]</p>";
El nombre es Juan Fulánez
Los dos programas siguientes acceden después a las matrices $_SESSION, pero cada uno accede a la matriz
correspondiente al nombre de sesión.
<?php
session_name("ejemplo1");
session_start();

print "<p>El nombre es $_SESSION[nombre]</p>";


El nombre es Pepito Conejo
<?php
session_name("ejemplo2");
session_start();

print "<p>El nombre es $_SESSION[nombre]</p>";


El nombre es Juan Fulánez
El nombre de sesión distingue entre minúsculas y mayúsculas, es decir, dos sesiones con el mismo nombre,
pero uno en minúsculas y otro en mayúsculas, son dos sesiones distintas.

Borrar elementos de la sesión

Los valores de $_SESSION se borran como en cualquier otra matriz mediante la función unset().
<?php
session_start();

$_SESSION["nombre"] = "Pepito Conejo";

print "<p>Su nombre es $_SESSION[nombre].</p>\n";

unset($_SESSION["nombre"]);

if (isset($_SESSION["nombre"])) {
print "<p>Su nombre es $_SESSION[nombre].</p>\n";
} else {
print "<p>No sé su nombre.</p>\n";
}
<p>Su nombre es Pepito Conejo.</p>
<p>No sé su nombre.</p>

Para borrar todos los valores de $_SESSION se pueden borrar uno a uno o utilizar la función session_unset(),
pero normalmente no se debe utilizar unset():
 unset($_SESSION) impide que el resto de la página escriba o lea valores en $_SESSION, pero la sesión
conserva los valores, por lo que otras páginas seguirían viendo esos valores.
<?php
session_start();
$_SESSION["nombre"] = "Pepito";
unset($_SESSION);
$_SESSION["apellidos"] = "Conejo";
header("Location:pagina-2.php");
<?php
session_start();
$_SESSION["saludo"] = "Hola";
print "<pre>\n";
print_r ($_SESSION);
print "</pre>\n";
<pre>
Array
(
[nombre] => Pepito
[saludo] => Hola
)
</pre>
 la función session_unset() borra todos los valores pero permite que el resto de la página (y otras
páginas) escriba o lea valores en $_SESSION.

<?php
session_start();
$_SESSION["nombre"] = "Pepito";
session_unset();
$_SESSION["apellidos"] = "Conejo";
header("Location:pagina-2.php");
<?php
session_start();
$_SESSION["saludo"] = "Hola";
print "<pre>\n";
print_r ($_SESSION);
print "</pre>\n";
<pre>
Array
(
[apellidos] => Conejo
[saludo] => Hola
)
</pre>
Funciones y bibliotecas

Funciones sin argumentos

Las funciones se identifican por su nombre. Las funciones se definen mediante la palabra
reservada function seguida del nombre de la función y unos paréntesis, seguidos de un conjunto de
instrucciones escritos entre llaves. La llave que abre el bloque de instrucciones se suele escribir al principio de
la línea siguiente, no a continuación del nombre de la función.
function nombreDelaFuncion()
{
bloque_de_sentencias
}
Las funciones se aprovechan en el resto del programa escribiendo el nombre de la función seguido de
paréntesis. PHP ejecuta el bloque de instrucciones de la función cada vez que se llama a la función.
<?php
// Definición de la función prueba()
function prueba()
{
print "<p>I will not waste chalk.</p>\n";
print "\n";
print "<p>I will not skateboard in the halls.</p>\n";
print "\n";
print "<p>I will not burp in class.</p>\n";
print "\n";
}

print "<p>Programa de prueba.</p>\n";


print "\n";
// Llamadas a la función prueba()
prueba();
prueba();
?>
<p>Programa de prueba.</p>

<p>I will not waste chalk.</p>

<p>I will not skateboard in the halls.</p>

<p>I will not burp in class.</p>

<p>I will not waste chalk.</p>

<p>I will not skateboard in the halls.</p>

<p>I will not burp in class.</p>


Si se llama a una función definida en el mismo fichero, la función puede estar definida antes o después de la
llamada.
<?php
// Definición de la función prueba()
function prueba()
{
print "<p>Hola!</p>\n";
}

// Llamada a la función prueba()


prueba();
?>
<p>Hola!</p>
<?php
// Llamada a la función prueba()
prueba();

// Definición de la función prueba()


function prueba()
{
print "<p>Hola!</p>\n";
}
?>
<p>Hola!</p>
Si no se llama a una función en el programa principal, las funciones no tienen ningún efecto en la salida del
programa (excepto si contienen errores de sintaxis que impidan la ejecución del programa).

PHP no distingue ente mayúsculas y minúsculas en el nombre de las funciones.

<?php
// Definición de la función prueba()
function prueba()
{
print "<p>I will not waste chalk.</p>\n";
print "\n";
}

// Llamadas a la función prueba()


prueba();
PRUEBA();
PrUeBa();
?>
<p>I will not waste chalk.</p>

<p>I will not waste chalk.</p>

<p>I will not waste chalk.</p>

Independencia de las funciones respecto al programa principal


Las funciones son independientes del resto del programa. En particular, las variables que aparecen en una
función son independientes de las variables del programa principal. En principio, ni la función tiene acceso a
las variables del programa principal, ni el programa principal tiene acceso a las variables de la función.
En el siguiente ejemplo, tanto el programa principal como la función utilizan una variable con el mismo
nombre ($a), pero para el programa se trata de dos variables distintas.

<?php
// Definición de la función prueba()
function prueba()
{
$a = 42;
print "<p>La variable a es $a.</p>\n";
print "\n";
}

// Damos un valor a la variable


$a = 100;
print "<p>La variable a es $a.</p>\n";
print "\n";
// Llamamos a la función, que da un valor distinto a una variable con el mismo
nombre
prueba();
// Pero en el programa principal, la variable no ha cambiado su valor
print "<p>La variable a es $a.</p>\n";
?>
<p>La variable a es 100.</p>

<p>La variable a es 42.</p>

<p>La variable a es 100.</p>


En el siguiente ejemplo, la función genera un aviso ya que se hace referencia a una variable no definida. Esto
se debe a que la función no da valor a la variable $a y la función no tiene acceso a la variable $a del programa
principal. Otro detalle a señalar es que el aviso se genera cuando el programa principal llama a la función, es
decir, cuando se ejecuta la función.

<?php
// Definición de la función prueba()
function prueba()
{
// Intentamos escribir el valor de la variable $a
// pero como no está definida, se produce un aviso
print "<p>La variable a es $a.</p>\n";
print "\n";
}

// Damos un valor a la variable


$a = 100;
print "<p>La variable a es $a.</p>\n";
print "\n";
// Llamamos a la función
prueba();
// Volvemos a escribir la variable
print "<p>La variable a es $a.</p>\n";
?>
<p>Programa de prueba.</p>

<p>La variable a es 100.</p>

<br />
<b>Warning</b>: Undefined variable $a in <b>ejemplo.php</b> on line <b>5</b><br
/>
<p>La variable a es .</p>

<p>La variable a es 100.</p>


En el siguiente ejemplo, es el programa principal el que genera el aviso ya que se hace referencia a una
variable no definida. Aunque hemos llamado a la función que da valor a una variable $a, el aviso se produce
porque el programa no tiene acceso a la variable $a de la función.

<?php
// Definición de la función prueba()
function prueba()
{
// La variable $a sólo está definida en la función, no fuera de ella
$a = 42;
print "<p>La variable a es $a.</p>\n";
print "\n";
}

// Llamamos a la función
prueba();
// Intentamos escribir el valor de la variable $a
// pero como no está definida, se produce un aviso
print "<p>La variable a es $a.</p>\n";
?>
<p>La variable a es 42.</p>
<br />
<b>Warning</b>: Undefined variable $a in <b>ejemplo.php</b> on line <b>13</b><br
/>
<p>La variable a es .</p>

Variables globales

Podemos hacer que una función tenga acceso a las variables del programa principal, indicando en el cuerpo
de la función los nombres de las variables precedidas de la palabra reservada global.
En el siguiente ejemplo, la función puede escribir el valor de la variable definida en el programa.

<?php
function prueba()
{
// Declaramos la variable $a como global
global $a;

print "<p>La variable a es $a.</p>\n";


print "\n";
}

$a = 100;
prueba();
?>
<p>La variable a es 100.</p>
El acceso a las variables globales es completo, es decir, las variables se pueden modificar, como muestra el
siguiente ejemplo:

<?php
function prueba()
{
global $a;

// Modificamos la variable $a en la función


$a = 50;
}

$a = 100;
prueba();
print "<p>La variable a es $a.</p>\n";
?>
<p>La variable a es 50.</p>

Funciones con argumentos (valores)

Podemos enviar datos a una función incluyendo argumentos en su llamada. En la definición de la función
deben indicarse los argumentos que se van a recibir, escribiéndolos entre los paréntesis como variables,
separadas por comas. En el programa principal, los datos que se quieren enviar a la función simplemente se
incluyen en la llamada a la función escribiéndolos entre los paréntesis, separados por comas. La función
guarda los valores en los argumentos (como variables) en el orden indicado en la definición. Los argumentos
se pueden utilizar o no en la función, pero si una función se define con argumentos, la llamada a la función
debe incluir todos los argumentos indicados en la definición.
function nombreDelaFuncion($argumento_1, $argumento_2, etc ...) {
bloque_de_sentencias
}
En este apartado se trata el caso más sencillo, es decir, cuando los argumentos son simplemente valores
(número, cadenas, matrices, etc.). En los dos apartados siguientes se tratan los casos en los que los
argumentos son variables del programa principal.
En el ejemplo siguiente, enviamos una cadena a la función para que la incluya en la salida de la función.

<?php
function saludo($nombre)
{
print "<p>Hola, $nombre!</p>\n";
}

saludo("Don Pepito");
?>
<p>Hola, Don Pepito!</p>
En el ejemplo siguiente, enviamos una cadena y un número a la función.

<?php
function saludo($nombre, $veces)
{
for ($i = 0; $i < $veces; $i++) {
print "<p>Hola, $nombre!</p>\n";
print "\n";
}
}

saludo("Don Pepito", 3);


?>
<p>Hola, Don Pepito!</p>

<p>Hola, Don Pepito!</p>

<p>Hola, Don Pepito!</p>


El ejemplo siguiente produce un error porque en él se llama sin argumentos a una función que tiene definido
un argumento.

<?php
// Definición de la función prueba($x) con 1 argumento
function prueba($x)
{
// Esta función no hace nada
}

// LLamamos a la función sin enviar el argumento


prueba();
?>
Fatal error: Uncaught ArgumentCountError: Too few arguments to function
prueba(), 0 passed in ejemplo.php on line 9 and exactly 1 expected in
ejemplo.php:3
Stack trace:
#0 ejemplo.php(9): prueba()
#1 {main}
thrown in ejemplo.php on line 3
PHP no produce error si se envía un argumento a una función que no tiene definidos argumentos, pero el
argumento enviado no se utiliza para nada.

<?php
function saludo()
{
print "<p>Hola!</p>\n";
}

saludo("Don Pepito");
?>
<p>Hola</p>
De la misma manera que el programa principal puede enviar valores a una función, una función puede
devolver uno o varios valores al programa principal. La palabra reservada return permite indicar la variable
que se devuelve.
El ejemplo siguiente muestra una función que devuelve la suma de los valores recibidos:

<?php
function suma($arg1, $arg2)
{
return $arg1 + $arg2;
}

$a = 20;
$b = 30;
$suma = suma($a, $b);
print "<p>$a + $b = $suma</p>\n";
print "\n";
print "<p>$a + $b = " . suma($a, $b) . "</p>\n";
?>
<p>20 + 30 = 50</p>

<p>20 + 30 = 50</p>
La ejecución de una función se interrumpe cuando se ejecuta un return:

<?php
function suma($arg1, $arg2)
{
return $arg1 + $arg2;
// Esta instrucción no se ejecuta nunca.
print "<p>Hola</p>\n";
}

$a = 20;
$b = 30;
print "<p>$a + $b = " . suma($a, $b) . "</p>\n";
?>
<p>20 + 30 = 50</p>
Una función puede devolver varios valores, devolviendo una matriz. Desde PHP 7.1 (publicado en diciembre
de 2016) para recoger los valores devueltos se pueden utilizar corchetes. En el ejemplo siguiente, la función
devuelve la suma y el producto de los valores recibidos:
<?php
function sumaProducto($arg1, $arg2)
{
return [$arg1 + $arg2, $arg1 * $arg2];
}

$a = 20;
$b = 30;
[$suma, $producto] = sumaProducto($a, $b);
print "<p>$a + $b = $suma</p>\n";
print "\n";
print "<p>$a * $b = $producto</p>\n";
?>
<p>20 + 30 = 50</p>

<p>20 * 30 = 600</p>

Funciones con argumentos predeterminados

En PHP se pueden definir funciones con argumentos predeterminados, de manera que si en la llamada a la
función no se envía un argumento, la función asume un valor predeterminado. Lógicamente, los argumentos
predeterminados deben ser los últimos en la lista de argumentos, para evitar ambigüedades.
Los argumentos predeterminados se establecen en la definición de la función, igualando el nombre del
argumento a su valor predeterminado.
El ejemplo siguiente muestra una función que calcula diferentes tipos de media (aritmética, geométrica,
armónica). Los argumentos de la función son los números cuya media se debe calcular y el tipo de media a
calcular. En el ejemplo, el tipo de media predeterminado es la media aritmética.
<?php
// ESTA ES LA DEFINICIÓN DE LA FUNCIÓN calculaMedia
function calculaMedia($arg1, $arg2, $arg3 = "aritmética")
{
if ($arg3 == "aritmética") {
$media = ($arg1 + $arg2) / 2;
} elseif ($arg3 == "geométrica") {
$media = sqrt($arg1 * $arg2) / 2;
} elseif ($arg3 == "armónica") {
$media = 2 * ($arg1 * $arg2) / ($arg1 + $arg2);
}
return $media;
}

// ESTO SON EJEMPLOS DE USO DE LA FUNCIÓN calculaMedia


$dato1 = 12;
$dato2 = 16;

// EL TERCER ARGUMENTO INDICA EL TIPO DE MEDIA A CALCULAR


$media = calculaMedia($dato1, $dato2, "geométrica");
print "<p>La media geométrica de $dato1 y $dato2 es $media.</p>\n";
print "\n";

// AL NO PONER EL TERCER ARGUMENTO, DEVUELVE LA MEDIA ARITMÉTICA


$media = calculaMedia($dato1, $dato2);
print "<p>La media aritmética de $dato1 y $dato2 es $media.</p>\n";
?>
<p>La media geométrica de 12 y 16 es 6.9282032302755.</p>

<p>La media aritmética de 12 y 16 es 14.</p>

Bibliotecas

Las bibliotecas son archivos php que se pueden incluir en cualquier otro archivo php. Las bibliotecas se suelen
utilizar para centralizar fragmentos de código que se utilizan en varias páginas. De esa manera, si se quiere
hacer alguna modificación, no es necesario hacer el cambio en todas las páginas sino únicamente en la
biblioteca.
Por ejemplo, si definimos en la biblioteca una función que imprima la cabecera de las páginas, desde cualquier
página se puede incluir la biblioteca mediante la construcción include y llamar a la función como si se hubiera
definido en la propia página:
biblioteca.php

<?php
function cabecera($titulo)
{
print "<!DOCTYPE html>\n";
print "<html lang=\"es\">\n";
print "<head>\n";
print " <meta charset=\"utf-8\">\n";
print " <title>$titulo</title>\n";
print " <meta name=\"viewport\" content=\"width=device-width, initial-
scale=1.0\">\n";
print " <link rel=\"stylesheet\" href=\"estilo.css\" title=\"Color\">\n";
print "</head>\n";
print "\n";
print "<body>\n";
print " <h1>$titulo</h1>\n";
print "\n";
}
?>
pagina-1.php

<?php
include "biblioteca.php";
cabecera("Página de ejemplo");
print " <p>Esta página es válida</p>";
?>
</body>
</html>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Página de ejemplo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="estilo.css" title="Color">
</head>

<body>
<h1>Página de ejemplo</h1>

<p>Esta página es válida</p>


</body>
</html>
pagina-2.php

<?php
include "biblioteca.php";
cabecera("Otra página de ejemplo");
print " <p>Esta página también es válida</p>";
?>
</body>
</html>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Otra página de ejemplo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="estilo.css" title="Color">
</head>

<body>
<h1>Otra página de ejemplo</h1>

<p>Esta página también es válida</p>


</body>
</html>

Se pueden crear todas las bibliotecas que se necesiten e incluir cualquier número de bibliotecas en cualquier
punto de un programa. Las bibliotecas pueden a su vez incluir otras bibliotecas.
Si una función está definida en una biblioteca, se debe incluir la biblioteca antes de llamar a la función o se
generará un error.
En el ejemplo siguiente, las bibliotecas modifican variables, lo que afecta a su valor.
biblioteca-1.php

<?php
$i = 1;
?>
biblioteca-2.php

<?php
$i = $i + 10;
?>
Programa:

<?php
include "biblioteca-1.php";
print "<p>Ahora \$i vale $i</p>\n";
include "biblioteca-2.php";
print "<p>Ahora \$i vale $i</p>\n";
include "biblioteca-2.php";
print "<p>Ahora \$i vale $i</p>\n";
?>
<p>Ahora $i vale 1</p>
<p>Ahora $i vale 11</p>
<p>Ahora $i vale 21</p>
Existe una construcción similar a include, la construcción require. La diferencia con respecto a include es
que require produce un error si no se encuentra el archivo (y no se procesa el resto de la página), mientras
que include sólo produce un aviso (y se procesa el resto de la página).
En un mismo archivo php se pueden incluir varias construcciones include o require, pero si las bibliotecas
incluidas contienen definiciones de funciones, al incluir de nuevo la definición de la función se genera un
error.
Para que no ocurra este problema se pueden utilizar las funciones include_once o require_once, que también
incluyen los ficheros pero que, en caso de que los ficheros ya se hayan incluido, entonces no los incluyen.
Las bibliotecas están habitualmente en el mismo servidor que los programas, pero podrían estar en otros
servidores y acceder a ellas por HTTP, no como ficheros locales. La directiva de
configuración allow_url_include permite acceder a bibliotecas por HTTP (suele estar desactivada).
Las cuatro construcciones (include, require, include_once y require_once) pueden utilizarse escribiendo entre
paréntesis el nombre de los ficheros o sin escribir paréntesis.
La guía de estilo del proyecto PEAR prescribe el uso de la construcción require_once en el caso de bibliotecas
cuya inclusión no dependa de ninguna condición y que no se utilicen paréntesis alrededor de los nombres de
las bibliotecas.
PHP Data Objects (PDO)
La extensión PDO (PHP Data Objects) permite acceder a distintas bases de datos (MySQL/MariaBD,
PostgreSQL, Oracle, MS SQL Server, SQLite, Firebird, DB2, Informix, etc.) de una forma uniforme, lo que facilita
la portabilidad de las aplicaciones. La portabilidad entre bases de datos no es absoluta debido por ejemplo a
las diferencias entre diferentes bases de datos en aspectos como la forma de conectarse o la sintaxis del
lenguaje de definición de datos. Para ilustrar esas diferencias y como tratarlas adecuadamente, se ofrecen
ejemplos de código específicos para SQLite y para MySQL.
La extensión PDO no evalúa la corrección de las consultas SQL, aunque sí implementa algunas medidas de
seguridad mediante consultas preparadas, como se comenta en el apartado correspondiente.

Conceptos básicos de PDO

PDO es una biblioteca de PHP orientada a objetos, pero se puede utilizar sin problemas en un programa no
orientado a objetos. Tan solo será necesario utilizar la notación propia de la orientación orientada a objetos al
manipular el objeto PDO.

Conexión con la base de datos

Para trabajar con una base de datos en nuestro programa, simplemente nos conectaremos con la base de
datos creando un objeto PDO. La información necesaria para la conexión con la base de datos específica se
incluye como argumento:
// CONEXIÓN CON LA BASE DE DATOS
$pdo = new PDO("informacion-para-la-conexion");

Manejo de errores de PDO

PDO permite elegir al usuario entre tres formas distintas de gestionar los errores encontrado al realizar las
consultas (normalmente por errores de sintaxis de SQL):
 PDO::ERRMODE_SILENT

En este modo, los errores de PDO no interrumpen la ejecución del programa, simplemente se guardan
y se pueden consultar mediante los métodos errorCode() y errorInfo. Si utilizamos este modo, nuestro
programa tiene que encargarse de comprobar tras cada consulta si ha habido un error y tenerlo en
cuenta.
 PDO::ERRMODE_WARNING

En este modo, PDO además de guardar los errores genera un aviso de tipo E_WARNING que,
dependiendo de la configuración de error_reporting, se mostrará o no en pantalla.
 PDO::ERRMODE_EXCEPTION

En este modo, PDO genera una excepción de clase PDOException. Si utilizamos este modo, nuestro
programa tiene que gestionar las excepciones, porque si no el programa se interrumpe con un error
E_ERROR.
Hasta PHP 8.0, publicado en 2020, el modo predeterminado era ERRMODE_SILENT, pero desde esa versión es
ERRMODE_EXCEPTION. En estos apuntes se utiliza el modo PDO::ERRMODE_SILENT, que se puede abordar
con simples estructuras if .. else ..., mientras que el modo PDO::ERRMODE_EXCEPTION requiere estructuras
try ... catch ... que no se tratan actualmente en estos apuntes.
El modo de manejo de errores se selecciona activando el atributo PDO::ATTR_ERRMODE tras conectarse con
la base de datos, como se comenta más adelante en esta lección en el apartado dedicado a la conexión con la
base de datos:
$tmp->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);

Ejecución de las consultas

Una vez realizada la conexión, las consultas SQL se realizar a través del objeto PDO. La ejecución de la consulta
y el tratamiento de la respuesta se puede hacer de cuatro formas distintas, atendiendo a dos criterios:
Por un lado, se debe considerar si la consulta incluye información que nos ha llegado a través de un
formulario. Por otro lado, se debe considerar si la consulta puede devolver registros:
Si la consulta no incluye datos provinientes de un formulario, se puede utilizar el método PDO-
>query(consulta):

// EJECUCIÓN DE UNA CONSULTA SIN DATOS PROVENIENTES DE UN FORMULARIO


$pdo->query("consulta");
Si por el tipo de consulta de que se trata sabemos que la consulta no va a devolver registros (por ejemplo
eliminación de tabla), la consulta devolverá simplemente true (si la consulta se realiza con éxito) o false (si la
consulta falla). En ese caso podemos utilizar directamente el resultado de la consulta en una estructura if ...
else ... para gestionar las tareas a realizar en cada caso. Conviene escribir la condición en negativo (con
exclamación delante), para escribir en primer lugar el caso en el que la consulta falle, que normalmente
contendrá menos líneas de programa:

// EJECUCIÓN DE UNA CONSULTA QUE NO VA A DEVOLVER REGISTROS


if (!$pdo->query("consulta")) {
... // Si la consulta falla
} else {
... // Si la consulta se ejecuta correctamente
}
Si la consulta puede devolver registros, devolverá false (si la consulta falla) o cero, uno o varios registros (por
ejemplo consulta de selección de datos). En ese caso conviene guardar el resultado de la consulta en una
variable auxiliar y escribir la estructura if ... else ... a partir de esa variable auxiliar:

// EJECUCIÓN DE UNA CONSULTA QUE PUEDE DEVOLVER REGISTROS


$resultado = $pdo->query("consulta")
if (!$resultado) {
... // Si la consulta falla
} else {
... // Si la consulta se ejecuta correctamente
}
Si la consulta sí incluye datos provenientes de un formulario, se deben utilizar consultas preparadas para
evitar ataques de inyección SQL de los que el método query() no nos protege. El método para efectuar
consultas es primero preparar la consulta con PDO->prepare(consulta) y después ejecutarla con PDO-
>execute([parámetros]), que devuelve el resultado de la consulta.

// EJECUCIÓN DE UNA CONSULTA CON DATOS PROVENIENTES DE UN FORMULARIO


$resultado = $pdo->prepare("consulta");
$resultado->execute([parámetros de la consulta]);
En este caso, independientemente de que la consulta devuelva o no registros, debemos utilizar siempre una
variable auxiliar y escribir la estructura if ... else ... a partir de esa variable auxiliar, puesto que debemos
comprobar si ha fallado tanto la preparación de la consulta como la ejecución de la sentencia preparada:
// EJECUCIÓN DE UNA CONSULTA PREPARADA
$resultado = $pdo->prepare("consulta")
if (!$resultado) {
... // Si la preparación de la consulta falla
} elseif (!$resultado->execute([parámetros de la consulta]) {
... // Si la ejecución de la consulta falla
} else {
... // Si la consulta se ejecuta correctamente
}
Cuando la consulta falle, es conveniente mostrar al usuario el motivo del fallo. Para ello, podemos utilizar los
métodos errorCode() y errorInfo(). errorCode() devuelve el código de error SQLSTATE definido en la norma
ANSI SQL. errorInfo() devuelve una matriz con el código de error SQLSTATE, el código de error específico del
driver y el mensaje de error específico del driver.
En los ejemplos y soluciones de ejercicios de estos apuntes cuando se produce un error se muestra un
mensaje en español y a continuación el código de error SQLSTATE y el mensaje de error específico del driver.
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
En los ejemplos anteriores se ha escrito la consulta en la llamada al método, pero es habitual definir una
variable $consulta que contenga la consulta y utilizar esa variable en la llamada al método:
// En una sola línea de programa
$resultado = $pdo->query("SELECT * FROM tabla");

// En dos líneas de programa


$consulta = "SELECT * FROM tabla";
$resultado = $pdo->query($consulta);
Utilizar una variable auxiliar permite por ejemplo imprimir la consulta mientras se está programando para
comprobar que no tiene errores.
$consulta = "SELECT * FROM tabla";
print "<p>Consulta: $consulta</p>\n";
// var_dump($consulta);
$resultado = $pdo->query($consulta);

Gestión de los registros devueltos por la consulta

Cuando la consulta puede devolver registros, se debe guardar la respuesta en una variable auxiliar. Esa
variable es de un tipo especial llamado recurso que no se puede acceder directamente, pero de la que
podemos ir extrayendo uno a uno los registros mediante un bucle foreach () o mediante los métodos fetch() o
fetchColumn():
Si la consulta devuelve un único registro que contiene la respuesta buscada en la primera columna se puede
utilizar el método PDOStatement->fetchColumn() para recuperar la primera columna del registro.

// CONSULTA DE SELECCIÓN DE REGISTROS QUE DEVUELVE UN ÚNICO REGISTRO DE UNA


COLUMNA
$consulta = "SELECT COUNT(*) FROM tabla";

$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>La tabla contiene {$resultado->fetchColumn()}
registro(s).</p>\n";
}
Si la consulta devuelve un único registro, se puede utilizar el método PDOStatement->fetch() para recuperar el
registro en forma de matriz. De forma predeterminada, los valores del registro aparecen repetidos en la
matriz y para acceder a los valores se puede utilizar como índice tanto los nombres de las columnas de la tabla
como números enteros correlativos (0, 1, 2, etc.). Si se enviara como argumento la constante
PDO::FETCH_ASSOC, los índices de la matriz serían únicamente los nombres de las columnas de la tabla.

// CONSULTA DE SELECCIÓN DE REGISTROS QUE DEVUELVE UN ÚNICO REGISTRO (O NINGUNO)


$id = id; // Normalmente este valor vendrá de un formulario

$consulta = "SELECT * FROM tabla WHERE id=:id"; // Normalmente solo habrá un


registro (o ninguno) con un id determinado

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":id" => $id])) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
$registro = $resultado->fetch();
print " <p><strong>Registro obtenido</strong></p>\n";
print "\n";
print " <p>$registro[columna1] - $registro[columna2] - etc.</p>\n";
print "\n";
}
Si la consulta devuelve varios registros y necesitamos acceder a todos los registros a la vez para realizar alguna
operación, se puede utilizar el método PDOStatement->fetchAll() para recuperar todos los registros en forma
de matriz bidimensional.

// CONSULTA DE SELECCIÓN DE REGISTROS QUE PUEDE DEVOLVER VARIOS REGISTROS (O UNO


O NINGUNO)
$consulta = "SELECT * FROM tabla";

$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!count($registros = $resultado->fetchAll())) {
print " <p class=\"aviso\">No se ha creado todavía ningún
registro.</p>\n";
} else
print " <p><strong>Registro(s) obtenido(s)</strong></p>\n";
print " <ul>\n";
foreach ($registros as $registro) {
print " <li>$registro[columna1] - $registro[columna2] -
etc.</li>\n";
}
print " </ul>\n";
print "\n";
}
Si la consulta devuelve varios registros y simplemente queremos acceder a los registros de forma consecutiva,
podemos recorrer la variable que guarda la respuesta con un bucle foreach ().:

// CONSULTA DE SELECCIÓN DE REGISTROS QUE PUEDE DEVOLVER VARIOS REGISTROS (O UNO


O NINGUNO)
$consulta = "SELECT * FROM tabla";

$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p><strong>Registro(s) obtenido(s)</strong></p>\n";
print " <ul>\n";
foreach ($resultado as $registro) {
print " <li>$registro[columna1] - $registro[columna2] -
etc.</li>\n";
}
print " </ul>\n";
print "\n";
}

Desconexión con la base de datos

Para desconectar con la base de datos, simplemente hay que destruir el objeto PDO.
$pdo = null;
Aunque no se destruya el objeto PDO, PHP lo destruye al terminar la página, por lo que a menudo la
instrucción no se suele escribir.

Consultas preparadas: seguridad en las consultas

Para evitar ataques de inyección SQL (en la lección Inyecciones SQL se comentan los ataques más
elementales), se recomienda el uso de sentencias preparadas, en las que PDO se encarga de "desinfectar" los
datos. En general, cualquier consulta que incluya datos provenientes de un formulario (o en general,
provenientes del usuario de la aplicación) debe realizarse mediante consultas preparadas.

Consultas preparadas
El método para efectuar consultas preparadas es primero preparar la consulta con PDO-
>prepare($consulta) y después ejecutarla con PDO->execute([parámetros]), que devuelve el resultado de la
consulta.
// Consulta preparada
$consulta = "SELECT * FROM tabla";
$resultado = $pdo->prepare($consulta);
$resultado->execute();
Si el programa incluye directamente en la consulta los datos recibidos a través de un formulario, PDO no
puede hacer ninguna "desinfección" de los datos, ya que PDO no puede identificar qué parte de la consulta es
la que ha llegado de un formulario y que puede haber manipulado la consulta original:
$valor1 = $_REQUEST["valor1"];
$valor2 = $_REQUEST["valor2"];

// ¡CUIDADO! DESACONSEJADO: PDO NO PUEDE DESINFECTAR LOS DATOS


$consulta = "SELECT COUNT(*) FROM tabla
WHERE columna1=$valor1
AND columna2=$valor2";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute();) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Se han encontrado {$resultado->fetchColumn()}
registro(s).</p>\n";
print "\n";
}
Para que PDO pueda desinfectar los datos provenientes de un formulario, estos deben enviarse al ejecutar la
consulta, no al prepararla. Para ello, al definir la consulta es necesario indicar la posición de los datos y al
ejecutar la consulta es necesario indicar el valor de los datos en forma de matriz. La posición de los datos se
puede indicar de dos maneras distintas, mediante parámetros o mediante interrogantes (se aconseja la
utilización de parámetros).
consulta preparada mediante parámetros (:parametro)

En este caso las posiciones en la que se insertarán los datos provenientes del formulario se indican mediante
cadenas de texto precedidas de dos puntos (:). La matriz con los datos debe incluir los nombres de los
parámetros y los valores que sustituyen a los parámetros (el orden no es importante), como muestra el
siguiente ejemplo:
$valor1 = $_REQUEST["valor1"];
$valor2 = $_REQUEST["valor2"];

// CONSULTA PREPARADA CON PARÁMETROS: PDO PUEDE DESINFECTAR LOS DATOS


$consulta = "SELECT COUNT(*) FROM tabla
WHERE columna1=:valor1
AND columna2=:valor2";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":valor1" => $valor1, ":valor2" => $valor2]);) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Se han encontrado {$resultado->fetchColumn()}
registro(s).</p>\n";
print "\n";
}
consulta preparada mediantes interrogantes (?)

En este caso las posiciones en la que se insertarán los datos provenientes del formulario se indican mediante
interrogantes (?). La matriz con los datos debe incluir los valores que sustituyen a los interrogantes (en el
mismo orden en que aparecen en la consulta), como muestra el siguiente ejemplo:
$valor1 = $_REQUEST["valor1"];
$valor2 = $_REQUEST["valor2"];

// CONSULTA PREPARADA CON INTERROGANTES: PDO PUEDE DESINFECTAR LOS DATOS


$consulta = "SELECT COUNT(*) FROM tabla
WHERE columna1=?
AND columna2=?";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([$valor1, $valor2]);) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Se han encontrado {$resultado->fetchColumn()}
registro(s).</p>\n";
print "\n";
}
Notas:
 Aunque no vayan a causar problemas en las consultas, sigue siendo conveniente tratar los datos
recibidos para eliminar los espacios en blanco iniciales y finales, tratar los caracteres especiales del
html, etc., como se comenta en la lección de Recogida de datos.
 La sintaxis mediante interrogantes es más cómoda, pero tiene el inconveniente de que podemos
equivocarnos en el orden de los valores. Sin embargo con la sintaxis mediante parámetros, aunque sea
más larga de escribir, no se puede cometer ese error.

Restricciones en los parámetros de consultas preparadas


Debido a que las consultas preparadas se idearon para optimizar el rendimiento de las consultas, el uso de
parámetros tiene algunas restricciones. Por ejemplo
 los identificadores (nombres de tablas, nombres de columnas, etc) no pueden sustituirse por
parámetros
 los dos elementos de una igualdad no pueden sustituirse por parámetros
 en general no pueden utilizarse parámetros en las consultas DDL (lenguaje de definición de datos)
(nombre y tamaño de las columnas, etc.)

Si no podemos usar parámetros, no queda más remedio que incluir los datos en la consulta. Como en ese caso
PHP no hace ninguna desinfección de los datos, la desinfección la tenemos que hacer nosotros previamente.
Como en estos casos los valores introducidos por el usuario suelen tener unos valores restringidos (por
ejemplo, si el usuario puede elegir una columna de una tabla, los nombres de las columnas están
determinadas y el usuario sólo puede elegir uno de ellos), podemos crear una función de recogida de datos
específica que impida los ataques de inyección por parte del usuario, como muestra el siguiente ejemplo:
// FUNCIÓN DE RECOGIDA DE UN DATO QUE SÓLO PUEDE TOMAR DETERMINADOS VALORES
function recogeValores($var, $valoresValidos, $valorPredeterminado)
{
if (isset($_REQUEST[$var]) && in_array($_REQUEST[$nombre], $valoresValidos))
{
return $_REQUEST[$var];
} else {
return $valorPredeterminado;
}
}

// EJEMPLO DE USO DE LA FUNCIÓN ANTERIOR

// Matriz con los nombres válidos de las columnas de la tabla


$columnas = [
"columna1",
"columna2",
...
];

$columna = recogeValores("columna", $columnas, "columna1");


$valor1 = $_REQUEST["valor1"];

// CONSULTA PREPARADA CON PARÁMETROS: PDO PUEDE DESINFECTAR LOS DATOS


$consulta = "SELECT * FROM tabla
WHERE columna1=:valor1
ORDER BY $columna ASC";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":valor1" => $valor1]);) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
...

Ejemplos de código para SQLite y MySQL

A continuación se ofrecen ejemplos de código de cómo se podría trabajar con PDO para realizar las tareas más
habituales de gestión de una base de datos.
La base de datos de estos ejemplos tiene una estructura muy simple: una sola tabla personas con tres
columnas: un identificador numérico (id), el nombre y los apellidos de una persona.
La estructura general de estas consultas se repite con ligeras variaciones. La estructura concreta viene
impuesta por dos aspectos:
 Si el resultado de la consulta va a ser únicamente true o false, o si el resultado pueden ser uno o varios
registros con una o varias columnas de datos. Si se pueden obtener registros, el resultado de la
consulta debe guardarse en una variable auxiliar.
 Si en la consulta deben incluirse datos recibidos de un formulario o no. Si se incluyen datos recibidos
de un formulario, es necesario utilizar consultas preparadas para prevenir ataques de inyección SQL. Si
se utiliza una consulta preparada, el resultado de la preparación debe guardarse en una variable
auxiliar.

Opciones del programa

Para dotar de flexibilidad a la aplicación, la aplicación incluirá opciones de configuración en forma de


variables. Distinguiremos entre opciones disponibles para el administrador de la aplicación y opciones
disponibles para el programador. Aunque la distinción es a veces algo arbitraria, el objetivo es ayudar al
administrador de la aplicación en su puesta en marcha:
 Las opciones de administrador son las opciones que el administrador debe establecer al instalar el
programa y las opciones que el programador pone a disposición del administrador para que
personalice la aplicación.
 Las opciones de programador son las opciones que el administrador no necesita modificar para instalar
el programa, pero que el programador ha preparado para dar mayor flexibilidad a la aplicación. Por
supuesto, el administrador puede modificarlas si entiende las consecuencias que podría provocar su
modificación.

Estas podrían ser las opciones para SQLite:


// SQLITE: OPCIONES DE CONFIGURACIÓN DEL PROGRAMA

// OPCIONES DISPONIBLES PARA EL ADMINISTRADOR DE LA APLICACIÓN


// Configuración para SQLite
$cfg["sqliteDatabase"] = "db.sqlite"; // Ubicación de
la base de datos

// Configuración de la tabla Personas


$cfg["dbPersonasTamNombre"] = 40; // Tamaño de la
columna Personas > Nombre
$cfg["dbPersonasTamApellidos"] = 60; // Tamaño de la
columna Personas > Apellidos
// OPCIONES DISPONIBLES PARA EL PROGRAMADOR DE LA APLICACIÓN
// Base de datos
$cfg["dbPersonasTabla"] = "personas"; // Nombre de la
tabla Personas
Estas podrían ser las opciones para MySQL:
// MYSQL: OPCIONES DE CONFIGURACIÓN DEL PROGRAMA

// OPCIONES DISPONIBLES PARA EL ADMINISTRADOR DE LA APLICACIÓN


// Configuración para MySQL
$cfg["mysqlHost"] = "mysql:host=localhost"; // Nombre de
host
$cfg["mysqlUser"] = ""; // Nombre de
usuario
$cfg["mysqlPassword"] = ""; // Contraseña
de usuario
$cfg["mysqlDatabase"] = ""; // Nombre de la
base de datos

// Configuración de la tabla Personas


$cfg["dbPersonasTamNombre"] = 40; // Tamaño de la
columna Personas > Nombre
$cfg["dbPersonasTamApellidos"] = 60; // Tamaño de la
columna Personas > Apellidos

// OPCIONES DISPONIBLES PARA EL PROGRAMADOR DE LA APLICACIÓN


// Base de datos
$cfg["dbPersonasTabla"] = "$cfg[mysqlDatabase].personas"; // Nombre de la
tabla Personas

Conexión con la base de datos

Para conectar con la base de datos hay que crear una instancia de la clase PDO, que se utiliza en todas las
consultas posteriores. En cada página php que incluya consultas a la base de datos es necesario conectar
primero con la base de datos.
Si no se puede establecer la conexión con la base de datos, puede deberse a que la base de datos no esté
funcionando, a que los datos de usuario no sean correctos, a que no esté activada la extensión pdo o (en el
caso de SQLite) que el camino donde se quiere guardar la base de datos no exista.

Conexión con SQLite 3

Para poder utilizar SQLite mediante PDO, debe estar activada la extensión pdo_sqlite en el archivo de
configuración php.ini (véase el apartado extensión pdo_sqlite en la lección de configuración de Apache y
PHP).
En SQLite, no se hace una conexión a un servidor, sino que simplemente se indica el archivo que va a contener
la base de datos. En SQLite no hay un servidor que gestiona todas las bases de datos, sino que cada base de
datos es un archivo independiente.
PDO puede crear el archivo SQLite, pero no puede crear la ruta hasta el archivo.
 Si se indica simplemente el nombre del archivo SQLite, el archivo se creará en el mismo directorio que
se encuentra el programa PHP. No se aconseja hacerlo así por dos motivos. Por un lado, si las páginas
del programa se encuentran distribuidas en varios directorios, cada página accedería a una base de
datos distinta creada en cada directorio. Por otro lado, al guardar la base de datos en un directorio
público, cualquier visitante podría obtener la base de datos completa. Por eso se recomienda guardar
el archivo SQLite en un directorio fuera del directorio público, teniendo en cuenta que el directorio
debe existir y el servidor web debe tener permisos de escritura en él.

// SQLITE: Conexión con la base de datos

function conectaDb()
{
global $cfg;

try {
$tmp = new PDO("sqlite:$cfg[sqliteDatabase]");
$tmp->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$tmp->query("PRAGMA foreign_keys = ON");
$tmp->query("PRAGMA encoding = 'UTF-8'");
return $tmp;
} catch (PDOException $e) {
print " <p class=\"aviso\">Error: No puede conectarse con la base de
datos. {$e->getMessage()}</p>\n";
exit;
}
}

// CONEXIÓN CON LA BASE DE DATOS


// La conexión se debe realizar en cada página que acceda a la base de datos
$pdo = conectaDb();
Notas:
 En las soluciones de los ejercicios proporcionadas en estos apuntes, los archivos se guardan en el
directorio /tmp/. Para que funcionen las soluciones, se debe crear ese directorio o cambiarlo a otro.
 En caso de error, la función conectaDb() imprime unos mensajes de error y termina el programa. Si
quisiéramos completar una página correcta, deberíamos imprimir el pie de página en caso de error y
asegurarnos de que se ha escrito la cabecera antes de conectarse a la base de datos.

Conexión con MySQL

En el caso de MySQL, para crear el objeto PDO se necesita proporcionar el nombre del servidor, el nombre de
usuario y la contraseña. En el ejemplo siguiente esos datos se proporcionan como constantes que deberían
definirse en el programa.
Para poder acceder a MySQL mediante PDO, debe estar activada la extensión php_pdo_mysql en el archivo de
configuración php.ini (véase el apartado extensión pdo_mysql en la lección de configuración de Apache y
PHP).
// MYSQL: Conexión con la base de datos

function conectaDb()
{
global $cfg;

try {
$tmp = new PDO($cfg["mysqlHost"], $cfg["mysqlUser"],
$cfg["mysqlPassword"]);
$tmp->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$tmp->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$tmp->exec("set names utf8mb4");
return $tmp;
} catch (PDOException $e) {
print " <p class=\"aviso\">Error: No puede conectarse con la base de
datos. {$e->getMessage()}</p>\n";
exit;
}
}

// EJEMPLO DE USO DE LA FUNCIÓN conectaDb()


// La conexión se debe realizar en cada página que acceda a la base de datos
$pdo = conectaDb();
Copiar

Creación y borrado de bases de datos y tablas: Consultas CREATE DATABASE, DROP DATABASE, CREATE
TABLE, DROP TABLE

Las consultas de creación no son iguales en MySQL y SQLite. Para que una misma aplicación pueda trabajar
con una u otra base de datos, en el apartado aplicación configurable estas consultas se incluyen en bibliotecas
específicas.
 Las consultas de creación de bases de datos CREATE DATABASE suelen ser específicas de cada base de
datos. En el caso de utilizar SQLite, en realidad no tiene sentido crear o borrar la base de datos ya que
con SQLite cada base de datos es un fichero distinto y al conectar con la base de datos ya se dice con
qué archivo se va a trabajar y se crea en caso necesario.
 Las consultas de creación de tablas CREATE TABLE suelen ser específicas de cada base de datos. Los
ejemplos de este apartado no utilizan sentencias preparadas (en caso de utilizarse sentencias
preparadas, las variables no podrían ir como parámetros por tratarse de sentencias DDL).

Creación y borrado de tablas en SQLite

Con SQLite no tiene sentido crear o borrar la base de datos, ya que SQLite trabaja con ficheros y cada fichero
es una base de datos. Tan solo es necesario borrar y crear las tablas.
Para borrar una tabla, se utiliza la consulta DROP TABLE. Esta consulta no es específica de SQlite y funcionaría
con otras bases de datos. Se ha añadido la condición IF EXISTS porque en algunas versiones de SQLite la
consulta DROP TABLE da error si la tabla no existe.
// CONSULTA DE BORRADO DE TABLA
$consulta = "DROP TABLE IF EXISTS $cfg[dbPersonasTabla]";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al borrar la tabla. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Tabla borrada correctamente (si existía).</p>\n";
}
print "\n";
Para crear una tabla, se utiliza la consulta CREATE TABLE. Las consultas de creación de tabla suelen ser
específicas de cada base de datos. El ejemplo no utiliza sentencias preparadas (en caso de utilizarse
sentencias preparadas, las variables no podrían ir como parámetros por tratarse de sentencias DDL).
// SQLITE: CONSULTA DE CREACIÓN DE TABLA
$consulta = "CREATE TABLE $cfg[dbPersonasTabla] (
id INTEGER PRIMARY KEY,
nombre VARCHAR($cfg[dbPersonasTamNombre]),
apellidos VARCHAR($cfg[dbPersonasTamApellidos])
)";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al crear la tabla. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Tabla creada correctamente.</p>\n";
}
print "\n";

Creación y borrado de bases de datos y tablas en MySQL

Con MySQL, borraremos la base de datos (y las tablas existentes), crearemos de nuevo la base de datos y
crearemos la tabla.
Para borrar una base de datos, se utiliza la consulta DROP DATABASE. Se ha añadido la condición IF EXISTS
porque en algunas bases de datos la consulta DROP DATABASE da error si la tabla no existe.
// MYSQL: CONSULTA DE BORRADO DE BASE DE DATOS
$consulta = "DROP DATABASE IF EXISTS $cfg[mysqlDatabase]";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al borrar la base de datos.
SQLSTATE[{$pdo->errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Base de datos borrada correctamente (si existía).</p>\n";
}
print "\n";
Para crear una base de datos, se utiliza la consulta CREATE DATABASE.
// MYSQL: CONSULTA DE CREACIÓN DE BASE DE DATOS
$consulta = "CREATE DATABASE $cfg[mysqlDatabase]
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al crear la base de datos.
SQLSTATE[{$pdo->errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Base de datos creada correctamente.</p>\n";
print "\n";
}
Nota: El juego de caracteres utilizado en este curso es UTF-8, por lo que en la base de datos MySQL se utiliza
el juego de caracteres utf8mb4 (que permite almacenar cualquier carácter Unicode) y el
cotejamiento utf8mb4_unicode_ci (que implementa todos los criterios de ordenación de Unicode). Para una
explicación más detallada se puede consultar el blog de Mathias Bynens.
Para crear una tabla, se utiliza la consulta CREATE TABLE. Las consultas de creación de tabla suelen ser
específicas de cada base de datos. El ejemplo no utiliza sentencias preparadas (en caso de utilizarse
sentencias preparadas, las variables no podrían ir como parámetros por tratarse de sentencias DDL).
// MYSQL: CONSULTA DE CREACIÓN DE TABLA
$consulta = "CREATE TABLE $cfg[dbPersonasTabla] (
id INTEGER UNSIGNED AUTO_INCREMENT,
nombre VARCHAR($cfg[dbPersonasTamNombre]),
apellidos VARCHAR($cfg[dbPersonasTamApellidos]),
PRIMARY KEY(id)
)";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al crear la tabla. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Tabla creada correctamente.</p>\n";
}

Creación, actualización y borrado de registros: Consultas INSERT INTO, UPDATE, DELETE FROM

Estas consultas son iguales en MySQL y SQLite.


Para añadir un registro a una tabla, se utiliza la consulta INSERT INTO.

// CONSULTA DE INSERCIÓN DE REGISTRO


$nombre = "Pepito"; // Normalmente estos valores vendrán de un
formulario
$apellidos = "Conejo";

$consulta = "INSERT INTO $cfg[dbPersonasTabla]


(nombre, apellidos)
VALUES (:nombre, :apellidos)";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":nombre" => $nombre, ":apellidos" =>
$apellidos])) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Registro creado correctamente.</p>\n";
print "\n";
}
Para modificar un registro a una tabla, se utiliza la consulta UPDATE.

// CONSULTA DE MODIFICACIÓN DE REGISTRO


$id = "1"; // Normalmente estos valores vendrán de un
formulario
$nombre = "Pepita";
$apellidos = "Conejo";

$consulta = "UPDATE $cfg[dbPersonasTabla]


SET nombre=:nombre, apellidos=:apellidos
WHERE id=:id";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":nombre" => $nombre, ":apellidos" => $apellidos,
":id" => $id])) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Registro modificado correctamente.</p>\n";
print "\n";
}
Para borrar un registro de una tabla, se utiliza la consulta DELETE FROM.

Nota: En el ejemplo siguiente los registros a borrar se reciben en forma de matriz y se recorre la matriz
borrando un elemento en cada iteración.
// CONSULTA DE BORRADO DE REGISTROS
$id = [1 => "on", 3 => "on"]; // Normalmente este valor vendrá de un
formulario (en este caso, como matriz).

foreach ($id as $indice => $valor) {


$consulta = "DELETE FROM $cfg[dbPersonasTabla]
WHERE id=:indice";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta.
SQLSTATE[{$pdo->errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":indice" => $indice])) {
print " <p class=\"aviso\">Error al ejecutar la consulta.
SQLSTATE[{$pdo->errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Registro borrado correctamente.</p>\n";
print "\n";
}
}
Si el campo es de tipo numérico, y el valor a insertar es una cadena (como ocurre cuando recogemos el dato
de un formulario), podríamos tener un problema de tipos al insertarlo. En el caso de los sistemas gestores de
bases de datos que se usan en este curso (SQLite y MariaDB/MySQL de forma general, PostgreSQL en algún
ejercicio) la conversión de tipos es automática y la cadena se convierte automáticamente en un valor
numérico, pero puede que en otros sistemas la conversión no se realice y se produzca un error.
Si nos encontráramos con este problema, deberíamos realizar la conversión de cadena a entero. Para ello
podríamos usar la función de PHP intval() como muestra el ejemplo siguiente en el que "edad" sería un campo
INTEGER:
$consulta = "INSERT INTO $cfg[dbPersonasTabla]
(nombre, edad)
VALUES (:nombre, :edad)";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":nombre" => $nombre, ":edad" => intval($edad)]))
{
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Registro creado correctamente.</p>\n";
}
En las soluciones de los ejercicios de estos apuntes no se realiza la conversión, ya que SQLite, MySQL o
PostgreSQL no lo necesitan.

Selección de registros: Consulta SELECT

Para obtener registros que cumplan determinados criterios se utiliza una consulta SELECT. Estas consultas son
iguales en MySQL y SQLite.
Si la consulta devuelve un único registro con una sola columna se puede utilizar el método PDOStatement-
>fetchColumn() para recuperar el dato.

// CONSULTA DE SELECCIÓN DE REGISTROS QUE DEVUELVE UN ÚNICO REGISTRO DE UNA


COLUMNA
$consulta = "SELECT COUNT(*) FROM $cfg[dbPersonasTabla]";

$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>La tabla contiene {$resultado->fetchColumn()}
registro(s).</p>\n";
print "\n";
}
Si la consulta devuelve un único registro, se puede utilizar el método PDOStatement->fetch() para recuperar el
registro en forma de matriz. De forma predeterminada, los valores del registro aparecen repetidos en la
matriz y para acceder a los valores se puede utilizar como índice tanto los nombres de las columnas de la tabla
como números enteros correlativos (0, 1, 2, etc.). Si se envía como argumento la constante
PDO::FETCH_ASSOC, los índices de la matriz son únicamente los nombres de las columnas de la tabla.

// CONSULTA DE SELECCIÓN DE REGISTROS QUE DEVUELVE UN ÚNICO REGISTRO (O NINGUNO)


$id = 1 // Normalmente este valor vendrá de un formulario

$consulta = "SELECT * FROM tabla WHERE id=:id";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":id" => $id])) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
$registro = $resultado->fetch();
print " <p><strong>Registro obtenido</strong></p>\n";
print "\n";
print " <p>$registro[id] - $registro[nombre] -
$registro[apellidos].</p>\n";
print "\n";
}
Si la consulta devuelve varios registros (es decir, que la consulta puede potencialmente devolver varios
registros, aunque igual no devuelve ninguno, o devuelve sólo uno, dependiendo de la consulta concreta y de
los registros guardados), para acceder a los registros devueltos por la consulta ...

Habitualmente se utiliza un bucle foreach para recorrer todos los registros devueltos. Es importante tener en
cuenta que sólo se puede iterar una vez sobre el resultado de la consulta, ya que los registros se van
eliminado del resultado de la consulta.

// CONSULTA DE SELECCIÓN DE REGISTROS QUE PUEDE DEVOLVER VARIOS REGISTROS (O UNO


O NINGUNO)
$consulta = "SELECT * FROM $cfg[dbPersonasTabla]";

$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p><strong>Registro(s) obtenido(s)</strong></p>\n";
print " <ul>\n";
foreach ($resultado as $registro) {
print " <li>$registro[id] - $registro[nombre] -
$registro[apellidos]</li>\n";
}
print " </ul>\n";
print "\n";
}
Para este caso también se puede utilizar un bucle while y el método PDOStatement->fetch(), que recupera el
primer registro de la consulta. Es importante tener en cuenta que sólo se puede iterar una vez sobre el
resultado de la consulta, ya que los registros se van eliminado del resultado de la consulta.

// CONSULTA DE SELECCIÓN DE REGISTROS QUE PUEDE DEVOLVER VARIOS REGISTROS (O UNO


O NINGUNO)
$consulta = "SELECT * FROM $cfg[dbPersonasTabla]";

$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p><strong>Registro(s) obtenido(s)</strong></p>\n";
print " <ul>\n";
while ($registro = $resultado->fetch()) {
print " <li>$registro[id] - $registro[nombre] -
$registro[apellidos]</li>\n";
print "\n";
}
print " </ul>\n";
print "\n";
}
Los dos ejemplos anteriores (con foreach o fetch()) escribirían una lista vacía en el caso en el que la consulta
no devolviera ningún registro, ya que no escribirían nada. Si en ese caso queremos mostrar un mensaje
informativo, podríamos hacer primero una consulta que cuente el número de resultados de la consulta y, si es
mayor que cero, hacer la consulta que recupera los registros.

// CONSULTA DE SELECCIÓN DE REGISTROS QUE PUEDE DEVOLVER VARIOS REGISTROS (O UNO


O NINGUNO)
$consulta = "SELECT COUNT(*) FROM $cfg[dbPersonasTabla]";

$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif ($resultado->fetchColumn() == 0) {
print " <p>No se ha creado todavía ningún registro en la tabla.</p>\n";
} else {
$consulta = "SELECT * FROM $cfg[dbPersonasTabla]";

$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p><strong>Registro(s) obtenido(s)</strong></p>\n";
print " <ul>\n";
foreach ($resultado as $registro) {
print " <li>$registro[id] - $registro[nombre] -
$registro[apellidos]</li>\n";
}
print " </ul>\n";
print "\n";
}
}
Podemos hacer lo mismo con una sola consulta utilizando el método PDOStatement->fetchAll(), que recupera
todos los registros devueltos por la consulta en forma de matriz.

// CONSULTA DE SELECCIÓN DE REGISTROS QUE PUEDE DEVOLVER VARIOS REGISTROS (O UNO


O NINGUNO)
$consulta = "SELECT * FROM $cfg[dbPersonasTabla]";

$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!count($registros = $resultado->fetchAll())) {
print " <p class=\"aviso\">No se ha creado todavía ningún
registro.</p>\n";
} else {
print " <p><strong>Registro(s) obtenido(s)</strong></p>\n";
print " <ul>\n";
foreach ($registros as $registro) {
print " <li>$registro[id] - $registro[nombre] -
$registro[apellidos]</li>\n";
}
print " </ul>\n";
print "\n";
}

Selección de registros: Consulta SELECT LIKE

La consulta SELECT permite efectuar búsquedas en cadenas utilizando el condicional LIKE o NOT LIKE y los
comodines _ (cualquier carácter) o % (cualquier número de caracteres). Estas consultas son iguales en MySQL
y SQLite.
Ejemplos de consultas:
Registros en los que el apellido empieza por la cadena recibida:

// CONSULTA DE SELECCIÓN DE REGISTROS QUE DEVUELVE UN ÚNICO REGISTRO DE UNA


COLUMNA
$apellidos = "con"; // Normalmente este valor vendrá de un formulario
$consulta = "SELECT COUNT(*) FROM $cfg[dbPersonasTabla]
WHERE apellidos LIKE :apellidos";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":apellidos" => "$apellidos%"])) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Se han encontrado {$resultado->fetchColumn()}
registro(s).</p>\n";
print "\n";
}
Registros en los que el apellido contiene la cadena recibida:

// CONSULTA DE SELECCIÓN DE REGISTROS QUE DEVUELVE UN ÚNICO REGISTRO DE UNA


COLUMNA
$apellidos = "nej"; // Normalmente este valor vendrá de un formulario

$consulta = "SELECT COUNT(*) FROM $cfg[dbPersonasTabla]


WHERE apellidos LIKE :apellidos";

$resultado = $pdo->prepare($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error al preparar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} elseif (!$resultado->execute([":apellidos" => "%$apellidos%"])) {
print " <p class=\"aviso\">Error al ejecutar la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Se han encontrado {$resultado->fetchColumn()}
registro(s).</p>\n";
print "\n";
}
Si el campo es de tipo numérico, y la cadena de búsqueda es una cadena, podríamos tener un problema de
tipos al compararlos. En el caso de muchas bases de datos (como SQLite o MySQL) la conversión de tipos es
automática y el valor numérico de la base de datos se convierte automáticamente en una cadena para
permitir la búsqueda la cadena de búsqueda, pero en otras (como PostgreSQL) la conversión no se realiza y se
produce un error.
Para escribir consultas que se puedan ejecutar sin problemas en el mayor número de sistemas gestores de
bases de datos, es recomendable realizar la conversión usando la función SQL como muestra el ejemplo
siguiente en el que "edad" sería un campo INTEGER:
$consulta = "SELECT * FROM $cfg[dbPersonasTabla]
WHERE nombre LIKE :nombre
AND CAST(edad AS VARCHAR) LIKE :edad
ORDER BY $ordena";

Consultas de unión de tablas

Se pueden también realizar consultas de unión entre varias tablas, como en el ejemplo siguiente. El ejemplo
está sacado del ejercicio de Biblioteca) y devuelve los préstamos pendientes de devolver a partir de tres tablas
de Usuarios, Obras y Préstamos:
// CONSULTA DE UNIÓN DE TABLAS
$consulta = "SELECT
$cfg[dbTablaPrestamos].id AS id,
$cfg[dbTablaUsuarios].nombre as nombre,
$cfg[dbTablaUsuarios].apellidos as apellidos,
$cfg[dbTablaObras].titulo as titulo,
$cfg[dbTablaPrestamos].prestado as prestado,
$cfg[dbTablaPrestamos].devuelto as devuelto
FROM $cfg[dbTablaPrestamos], $cfg[dbTablaUsuarios],
$cfg[dbTablaObras]
WHERE
$cfg[dbTablaPrestamos].id_usuario=$cfg[dbTablaUsuarios].id
AND $cfg[dbTablaPrestamos].id_obra=$cfg[dbTablaObras].id
AND $cfg[dbTablaPrestamos].devuelto='0000-00-00'
ORDER BY $columna $orden";
$resultado = $pdo->query($consulta);
if (!$resultado) {
print " <p class=\"aviso\">Error en la consulta. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
...

Aplicación configurable

En los ejercicios en este curso se propone al alumno organizar los programas de manera que puedan trabajar
tanto con SQLite como con MySQL y hacerlo de forma organizada, para que se puedan añadir fácilmente otras
bases de datos.
Para ello distribuiremos los elementos comunes (constantes, variables y funciones) en cuatro ficheros
distintos
 config.php. En este fichero escribiremos las opciones de configuración a disposición del usuario.
 biblioteca.php. En este fichero escribiremos los elementos comunes que no dependen de la base de
datos utilizada.
 biblioteca-sqlite.php. En este fichero escribiremos los elementos comunes que necesitan adaptarse
para utilizar SQLite.
 biblioteca-mysql.php. En este fichero escribiremos los elementos comunes que necesitan adaptarse
para utilizar MySQL.

Todas las páginas de la aplicación cargarán la biblioteca general, que a su vez cargará el fichero de
configuración y una de las dos bibliotecas específicas, de acuerdo con la configuración escogida por el usuario.
Todas las páginas incluyen biblioteca.phpbiblioteca.php<?php...include "config.php";...if (SQLite) {include
"biblioteca-sqlite.php"} elseif (MySQL) {include "biblioteca-mysql.php"}...config.phpbiblioteca-
sqlite.phpbiblioteca-mysql.php

Conexión configurable

Por ejemplo, para el caso de la función de conexión, el resultado sería:


config.php: en este fichero se especifica la base de datos que se va a utilizar:

// config.php
// OPCIONES DISPONIBLES PARA EL ADMINISTRADOR DE LA APLICACIÓN

// Base de datos utilizada por la aplicación

$cfg["dbMotor"] = SQLITE; // Valores posibles:


MYSQL o SQLITE

// Configuración para SQLite

$cfg["sqliteDatabase"] = "/tmp/mclibre-base-datos-1-6.sqlite"; // Ubicación de


la base de datos

// Configuración para MySQL

$cfg["mysqlHost"] = "mysql:host=localhost"; // Nombre de host


$cfg["mysqlUser"] = ""; // Nombre de usuario
$cfg["mysqlPassword"] = ""; // Contraseña de
usuario
$cfg["mysqlDatabase"] = ""; // Nombre de la base
de datos
biblioteca.php: la configuración establecida en config.php determina la biblioteca específica a cargar:

// biblioteca.php

// CONSTANTES
define("SQLITE", 1);
define("MYSQL", 2);

require_once "config.php";

if ($cfg["dbMotor"] == SQLITE) {
require_once "biblioteca-sqlite.php";
} elseif ($cfg["dbMotor"] == MYSQL) {
require_once "biblioteca-mysql.php";
}
biblioteca-sqlite.php: contiene la definición de la función conectaDb() específica para trabajar con SQLite

// biblioteca-sqlite.php
// SQLITE: Conexión con la base de datos

function conectaDb()
{
global $cfg;

try {
$tmp = new PDO("sqlite:$cfg[sqliteDatabase]");
$tmp->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$tmp->query("PRAGMA foreign_keys = ON");
$tmp->query("PRAGMA encoding = 'UTF-8'");
return $tmp;
} catch (PDOException $e) {
print " <p class=\"aviso\">Error: No puede conectarse con la base de
datos. {$e->getMessage()}</p>\n";
exit;
}
}
biblioteca-mysql.php: contiene la definición de la función conectaDb() específica para trabajar con MySQL

// biblioteca-mysql.php

// MYSQL: Conexión con la base de datos

function conectaDb()
{
global $cfg;

try {
$tmp = new PDO($cfg["mysqlHost"], $cfg["mysqlUser"],
$cfg["mysqlPassword"]);
$tmp->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$tmp->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$tmp->exec("set names utf8mb4");
} catch (PDOException $e) {
print " <p class=\"aviso\">Error: No puede conectarse con la base de
datos. {$e->getMessage()}</p>\n";
exit;
}
}
finalmente, en cualquier fichero que quiera conectar con la base de datos se llamaría a la biblioteca general y
se llamaría a la función genérica conectaDb():

// EJEMPLO DE USO DE CONEXIÓN CONFIGURABLE


// La conexión se debe realizar en cada página que acceda a la base de datos
require_once "biblioteca.php";
$pdo = conectaDb();

Borrado y creación de base de datos y tablas configurable


El resultado sería
config.php: contiene las variables de configuración del programador comunes:

// config.php
// Configuración de la tabla Personas

$cfg["dbPersonasTamNombre"] = 40; // Tamaño de la


columna Personas > Nombre
$cfg["dbPersonasTamApellidos"] = 60; // Tamaño de la
columna Personas > Apellidos
biblioteca-sqlite.php: contiene las variables de configuración del programador específicas de SQLite y la
definición de la función borraTodo() específica para trabajar con SQLite:

// biblioteca-sqlite.php
// FUNCIONES ESPECÍFICAS DE LA BASE DE DATOS SQLITE

// SQLITE: Nombres de las tablas

$cfg["dbPersonasTabla"] = "personas"; // Nombre de la tabla


Personas

// SQLITE: Consultas de borrado y creación de tablas

function borraTodo()
{
global $pdo, $cfg;

$consulta = "DROP TABLE IF EXISTS $cfg[dbPersonasTabla]";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al borrar la tabla. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Tabla borrada correctamente (si existía).</p>\n";
}
print "\n";

$consulta = "CREATE TABLE $cfg[dbPersonasTabla] (


id INTEGER PRIMARY KEY,
nombre VARCHAR($cfg[dbPersonasTamNombre]),
apellidos VARCHAR($cfg[dbPersonasTamApellidos])
)";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al crear la tabla. SQLSTATE[{$pdo-
>errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Tabla creada correctamente.</p>\n";
}
print "\n";
}
biblioteca-mysql.php: contiene las variables de configuración del programador específicas de MySQL y la
definición de la función borraTodo() específica para trabajar con MySQL

// biblioteca-mysql.php
// FUNCIONES ESPECÍFICAS DE LA BASE DE DATOS MYSQL

// MYSQL: Nombres de las tablas

$cfg["dbPersonasTabla"] = "$cfg[mysqlDatabase].personas"; // Nombre de la tabla


Personas

// MYSQL: Consultas de borrado y creación de base de datos y tablas

function borraTodo()
{
global $pdo, $cfg;

$consulta = "DROP DATABASE IF EXISTS $cfg[mysqlDatabase]";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al borrar la base de datos.
SQLSTATE[{$pdo->errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Base de datos borrada correctamente (si existía).</p>\n";
}
print "\n";

$consulta = "CREATE DATABASE $cfg[mysqlDatabase]


CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al crear la base de datos.
SQLSTATE[{$pdo->errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Base de datos creada correctamente.</p>\n";
print "\n";

$consulta = "CREATE TABLE $cfg[dbPersonasTabla] (


id INTEGER UNSIGNED AUTO_INCREMENT,
nombre VARCHAR($cfg[dbPersonasTamNombre]),
apellidos VARCHAR($cfg[dbPersonasTamApellidos]),
PRIMARY KEY(id)
)";

if (!$pdo->query($consulta)) {
print " <p class=\"aviso\">Error al crear la tabla.
SQLSTATE[{$pdo->errorCode()}]: {$pdo->errorInfo()[2]}</p>\n";
} else {
print " <p>Tabla creada correctamente.</p>\n";
}
}
}
finalmente, en el fichero que quiera reiniciar la base de datos se llamaría a la biblioteca general y se llamaría a
la función genérica borraTodo():

// EJEMPLO DE USO DE BORRADO CONFIGURABLE


require_once "biblioteca.php";
$pdo = conectaDb();
borraTodo();
$pdo = null;

También podría gustarte