Está en la página 1de 124

Carrera Linux 2008 ­ Programacion PHP                                                                 1

Clase 1 ­ Introducción a PHP
Escrito por Demian P. Alonso (demian@linuxadistancia.com)

Programa analítico de la materia
1. Introducción a PHP y los scripts. Variables. Tipos De Datos. Entrada/Salida Básica. 
2. Control de flujo: if, for, while, foreach 
3. Archivos. Descriptores de Archivos. Entrada/Salida en Archivos. Tuberías. 
4. Expresiones Regulares 
5. Funciones y Módulos 
6. Manejo de archivos y directorios. 
7. Biblioteca de funciones: manejo de cadenas; manejo de arreglos; manejo de fechas 
8. Servicios de Internet: SMTP, POP y FTP 
9. Referencias 
10.Introducción al manejo de objetos. Conceptos básicos herencia, polimorfismo, redefinición 
11.Excepciones: teoría y aplicación 
12.Introducción a la programacion web. Introducción a HTML: HTML, HEAD, BODY. Formato 
básico del texto. Creación de links y tablas. 
13.Creación de Formularios en HTML. Utilización de Frames y listas en HTML 
14.Creación de páginas web dinámicas. Utilización de valores pasados por formularios y por links 
15.Manejo de Cookies y sesiones. 
16.Introducción a las base de datos relacionales. El servidor MySQL. Lenguaje de Definición de 
Datos 
17.Lenguaje de Manipulación de Datos 
18.Lenguaje de Administración de Seguridad. Utilidades Relacionadas. 
19.Índices e Integridad Referencial. 
20.Conectividad a base de datos: PHP y MySQL 

Conceptos Teóricos Generales sobre Programación
Programa: Es un conjunto de acciones que realizan una tarea especifica. Para ello un programa toma 
datos y los convierte en información (por ejemplo, listado de clientes, modificar un archivo, enviar un 
dato a otra computadora, etc). 
Esquematicamente:
Datos *----------* Información
------->| Programa |------------->
*----------*
Carrera Linux 2008 ­ Programacion PHP                                                                 2

Lenguaje de programación: Es un conjunto de reglas sintácticas que nos otorgan una forma de 
escribir nuestros programas. 
Código fuente: Es un programa escrito en un lenguaje de programación dado. 
Compilador: Es un programa que traduce un programa escrito en un lenguaje de programación a un 
archivo ejecutable. Esto significa que convierte el texto escrito en un lenguaje de programación X, en 
código de máquina para ser ejecutado cuando sea necesario. A este proceso se lo denomina como 
compilación. Si se llegase a modificar el código fuente será necesario pasar de nuevo por el proceso de 
compilación para que se vean reflejados dichos cambios. Ejemplos de lenguajes que son compilados 
son: C, C++, Pascal, Clipper, etc. 
Intérprete: Es un programa que se encarga de ejecutar un código fuente en un lenguaje dado. Un 
interprete leerá el texto y lo ira ejecutando a medida que lo va leyendo, sin necesidad de generar un 
ejecutable. En consecuencia, cuando se altera el código fuente del programa se verá automaticamente 
reflejado la proxima vez que se ejecute. Ejemplos de lenguajes que son interpretados son: Perl, Python, 
LISP, PHP, Bash, etc. 
Variable: Es un espacio en la memoria de la computadora en donde se puede almacenar datos. Toda 
variable tiene un nombre para poder usarla desde el programa. 

Introducción al uso de PHP
Para crear un programa en PHP deberemos primero crear un archivo con su editor preferido (emacs, vi, 
mcedit, kedit, etc).
Este archivo contendrá el có del programa. Sin embargo, la primer línea del mismo tendrá la siguiente 
forma (DEBE SER LA PRIMERA DE TODAS): 

#!/usr/bin/php

Esta línea le indica al shell en donde se encuentra el intérprete de PHP para ejecutar nuestro programa. 
Si en su sistema PHP no se encuentra instalado en ese directorio, deberá cambiar dicha ruta por la 
ubicación correcta. 
Para saber si PHP esta instalado puede ejecutar desde el shell el siguiente comando: 

$ which php

Si PHP esta instalado, entonces se mostrará la ruta al mismo (la cual es la correcta para utilizar). 
Una vez escrito el programa, se deberá realizar un paso previo antes de poder ejecutarlo. Primero es 
necesario asignarle permisos de ejecución. Para ello utilizaremos el comando chmod: 

$ chmod 755 nombre_archivo.php


Carrera Linux 2008 ­ Programacion PHP                                                                 3

Donde nombre_archivo.php es el nombre del archivo que acabasen de crear con su programa.
Luego será posible ejecutar el programa simplemente ingresando desde el shell: 

$ ./nombre_archivo.php

Si el programa esta bien escrito se ejecutará, en caso contrario PHP nos informará de los errores que 
existiesen. 
NOTA: Durante todas las clases se adoptará como regla que todos los comandos que se deban ejecutar 
desde el shell estarán antepuestos por un símbolo de pesos ($) si se debe ejecutar dicho comando como 
un usuario normal o un numeral (#) si se debe ejecutar como root. Dicho símbolo NO se debe escribir 
ya que simplemente representa al prompt del shell (que deberín concordar con lo que ve en pantalla) 

El lenguaje de programación PHP
PHP (PHP: Hypertext Preprocessor) es un lenguaje que nació en el mundo de las páginas web. Surgió 
como una manera práctica de poder mezclar un lenguaje de programación con HTML (el lenguaje para 
escribir páginas web).
Un programa en PHP, dentro de una página web, se puede pensar como un conjunto de secciones de 
código PHP introducidas dentro de un archivo HTML. En el caso de un programa que interactue 
completamente sobre el shell, podremos imaginarlo como un solo gran bloque de código PHP 
embebido en nada de HTML.
Entonces, definiremos un bloque de PHP de la siguiente forma: 

<?php
# Codigo en PHP
?>

En donde <?php abre el bloque de código y ?> cierra dicho bloque. 

Variables en PHP
En PHP todas las variables comienzan con un signo de pesos ($). El interprete cuando encuentra un $
leerá los siguientes carácteres como el nombre de la variable. Los nombres de las variables en PHP 
pueden contener cualquier caracter alfanumérico (letras y números) y el guión bajo (_). De todos ellos 
queda restringido empezar el nombre de la variable con un número.
Si se hace referencia a una variable que no existe, esta pasara a existir (en el caso de una asignación) o 
simplemente sera reemplazada en la expresión por un valor vacío (que generalmente no afecta en la 
operación en cuestión).
Ejemplos de definición de variables: 

$numero = 3;
$decimal = 8.3;
Carrera Linux 2008 ­ Programacion PHP                                                                 4

$cadena = "Hola Mundo!";

Ejemplo de operaciones con variables 

$suma = $numero + $decimal;


$texto = "$cadena\nHello World";
echo "La suma es $suma";

Existen otros tipos de variables que se utilizan de forma distinta. Entre ellos podemos encontrar los 
arreglos. Un arreglo (también conocido como arreglo asociativo, diccionario o hash) es simplemente un 
conjunto de elementos. Estos elementos pueden ser tanto variables comunes como otro arreglo. A su 
vez, cada elemento esta asociado a una clave (que puede ser tanto numérica como alfabética). En 
consecuencia, estos arreglos pueden ser utilizados como vectores en donde las claves se utilizaran como 
índices numéricos. Para definir un arreglo usaremos la función array de alguna de las siguientes 
formas: 

$vector = array(1, 3, 4, "Hola Mun", 3.4);


$arreglo = array("Jose" => 2, "Pepe" => 35, 23 => 42);

La primer forma crea un arreglo en forma de "vector" en donde el elemento 1 tiene el índice 0, el 
elemento 3 tiene el índice 1, el elemento 4 tiene el índice 2, el elemento "Hola" tiene el índice 3 y el 
elemento 3.4 tiene el índice 5.
La segunda forma crea un arreglo de forma tal que la clave "Jose" tiene asociado el valor 2, la clave 
"Pepe" el 35 y la clave 23 el 42. 
Para acceder luego a uno de los valores del vector, solo hace falta conocer la clave que se quiere 
acceder y escribirla entre corchetes luego del nombre de la variable. Por ejemplo: 

echo "$vector[3] $arreglo[Jose]";

mostrará por pantalla "Hola Mun 2". También se puede modificar (o agregar si no existe) una clave, 
asignándole un valor a ella. Por ejemplo: 

$arreglo["Yo"] = 24;

agregará una clave al arreglo mientras que 

$arreglo["Pepe"] = 22;

modificará el contenido de la ya existente clave "Pepe". 
Carrera Linux 2008 ­ Programacion PHP                                                                 5

Operadores

Operador de asignación
El operador de asignación es el igual(=). Su misión es la de darle un valor a una variable. Por ejemplo: 

$mi_nombre = "Pepe";
$mi_lista = array(1, 2, 3);
$un_numero = (3 + 5) * 4;

Es importante destacar que primero se evalua todo lo que se encuentre a la derecha del igual y luego se 
los escribe en la variable especificada. No tendría sentido tratar de asignarlo al revez. 

Operadores matemáticos
Estos operadores sirven para realizar operaciones matemáticas básicas. Por ejemplo para sumar dos 
números se usa el más (+): 3 + 4
Los operadores básicos son: 
Operación Operador
suma +
resta ­
multiplicación *
división /
módulo %

Operadores de cadenas
Existe un operador para manejar cadenas. Es el de concatenación (.). Este sirve para juntar dos 
cadenas (que pueden estar en una variable) en una sola.
Por ejemplo, si se tiene una variable $nombre con el valor "Pepe", entonces "Hola " .
$nombre es lo mismo que "Hola Pepe". 

Operadores de comparación
Estos operadores sirven para determinar si dos expresiones responden o no a un criterio (verdadero o 
falso). Por ejemplo, para saber si una cadena (o número) es igual a otra se utiliza el operador == y este 
dirá si ambas son iguales o no. Todos estos operadores son binarios, por lo tanto, se escriben de la 
siguiente forma: expresion1 operador expresion2 y todo esto devolverá verdadero o falso. 
Si se tiene una variable $sueldo con el valor 500 entonces $sueldo > 1000 será falso, mientras 
que $sueldo <= 500 será verdadero. Estos operadores son: 
Carrera Linux 2008 ­ Programacion PHP                                                                 6

Operación Operador
Igualdad ==
Mayor que >
Menor que <
Mayor igual que >=
Menor igual que <=
Distinto !=

Operadores lógicos
Estos operadores son similares a los de comparación ya que determinan la veracidad o falsedad de una 
o más condiciones. Los operadores mencionados anteriormente generaban condiciones (que $sueldo
> 500 por ejemplo) las cuales pueden ser concatendas para hacer condiciones mas complejas. Para 
ello existen 3 operadores.
El primero es el operador and (y) el cual toma dos condiciones. Para que sea verdadera esta nueva 
condición, las dos condiciones tomadas deben ser verdaderas. El siguiente cuadro resume todas las 
posibilidades de valores que pueden tener dos condiciones: 

condición1 and condición2 = Valor


V V V
F V F
V F F
F F F

El segundo operando es el or (o), el cual es similar al and solo que alcanza con que una sola sea 
verdadera para que toda la condición sea verdadera. De forma análoga: 

condición1 or condición2 = Valor


V V V
F V V
V F V
F F F

El último operando es el not (no) que es la negación. Simplemente cambia el valor de verdad que 
tenga una condición. 

condición = Valor
V F
F V
Carrera Linux 2008 ­ Programacion PHP                                                                 7

Entrada y salida básica
Salida

Para mostrar cosas por la pantalla se utiliza la función echo. Esta recibe una lista con todas las cosas 
que debe mostrar. Por ejemplo: 

print "Hola ", $nombre, " la suma es ", 2 + 2, "\n";

Nota: Cuando en una cadena se pone una barra invertida (\), PHP interpreta el próximo caracter en 
forma especial. En el ejemplo anterior, el próximo caracter es la "n" y se interpreta el \n como si fuera 
una nueva línea, por lo que los proximos echo imprimirán en la línea siguiente en vez de imprimir al 
lado. 
Los más comunes son: 
Caracter Descripción
\n Nueva línea
\t Tabulación
\\ La barra invertida literalmente (se muestra UNA SOLA barra)

Entrada
Para leer datos del teclado se utiliza la entrada estándar. Para ello debemos leer desde el archivo del 
teclado, el cual se llama STDIN. Para leer una línea desde el teclado llamaremos a la función 
fgets(STDIN); la cual nos devolverá la próxima línea disponible o bloqueará el programa hasta 
que se encuentre una disponible.
Para quitar el ENTER hay que utilizar el operador chop sobre lo leído. Por ejemplo: 

$mi_entrada = fgets(STDIN);
$mi_entrada = chop($mi_entrada);

Entonces, si el usuario ingreso "Hola Mundo\n" (el \n se agrega siempre porque es el caracter que 
ingresa el usuario para terminar) luego de las dos sentencias escritas, quedará en la variable 
$mi_entrada el valor "Hola Mundo" 

Ejercicios
1. ¿Que es una variable? 
2. ¿Que tipos de datos hay en PHP? 
3. ¿Para que sirven cada tipo de operador? 
4. ¿Cual es la diferencia entre la funcion fgets y la funcion echo? 
5. ¿Que ventajas tiene la programacion de scripts a programar sobre un lenguaje que se compile? 
Carrera Linux 2008 ­ Programacion PHP                                                                 8

Clase 2 ­ Control del flujo de ejecución
Estructuras de control de flujo
Hasta este punto solo se podían ejecutar una sentencia debajo de la otra hasta que se completará el 
programa. Sin embargo, existen algunas estructuras que permiten alterar este comportamiento y obtener 
resultados más interesantes. 

Estructura de bifurcación
La primera de las estructuras, el if, es la que me permite tomar una decisión sobre si ejecutar o no un 
bloque de código dependiendo de una condición: 

if(condición) {
sentencia1;
sentencia2;
sentencia3;
...
sentenciaN;
}

Si se cumple condición entonces se ejecutarán todas las sentencias que se encuentren entre las llaves 
(que son obligatorias). En caso de que no se cumpla, entonces se seguiran ejecutando las sentencias que 
se encuentren por debajo de la última llave del if.
Una condición puede solamente ser Verdadera, se cumple, o Falsa, no se cumple (Ver operadores de 
comparación).
Sin embargo, también se puede obligar a ejecutar un bloque de código si no se cumple la condición: 

if(condición) {
sentencia1;
sentencia2;
...
sentenciaN;
} else {
sentenciaN+1;
sentenciaN+2;
...
sentenciaM;
}

En este caso, si se cumple la condición se ejecutan las sentencias que van desde el 1 hasta N, y si no 
se cumple, las que van desde N+1 hasta M. Para ello se utilizó la palabra else (sino) que nos permite 
ejecutar algo si la condición es falsa. Siempre se ejecutará un bloque u otro pero nunca ambos. 
Carrera Linux 2008 ­ Programacion PHP                                                                 9

Cuando se anidan un if, o sea, poner muchos if uno dentro de otro, el código se hace bastante ilegible. 
Para ello existe otra palabra reservada (o conjunción), elseif, que permite juntar un else con un if y 
así dejar el código más ordenado: 

if(condición) {
sentencia1;
sentencia2;
...
sentenciaN;
} elseif(condicion2) {
sentenciaN+1;
sentenciaN+2;
...
sentenciaM;
} else {
sentenciaM+1;
sentenciaM+2;
...
sentenciaJ;
}

En este caso, solo se ejecutará uno de los tres bloques de código (1 a N, N+1 a M o M+1 a J). 

Ejemplos
Ejemplo 1: Leer una temperatura desde el usuario y decir "Hace Calor" si la temperatura es mayor que 
30 o "Hace Frio" en otro caso. 

echo "Ingrese la temperatura actual: ";


$temperatura = fgets(STDIN);

if($temperatura > 30) {


echo "Hace calor\n";
} else {
echo "Hace frio\n";
}

Ejemplo 2: Leer una temperatura desde el usuario y decir "Hace Calor" si la temperatura es mayor que 
30, si esta entre 20 y 30 mostrar "Esta perfecto" o "Hace Frio" en otro caso. 

echo "Ingrese la temperatura actual: ";


$temperatura = fgets(STDIN);

if($temperatura > 30) {


echo "Hace calor\n";
} elseif ($temperatura > 20) {
echo "Esta perfecto\n";
} else {
Carrera Linux 2008 ­ Programacion PHP                                                                 10

echo "Hace frio\n";


}

Estructura while
Esta estructura sirve para iterar sobre una porción de código mientras se cumpla una condición dada: 

while(condición) {
sentencia1;
sentencia2;
...
sentenciaN;
}

Las sentencias 1 a la N se ejecutarán mientras condición tenga un valor verdadero. La condición se 
controla cada vez que se termine de ejecutar la sentenciaN y allí determinará si debe iterar de nuevo o 
no. Por lo tanto un ciclo while puede ejecutarse desde 0 (la condición nunca fue verdadera) hasta 
infinito. 

Ejemplos
Ejemplo 1: Mostrar la tabla de multiplicar del 7. 

$x = 1;
while ($x <= 10) {
echo "$x por 7 = ", $x * 7, "\n";
$x = $x + 1;
}

Ejemplo 2: Leer varias líneas por teclado hasta que se ingrese una línea que contenga solamente un 
punto (.). Cada línea leída se debe repetir en pantalla, pero enumerandolas desde 1 en adelante. 

$ingreso = fgets(STDIN);
$ingreso = chop($ingreso);
$x = 1;
while($ingreso != '.') {
echo "$x. $ingreso\n";
$x = $x + 1;
$ingreso = fgets(STDIN);
$ingreso = chop($ingreso);
}

Estructura foreach
Esta estructura se utiliza para recorrer un arreglo.
Existen dos estilos de foreach. En el primero, se irán tomando de a uno los elementos del arreglo 
Carrera Linux 2008 ­ Programacion PHP                                                                 11

indicado, y se irán colocando en la variable indicada luego del as.
La sintaxis sería: 

foreach($arreglo as $valor) {
sentencia1;
sentencia2;
...
sentenciaN;
}

Aquí se ejecutarán las sentencias 1 a la N tantas veces como elementos haya en el arreglo. Para cada 
iteración existirá una variable llamada $valor que tendrá un valor de la lista. 
La segunda forma nos permite no solo obtener el valor, sino también la clave asociada con dicho valor.
Para ello utilizaremos la sintaxis: 

foreach($arreglo as $clave => $valor) {


sentencia1;
sentencia2;
...
sentenciaN;
}

De esta forma para cada ciclo se dispondrá de una variable $clave que tiene la clave del elemento que 
se este procesando. Además, en $valor estará el contenido del elemento actual. Por lo tanto, al saber 
la clave, es posible modificar el arreglo original. 

Ejemplos
Ejemplo 1: Mostrar todos los elementos de una lista. 

$lista = array("Hola", 3, 5, "Mundo");


foreach($lista as $valor) {
echo "$valor\n";
}

Ejemplo 2: Desde una lista con números calcular la suma de todos ellos. 

$lista = array(2000, 700, 900, 1500);


$total = 0;
foreach($lista as $valor) {
$total = $total + $valor;
}
echo "La suma es $total\n";
Carrera Linux 2008 ­ Programacion PHP                                                                 12

Ejercicios
1. ¿Cual es la diferencia entre un if y un while? 
2. ¿Que es más práctico para recorrer una lista? ¿un while o un foreach? 
3. Hacer un programa que dada una lista con numeros, los muestre y diga si cada número es PAR o 
IMPAR.
NOTA: un número es PAR si al dividirlo por 2 el modulo da 0 ($numero % 2 == 0) 
4. Hacer un programa que dada una lista con numeros, calcular la sumatoria y el promedio de 
todos ellos. 
5. Hacer un programa que muestre las tablas de multiplicar del 1 al 10 (usando solamente dos 
ciclos while) 

Clase 3 ­ Archivos de datos
Introducción
Un archivo es simplemente un conjunto de bytes (o caracteres). Los archivos se dividen en dos 
categorías: de texto y binarios. Si bien esta división es arbitraria ya que no hay diferencia real entre 
ellos, diremos que los archivos de texto son aquellos que podemos leer y "entender" con cualquier 
editor de texto (emacs, vi, mcedit, etc) y los archivos binarios son aquellos que presentan caracteres 
"raros" cuando se los trata de leer.
Veremos aquí el uso de los archivos de texto.
Por lo general, cuando se lee un archivo se ven varias líneas de texto. Por ejemplo 
Querido Mundo:
Hola Mundo, como has estado?

Es razonable pensar que existe alguna forma de expresar que "Hola Mundo" no se escriba al lado de 
"Querido Mundo:". A pesar de que no se puede ver, hay un caracter entre estas dos cadenas. Este 
caracter es el de nueva línea (el '\n'). Por defecto este es el caracter que le indica a PHP hasta donde 
leer cuando se requiere una lectura. 

Uso de Archivos

Apertura
Cuando se quiere utilizar un archivo (leer o escribir) primero es necesario decirle al Sistema Operativo 
que nos lo "preste" para hacer lo que deseemos.
Para ello existe una función llamada fopen, que tiene la siguiente forma: 

$archivo = fopen("nombre_del_archivo", "modo");

Donde $archivo es el nombre de la variable con la cual se hará referencia, dentro del script en PHP, 
al archivo que haya sido abierto exitosamente. "nombre_del_archivo" es una cadena que tiene la 
Carrera Linux 2008 ­ Programacion PHP                                                                 13

ruta y el nombre del archivo.
NOTA: Una vez abierto el archivo se debe usar la variable $archivo para hacer referencia al archivo 
dentro del script. nombre_del_archivo es solo una cadena y no se puede ni leer ni escribir desde 
o hacia ella. 
Como se mencionó antes, el archivo puede ser abierto para leer, escribir o tambien para agregar. Esto se 
especifica dentro de la cadena "modo". Esta cadena podrá ser "r" para abrirlo para lectura, "w" para 
escritura y "a" para agregar. Por ejemplo, para escribir en el archivo pepe.datos del directorio 
actual, la cadena nombre_del_archivo es "./pepe.datos" y el modo "w". Cuando se abre un 
archivo para escribir si no existe el archivo, entonces este es creado, y si existe todos los datos son 
eliminados. Luego de abierto se comienza a escribir desde el inicio del archivo.
Si la intención no es la de borrar los datos, entonces se debe abrir para agregar. Cuando esto ocurre si el 
archivo no existe se crea, y si existe entonces se comienza a escribir desde el fin de datos del archivo sin 
borrar su contenido. 
Algunos ejemplos de open son: 

$datos = fopen("./datos.txt", "r"); # Abre el archivo datos.txt para leer


$estadisticas = fopen("./stats.dat", "w"); # Abre el archivo stats.dat para
escribir
# y le asigna el descriptor ESTADISTICAS
$log = fopen("mensajes.log", "a"); # Abre para agregar el archivo mensajes.log

Puede ocurrir que no se pueda abrir el archivo por diversos motivos. Por ejemplo, si se abre el archivo 
para lectura y el archivo no existe o no se tienen los permisos adecuados es un error. Para ello la 
función open devuelve verdadero si se pudo abrir y falso en caso contrario.
Para controlar esto podríamos hacer: 

$archivo = fopen("mi_archivo.txt", "r");


if(! $archivo) {
echo "ERROR al intentar abrir el archivo";
}

Esto controlaría en el if si no se pudo abrir el archivo. En cuyo caso mostraría un mensaje informando 
el motivo. 

Clausura
Cuando se ha terminado de usar el archivo es necesario cerrarlo para asegurarse que todo haya quedado 
guardado. Para ello existe la función close a la cual solo debe especificarsele el descriptor del 
archivo. Por ejemplo: 

close($archivo);
Carrera Linux 2008 ­ Programacion PHP                                                                 14

Lectura
Para leer de un archivo se puede hacer de la misma forma en que se leía desde el teclado (en realidad el 
teclado es un archivo). Esto se hace utilizando la misma función fgets. Por ejemplo, 

$linea = fgets($archivo);

leerá una línea (hasta e incluyendo el '\n') hasta el delimitador (que por defecto es el '\n' que separa las 
líneas). Con cada lectura se avanzará a la próxima línea y cuando no haya más líneas cada lectura 
devolverá falso.
Para detectar que se hay llegado al final del archivo existe la función feof. Esta función devolverá 
verdadero una vez que se haya leido el fin de archivo (una lectura despues del final del archivo) y falso 
en otro caso. Para hacer un programa que muestre el contenido del archivo "mi_archivo.txt" una 
solución sería: 

$arch = fopen("1.html", "r");


while(!feof($arch)) {
$linea = fgets($arch);
echo $linea;
}
fclose($arch);

Sabiendo que la función fgets devolverá falso una vez que tratemos de leer más alla del final, otra 
solución sería: 

$arch = fopen("mi_archivo.txt", "r");


while($linea = fgets($arch)) {
print $linea;
}
fclose($arch);

Escritura
Para escribir en un archivo se utiliza la función fputs. Para ello se debe especificar como primer 
parámetro el archivo a utilizar y luego lo que se quiera mostrar. Por ejemplo para guardar los números 
del 1 al 10 en un archivo (numeros.txt): 

$arch_numeros = fopen("./numeros.txt", "w");


foreach (range(1, 10) as $numero) {
fputs($arch_numeros, "$numero\n");
}
fclose($arch_numeros);

NOTA: La función range nos devuelve una arreglo cuyos valores son los números que comprenden el 
intervalo especificado con sus dos parámetros. 
Carrera Linux 2008 ­ Programacion PHP                                                                 15

Tuberías
Una tubería es ni más ni menos que un archivo. La diferencia esta que en vez de leer desde un archivo 
de datos se leerá desde la salida de un comando, o en vez de describir en un archivo de datos, se 
escribirá a la entrada de un comando.
Para crear una tubería utilizamos la función popen, que es análoga a open pero en vez de abrir un 
archivo, ejecutará el programa especificado. Como diferencia tendremos solo dos modos "r" y "w" ya 
que las tuberías son unidireccionales, solo podemos leer o escribir de ellas, pero no ambas cosas sobre 
la misma tubería. 
Para cerrar una tubería poseemos la función pclose que es igual a close pero cierra una tubería en 
vez de un archivo. 
Veamos un ejemplo: 

$tub = popen("ps -o user ax | grep mi_usuario", "r");


$cant = 0;
while($l = fgets($tub)) {
$cant ++;
}
echo "Cantidad de procesos para mi_usuario: $cant\n";

Argumentos desde la línea de comandos
Es muy común que un script necesite el usuario le especifique sobre que archivos trabajar o que 
modifique alguna conducta específica. Para ello se utilizan los parámetros que se le pasan a los 
programas desde la línea de comandos. Por ejemplo el programa ls muestra todos los archivos de un 
directorio. Pero si se quiere ver la información detallada de estos se le agrega un argumento ("-l") 
para que lo haga.
En PHP todos estos argumentos son accedidos a través del arreglo argv. Este arreglo es creado 
automaticamente por PHP y es automáticamente llenado con los argumentos. Para verificar esto se 
muestra el programa args.php: 

echo "Los argumentos son:\n";


foreach($argv as $indice => $argumento) {
echo "Argumento $indice: $argumento";
# notar que $argumento es lo mismo que $argv[$indice]
}

Si se ejecuta ahora: 

$ args.php Hola Mundo "Hello World" 4 5 6

Mostrará por pantalla: 
Carrera Linux 2008 ­ Programacion PHP                                                                 16

Los argumentos son:


Argumento 0: args.php
Argumento 1: Hola
Argumento 2: Mundo
Argumento 3: Hello World
Argumento 4: 4
Argumento 5: 5
Argumento 6: 6

Ejercicios
1. ¿Que tiene de similar el teclado (STDIN), un archivo y una tuberia? 
2. Hacer un programa que genere N numeros aleatorios y los guarde en un archivo uno por linea. 
Tanto N como el nombre del archivo se deberan pasar desde la linea de comandos. Para los 
numeros aleatorios mirar la ayuda para la funcion rand (buscar la funcion en el sitio de php: 
www.php.net). 
3. Hacer un programa que lea un archivo ingresado como un argumento desde la linea de 
comandos (generado por el programa anterior) y que muestre solo aquellos numeros que sean 
PAR. 
4. Hacer un programa que lea todas las lineas de un archivo y las imprima nuevamente pero 
anteponiendoles cuantas veces se repitieron dentro del mismo. 
5. Hacer un programa que reciba tres nombres de archivos desde los argumentos. El programa 
debe generar el tercer archivos en base a los dos primeros, intercalando las lineas de ambos. 

Clase 4 ­ Expresiones Regulares
Introducción a las expresiones regulares
Una expresión regular es una forma que nos provee PHP (entre otros lenguajes) de verificar, validar y 
extraer datos. Esta herramienta se basa en que la entrada tiene un patrón. Esto significa que si bien no 
son iguales todas las entradas, todas tienen la misma forma. Por ejemplo, un archivo de log 
(/var/log/messages), un archivo de configuración (como /etc/inittab), o un archivo de datos (como /etc/
passwd) entre otros. 

Patrones
Los patrones se especificará como una cadena de caracteres común. Estos patrones contaran con 
caracteres literales (deben estar literalmente en la cadena que se busca) y otros caracteres especiales 
que le dan flexibilidad y generalidad (por ejemplo, decir que debe haber uno o más dígitos).
Para aplicar este patrón sobre una cadena se utiliza la función ereg, en donde el primer parámetro será 
el patrón y la segunda la cadena con la cual se quiere comparar. Ademas, ereg devolverá verdadero si la 
cadena corresponde al patrón dado o falso en caso contrarior.
Carrera Linux 2008 ­ Programacion PHP                                                                 17

Ejemplo: 

$cadena = "El conejo esta sobre la mesa";


if(ereg("conejo", $cadena)) {
print "La palabra conejo esta en la cadena\n";
} else {
print "La palabra conejo NO esta en la cadena\n";
}

En este ejemplo, aparecerá por pantalla la primera opción. Cuando se especifica un patrón que consta 
solo de literales (ningun caracter especial), se fijará si ese patrón esta en alguna parte de la cadena sin 
importar donde este.
El patrón tambien puede ser especificado o contener, variables comunes de tipo cadenas. Para poner el 
patrón anterior en una variable el programa quedaría: 

$cadena = "El conejo esta sobre la mesa";


$patron = "conejo";
if(ereg($patron, $cadena)) {
print "La palabra conejo esta en la cadena\n";
} else {
print "La palabra conejo NO esta en la cadena\n";
}

Caracteres especiales
Los caracteres especiales son: . * ? + [ ] ( ) { } ^ $ \
Si se quiere que alguno de estos caracteres deba aparecer en la cadena que se esta validando, entonces 
se les debe anteponer una barra invertida (\) para que se los interprete como tal. 

Límites
La primer restricción que pondremos sobre una expresión regular será los límites principio y fin. Para 
ello existe el caracter ^ (principio) y el caracter $ (fin). El ^, si aparece, aparecerá como primer 
caracter de la expresión, ya que el principio de la cadena solo puede ocurrir al principio. De forma 
análoga será el $. Para saber si una oración termina en punto se podría pregunar: 

if(ereg("\.$", $cadena)) {
print "Bien terminada\n";
} else {
print "Mal terminada\n";
}

Esta expresión consta de dos caracteres: el \. que representa un punto literal (este caracter debe estar 
en $cadena y debe ser el último de todos) y el caracter $ que indica el fin de la cadena (dentro de cad 
no puede haber más caracteres despues del .). 
Carrera Linux 2008 ­ Programacion PHP                                                                 18

Conjuntos
Hasta ahora solo se usaron caracteres literales, pero también pueden generalizarse. Esto significa que se 
puede decir que en cierto punto puede ocurrir, por ejemplo, una letra mayuscula. Para ello se utilizan 
los corchetes ( [ ] ). Dentro de los corchetes se pondran todos los caracteres que se permiten. Si se 
buscan solo dígitos se usará [0123456789]. Si se quiere verificar que un valor ingresado se un 
número de 3 dígitos se podría hacer: 

$entrada = chop(fgets(STDIN));
if(ereg("^[0123456789][0123456789][0123456789]$", $entrada)) {
print "Tiene 3 digitos\n";
}

Como se puede apreciar esto es largo, confuso, y poco estetico. Para ello se permite la posibilidad de 
definir un rango. Esto significa, que en vez de enumerar todas las posibilidades se puede decir desde un 
caracter (0 por ejemplo) hasta cierto otro (9 por ejemplo). El rango se especifica poniendo entre estos 
dos valores, un guión (-).
Considerando esto, el ejemplo anterior quedaría: 

$entrada = chop(fgets(STDIN));
if(ereg("^[0-9][0-9][0-9]$", $entrada)) {
print "Tiene 3 digitos\n";
}

Si bien esto es mucho más claro, aun no es lo más óptimo. Para ello se definieron algunos rangos que se 
usan muy comunmente. Estos rangos poseen un nombre, y se especifica el mismo entre los símbolos 
[: y :]. Por ejemplo, el rango [0-9] esta representado por [:digit:] (equivalente a 0-9).
Considerando esto, se puede modificar lo anterior a: 

$entrada = chop(fgets(STDIN));
if(ereg("^[[:digit:]][[:digit:]][[:digit:]]$", $entrada)) {
print "Tiene 3 digitos\n";
}

Así como se especifico en un conjunto cuales son los caracteres que se admiten, tambien puede ser 
expresado de su forma contraria. Esto es, decir solamente cuales caracteres no se permiten, dejan que 
califican en este rango a todos los demas caracteres. Para ello, luego del primer corchete, se debe poner 
el acento circunflejo (^), que es el operador que me "niega" los demas caracteres. Por ejemplo si no se 
quiere aceptar ningun número se pondría: 

if(ereg("[^0-9]", $entrada) {
print "La cadena no tiene ningun numero\n";
}

Si bien esto es posible, es recomendable que siempre que se utilice un conjunto que se especifiquen los 
caracteres que si pueden ir, en vez de especificarlo por negación. Esto nos da la seguridad que si la 
Carrera Linux 2008 ­ Programacion PHP                                                                 19

entrada es válida, entonces la solución esta entre lo que uno planeo. Si en cambio se nego los caracteres 
que no se querian, si se olvido de poner alguno o si aparecieron otros caracteres que en el momento de 
escribir el programa no existieran, podrian causar efectos raros en nuestro programa.
Entre los conjuntos ya definidos se encuentran: 

[:alnum:] [0-9A-Za-z]
[:alpha:] [A-Za-z]
[:digit:] [0-9]
[:blank:] [ \t\n\r]

Repeticiones
Cuando se utiliza expresiones regulares, por lo general, ciertos caracteres se repiten varias veces. Por 
ejemplo, si se esta leyendo un archivo que tiene nombres de usuarios, seguidos por un espacio y 
seguido por su directorio actual, ocurrirá que los nombres tienen más que un solo caracter (muchos 
[:alnum:]). En este ejemplo, tampoco se sabe hasta cuantos caracteres pueda tener el nombre o el 
directorio, por lo que no se podría expresar todas las posibilidades. Aquí es donde entran las 
repeticiones. 

Cero o una repetición
Si se quiere poner algo como opcional, querra decir que cierto caracter puede o no estar. Para ello existe 
el caracter especial ?. Este operador permite que el caracter anterior este o no. Por ejemplo, si se esta 
leyendo líneas como las descriptas anteriormente, entradas posibles serían: 

root /root
usuario /home/usuario/

Como se puede apreciar, los directorios no tienen la misma forma, ya que uno termina con / y el otro 
no. Entonces esta barra (/) es opcional. En nuestra expresión regular aparecerá un /?. El ? permitirá 
que ese caracter este o no este. Gracias a esto ambas entradas son válidas. 

una o más repeticiones
Si consideramos el ejemplo anterior, para validar el nombre del usuario haria falta poder expresar que 
debe haber por lo menos un caracter, y que luego pueden sucederlo varias mas. Para ello existe el 
operador más (+). Este operador permite que el caracter o expresión que lo precede se repita 1 o más 
veces. Dentro de la expresión regular, para validar al nombre, aparecerá al principio ^[[:alnum:]]+
donde el ^ representa el inicio de la cadena, [[:alnum:]] es cualquier caracter alfanumérico y el +
hace que se pueda repetir el [[:alnum:]] una o más veces. 
Carrera Linux 2008 ­ Programacion PHP                                                                 20

cero o más repeticiones
Si existe la posibilidad de que todo un campo pueda estar vacío, entonces en vez de necesitar que algo 
se repita una o más veces, se necesitará que se repita ninguna o más veces. El "ninguna" es el que le da 
la categoria de opcional. Por ejemplo, el archivo de usuarios (/etc/passwd) tiene algunos campos que 
son opcionales (como el campo GECOS contiene información superflua, como el nombre real del 
usuario). El operador que me permite hacer esto es el asterisco (*). De esta forma, en la expresión 
regular aparecerá un [[:alnum:]]* donde [[:alnum:]] es un caracter que, por el asterisco, se 
podrá repetir cero o más veces. 

Rango de repeticiones
Las repeticiones anteriores eran indefenidas, esto es, no tenían un limite establecido. Puede ocurrir que 
se necesite que un caracter este un número específico de veces o que este dentro de un rango. Si se 
quiere validar un número de 3 dígitos, haría falta que el set [[:digit:]] se repita tres veces 
([[:digit:]][[:digit:]][[:digit:]]). También puede especificarse una sola vez que 
caracter se quiere que se repita y decir cuantas veces se debe repetir. Para indicar las repeticiones estas 
se deben especificar entre llaves ( {} ). Para el caso anterior sería [[:digit:]]{3}. Que pasaría si 
el número de 3 dígitos puede tener valores que solo sean de dos dígitos (ya que el 099 sería lo mismo 
que poner 99). Para ello se puede decir que haya entre 1 y 3 dígitos. De esta forma estarian 
contempladas todas las posibilidades. Para especificar un rango también se usan las llaves y entre ellas 
se pondra el limite inferior seguido de una coma y seguido del limite superior. En nuestro ejemplo sería 
[[:digit:]]{1,3}.
La repetición puede imitarse poniendo tantas veces como se necesite el caracter, pero el rango de 
repeticiones no puede ser imitado de esta forma, por lo que lo hace necesario conocerlo.
También es posible no especificar uno de los limites. PHP interpretará que llendo para el limite que no 
se especifico, puede tomar cualquier valor. Entonces, si se escribe [[:digit:]]{,3} (no se 
especifico el limite inferior), podrá haber entre 0 y 3 dígitos. Y [[:digit:]]{2,} (no se especifico 
el limite superior) significa que puede haber 2 o más dígitos. 

Recuperar partes de la cadena
Cuando se aplica una expresión regular a una cadena se fija si esta cadena concuerda con el patrón 
especificado. Si hay un patrón, entonces debe haber información útil mezclada con alguna forma de 
expresar toda esta información para que se entendible por algo o alguien. Las expresiones regulares en 
PHP nos permiten recuperar esta información útil desde la cadena. Para lograr este comportamiento las 
partes de la expresión regular que se quieran obtener como variables se deben especificar entre 
paréntesis.
Desde PHP sera necesario agregar un parámetro más a la llamada a ereg. Este será el nombre de un 
arreglo que podemos usar. Luego de la llamada, quedará a partir de la posición 1 el primer juego de 
paréntesis, en la posición 2 el segundo y asi sucesivamente.
Veamos un ejemplo práctico: El archivo /var/log/messages es un archivo de log que registra todas las 
Carrera Linux 2008 ­ Programacion PHP                                                                 21

acciones realizadas por los programas. Una entrada de este archivo en mi máquina es: 

Dec 26 14:45:23 darkstar login[1077]: ROOT LOGIN on `tty2'

El formato de una entrada es (en este orden): 
El comienzo de la cadena
3 letras que identifican el mes
1 o mas espacios
El dia en que se registro la operacion (pueden ser 1 o dos digitos)
La hora en que se registro la operacion separando las horas,
minutos y segundos con un :
El nombre del host
Una cantidad de caracteres hasta el un (puede haber espacios) : que
representan el programa (o proceso) que genero ese registro
1 :
Una cantidad indefinida de caracteres que muestran un mensaje que
informa el problema o exito detectado (incluido el \n).
Fin de la cadena.

El objetivo de este programa será mostrar por pantalla solo aquellas entradas que pertenezcan a un mes 
y día especifico. La salida deberá indicar la hora y el mensaje de cada entrada.
El programa: 

echo "Ingrese el mes a buscar: ";


$mes = chop(fgets(STDIN));
echo "Ingrese el dia a buscar: ";
$dia = chop(fgets(STDIN));

echo "Los mensajes de $dia de $mes:\n";


$log = fopen("/var/log/messages", "r");
if(!$log) {
echo "No se puede abrir el archivo: $!\n";
exit(1);
}

$patron = "^$mes".
"[[:blank:]]+".
"$dia".
"[[:blank:]]+".
"([[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2})".
"[[:blank:]]+".
"[[:alnum:]]+".
"[[:blank:]]+".
"[][[:alnum:].]+".
":".
"(.+)$";

while($linea = chop(fgets($log))) {
if(ereg($patron", $linea, $reg) {
Carrera Linux 2008 ­ Programacion PHP                                                                 22

cho "$reg[1]: $reg[2]\n";


}
}
fclose($log);

Lo único complejo de este programa es el patrón utilizado en el if. Veamosla por partes.
Al principio esta el ^ que indica que lo que sigue debe estar al principio de la cadena. En este caso se 
utiliza la variables mes que posee el mes, que el usuario ingreso por teclado, que se quiere buscar (el 
mes se escribe en ingles las primeras 3 letras).
Seguido del mes se especifica que puede haber 1 o más espacios ([[:blank:]]+). Luego aparece el 
día que se quiere buscar, que se encuentra en la variable día (que ingreso el usuario).
Hasta aqui hace que la expresión concuerde con la fecha que el usuario quiere buscar. Esta es la unica 
parte que cambia entre distintas ejecuciones del programa.
Luego aparece nuevamente los espacios ([[:blank:]]+). Según el formato del archivo de log, lo 
siguiente es la hora con el formato dos dígitos dos puntos dos dígitos dos puntos dos dígitos 
([[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}). Como esto es parte de lo que nos 
interesa mostrar lo escribimos dentro de paréntesis. De esta forma si la cadena concuerda con la 
expresión regular, quedará guardado en la variable $reg[1] (por ser el primer grupo de paréntesis) la 
hora.
Despues de la hora hay espacios ([[:blank:]]+), el nombre del host ([[:alnum:]]+) y más 
espacios ([[:blank:]]+).
Luego viene el nombre del programa. Aquí pueden aparecer caracteres como los corchetes ( [] ), el 
punto, el espacio o cualquier caracter alfanumérico. Para se hace un conjunto que contenga a todos 
ellos (los corchetes por ser los que delimitan los conjuntos se deben escribir al comienzo), este conjunto 
se escribe como [][[:alnum:].]. Y como todo eso se puede repetir 1 o más veces se le pone luego 
un más (+).
Luego viene el dos puntos (:) literal, y luego puede haber cualquier cosa hasta el fin de la cadena. 
Existe un caracter especial que concuerda con cualquier caracter. Este caracter es el punto (.). 
Especialmente útil en esta ocasión, el punto seguido del más concuerda con cualquier cosa que haya 
luego del punto. Como todo esto representa al mensaje que se esta buscando y es parte de lo que nos 
interesa obtener el .+ se encierra entre paréntesis. De esta forma quedará en la variable $reg[2] la 
cadena con el mensaje de log.
Finalmente se encuentra el fin de cadena que es donde termina la expresión regular.
Dentro del if solo se imprime la fecha (que estaba en $reg[1]) y luego el mensaje (que estaba en 
$reg[2]). 
Un ejemplo de la salida reducida es (si se ingreso como mes May y como día 6): 

00:01:43: lp0: using parport0 (polling).


00:01:43: PPP Deflate Compression module registered
00:01:43: Soundblaster audio driver Copyright (C) by Hannu Savolainen
00:01:43: sb: CMI8330/C3D Audio Adapter detected
00:01:43: sb: ISAPnP reports 'CMI8330/C3D Audio Adapter' at i/o 0x220, irq 5, dma
1, 5
00:01:43: SB 4.13 detected OK (220)
Carrera Linux 2008 ­ Programacion PHP                                                                 23

00:01:43: sb: 1 Soundblaster PnP card(s) found.


00:01:43: ne2k-pci.c:v1.02 10/19/2000 D. Becker/P. Gortmaker
00:01:43: http://www.scyld.com/network/ne2k-pci.html
00:01:43: PCI: Found IRQ 9 for device 00:10.0

Partiendo y juntando cadenas
Si se posee una cadena, como una entrada del archivo /etc/passwd, que tiene campos separados por 
delimitadores (en ese ejemplo el :), se puede separar esta cadena por campos para poder utilizar 
aquellos que nos sean de interes. Para ello existe una función que despedaza una cadena en una lista, 
donde cada elemento de la lista es un campo. Esta función se llama explode y lleva dos parámetros. 
El primero es una cadena que específica el delimitador que se quiere usar y el segundo parámetro es la 
cadena que se quiere romper. explode devolverá luego una lista con todos los campos.
Para el ejemplo del /etc/passwd: 

$entrada = "root:x:0:0::/root:/bin/bash";
$campos = explode(":", $entrada);

Dejará en $campos el arreglo ("root", "x", 0, 0, ,"/root,/bin/bash"). Luego se 


podrá utilizar facilmente cualquier campo. 
Para hacer el proceso inverso existe la función implode. Esta como primer parámetro el delimitador 
con el que se quiera juntar los campos de una lista, y como segundo parámetro la lista con los campos a 
juntar. implode devolverá una cadena con todos los campos unidos por el delimitador.
Para cambiar el delimitador en una entrada del archivo de configuración (considerando el código que se 
ejecuto antes): 

$nueva_salida = implode("#", $campos);

Esto dejará en $nueva_salida la cadena "root#x#0#0##/root#/bin/bash". 

Ejercicios
1. ¿Que es un patron y para que puede ser usado? 
2. Hacer un programa que permita ingresar numeros (positivos y negativos) por teclado y los 
valide. Para ello se debera usar una expresion regular. Se considerara un numero solo aquellas 
entradas que posean digitos unicamente (sin espacios). Aquellas entradas que no sean numericas 
deberan ser impresas en la salida de error estandar (STDERR). 
3. Se posee un archivo con palabras (una por linea) que representa todas las palabras que hay en un 
diccionario de español (dict.txt). Se pide hace un programa que le pida al usuario una 
terminacion y que busque en dicho diccionario todas aquellas palabras que tengan esa 
terminacion. Tanto la terminacion como el archivo de palabras se debera poder pasar como un 
argumento desde la linea de comandos 
4. El comando who -u muestra a los usuarios que estan conectados, en que terminal, en que 
Carrera Linux 2008 ­ Programacion PHP                                                                 24

fecha y hora, y cuanto tiempo estuvieron inactivos. Considerando que la ultima columna 
muestra cuanto tiempo estuvieron inactivos (los que estan activos tiene un .), se pide hacer un 
programa que muestre cual es el usuario que mas tiempo sin hacer nada. 
5. El archivo /proc/meminfo posee informacion sobre la memoria. De este archivo se pide extraer 
el valor asociado a MemFree y a MemTotal (Memoria libre y Memoria total 
respectivamente). Luego el programa debera informar que porcentaje de memoria esta libre en 
ese momento. 

5 ­ Funciones y módulos
Funciones
Una función es una agrupacion de sentencias, decisiones, y ciclos que realizan una tarea común. Estos 
nos trae varios beneficios: 
1. Reutilización: Una función puede ser usada varias veces sin necesidad de reescribirla cada vez 
que haya que usarla. 
2. Abstracción: Cuando una función esta hecha, ya no importa como es que lo hace sino que es lo 
que hace. De esta forma nos permite concentrarnos en el problema más grande, dejando de lado 
los detalles de la implementación. 
3. Menos errores: Al separar el programa en partes más pequeñas es más fácil ubicar y corregir 
los errores. Además, una función bien hecha ya no posee errores, y cuando se reutilize habra 
menos errores en el campo general. 
Una función puede depender de algunos parámetros de entrada. Si por ejemplo tenemos una función 
que calcula el factorial de un número, será necesario pasarle a la función sobre que número se quiere 
trabajar. La cantidad de argumentos puede ir desde cero hasta los que se quiera.
Tambien una función puede devolver un valor. En el ejemplo anterior, será necesario que la función 
devuelva el factorial calculado. 
En PHP para definir una función utilizaremos la palabra reserva function seguida del nombre de la 
función, su argumentos y el bloque de código correspondiente.
En general sería: 

function nombre_de_la_funcion($arg1, $arg2, $arg3) {


# Bloque de codigo
}

Los argumentos se definen como variables normales, y pueden tomar cualquier valor, desde una cadena 
hasta un array.
Para devolver un valor se llama a la funcion return seguida del valor a devolver.
Cuando se define una función, el código que de la misma no se ejecuta. Solo se ejecutará si se llama a 
la función (como cuando se hacia con rand). Para llamar a una función pondremos el nombre de ella y 
seguido y entre paréntesis sus argumentos (si no hay argumentos se escribira solamente los paréntesis). 
Carrera Linux 2008 ­ Programacion PHP                                                                 25

Veamos un ejemplo: La definición del a función será: 

function factorial($numero) {
$fact = 1;
while($numero > 0) {
$fact = $fact * $numero;
$numero = $numero - 1;
}
return $fact;
}

Luego en alguna parte del código veremos un llamada del estilo: 

$x = factorial(4);

En este caso, $x tendrá el valor 24 (4!).
Aclaración: Las variables que se definen dentro de una función, existen solamente dentro de la misma 
y no afectará a variables que tengan el mismo nombre y se encuentren afuera de la función. 

Ejemplo integrador
Para ejemplificar el pasaje y devolución de valores haremos dos funciones: una que nos diga si un valor 
está o no dentro de un arreglo. Y otra que nos diga cual es el mayor valor dentro de un arreglo.
El código del primer ejemplo será: 

function esta($valorBuscar, $arreglo) {


foreach($arreglo as $valorArreglo) {
if($valorArreglo == $valorBuscar) {
return true;
}
}
return false;
}

Esta función tomará dos parámetros: el elemento a buscar y un arreglo en donde hacerlo. Luego 
devolverá verdadero si lo encuentra o falso si no lo encuentra. Para ello, irá recorriendo el arreglo y 
preguntando cada elemento contra el valor a buscar. Si lo encuentra, entonces devuelve verdadero y la 
función termina (no se siguen consultando los demas valores).
Si se termino de recorrer el arreglo, entonces no se ha encontrado el elemento y se devolverá falso.
Si ejecutamos: 

$miArreglo = array(45, 76, 12, 765);


if(esta(76, $miArreglo)) {
echo "El valor se encuentra en el arreglo";
}

se mostrará por pantalla el mensaje del echo. 
Carrera Linux 2008 ­ Programacion PHP                                                                 26

El código de la segunda función es: 

function buscarMayor($arreglo) {
$indiceMayor = $0;
$valorMayor = $arreglo[0];
foreach($arreglo as $indice => $valor) {
if($valor > $valorMayor) {
$indiceMayor = $indice;
$valorMayor = $valor;
}
}
return array("INDICE" => $indiceMayor, "VALOR" => $valorMayor);
}

En este caso se le pasará a la función un arreglo y esta nos devolverá otro arreglo con dos datos: el 
índice del mayor elemento, y el valor del mismo.
Para buscar al mayor iremos guardando en una variable el mayor valor encontrado al momento de 
recorrer el arreglo (comenzando con que el primero es el mayor). Entonces si encontramos que un valor 
del arreglo ($valor) es más grande que el que teniamos guardado ($valorMayor), lo 
reemplazamos por el nuevo (al igual que al índice).
Al terminar el ciclo, en $valorMayor quedará el valor más grande y en $indiceMayor su índice. 
Una llamada a esta función podría ser: 

$miArreglo = array(45, 76, 12, 765);


$mayor = buscarMayor($miArreglo);
echo "El mayor es $mayor[VALOR] y esta en la posicion $mayor[INDICE]\n";

Valores por defecto
Cuando se le pasan argumentos una función se le deben pasar la misma cantidad de argumentos con la 
que fue definida.
Sin embargo, es posible darle valores por defecto. Si a un parámetro se le da un valor por defecto, 
entonces no es obligatorio especificarlo, y en el caso de no hacerlo, se usará el valor que tenga por 
defecto.
Ejemplo: 

function factorial($numero = 26) {


$fact = 1;
while($numero > 0) {
$fact = $fact * $numero;
$numero = $numero - 1;
}
return $fact;
}

factorial();
Carrera Linux 2008 ­ Programacion PHP                                                                 27

En esta caso al darle como valor por defecto 26, se puede llamar a la función sin parámetros. Por lo 
tanto, al llamarla de este modo, se calcularía el factorial de 26.
Como última aclaración diremos que los parámetros que tengan valores por defecto serán los que 
aparezcan últimos en el momento en que se define la función. 

Recursividad
El concepto de recursividad es simplemente hacer que una función se llame a si misma. Esto es útil 
cuando se necesita hacer un proceso que requiere hacer subprocesos que sean iguales a él. Por ejemplo, 
el recorrer toda una jerarquía de directorios. Recorrer un subdirectorio es lo mismo que recorrer el 
directorio actual, y así sucesivamente. El clásico ejemplo es el de calcular el factorial. El factorial de un 
número n, es igual al producto de si mismo por todos los demas que lo preceden hasta el 0 (o sea, el 
número multiplicado por el factorial del anterior). Y además, el factorial de 0 es 1.
Una función que calcule el factorial de un número n sería: 

function factorial($n) {
if($n == 0) {
return 0;
}
return $n * factorial($n - 1);
}

Módulos
Una vez que tengamos muchas funciones, vamos a necesitar utilizarla desde otros scripts. Sería muy 
incomodo tener que estar abriendo el archivo que tiene la función, copiarla y pegarla en el nuevo. 
Además si se modifica en algun lado la función habría que buscar todos los archivos que la tengan 
definida y modificarlos también.
Lo mejor es tener todas las funciones que se puedan utilizar por varias páginas en archivos separados, y 
"traer" estos archivos a nuestro PHP. Esto se logra con la construcción require_once. Si por 
ejemplo tenemos un archivo utils.php que tiene definida todas las funciones generales, podemos 
traer todas estas funciones a nuestro archivo actual de la siguiente forma:

require_once("utils.php");

Con solo agregar esta línea al principio del programa tendremos disponibles todas las funciones que se 
encuentre allí.
Existe otra construcción que es muy útil llamada include. include se diferencia de require_once en que 
include trae todo el archivo y lo reemplaza en donde se encuentre la llamada. Por lo tanto escribir: 

include("error.php");

sería idéntico a copiar y pegar todo el contenido de error.php en donde se encuentra el include.
Carrera Linux 2008 ­ Programacion PHP                                                                 28

Esta construcción será más útil cuando se vea la programación web ya que servirá para redireccionar a 
otra página haciendo un include de la misma.
Otra diferencia entre require_once e include es que la primera se ejecuta siempre, 
independientemente de donde se haya escrito y la segunda se ejecuta solo si la ejecución pasa por allí.

Ejercicios
1. Enuncie cuales son las ventajas de utilizar funciones 
2. Hacer una funcion (elegir_opciones) que se le pasen varias cadenas (cada una de ellas es 
una opcion) dentro de un arreglo. Esta funcion debe mostrarle al usuario todas las opciones 
disponibles y luego debe permitirle elegir una de ellas. Si el usuario ingresa algo que no esta 
contemplado en esas opciones debe pedirle que ingrese una opcion nuevamente (tambien le 
muestra las opciones nuevamente. Por ejemplo, la llamada: 
elegir_opciones (array("agregar", "borrar", "consultar", "salir"));

debe producir una salida similar a esta: 
agregar
borrar
consultar
salir

Ingrese su opcion:

Si el usuario no ingresa ninguna de esas cuatros palabras la salida debe repetirse y tambien la 
entrada. 
3. Realizar una subrutina que devuelva una lista con todos los usuarios cuyo UID sea menor que 
500 (privilegios de administrador. Luego realizar otra funcion que tomando esta lista como 
parametros, lea desde otro archivo varios nombres de usuarios y devuelva una lista con aquellos 
que no se encuentren alli. 
4. Realizar una subrutina que se le pase por parametro el nombre de un servicio (ejemplo, "ftp", 
"http", etc) y devuelva el puerto al que esta asociado. Para ello, debera obtener la informacion 
desde el archivo /etc/services.
Se debe investigar como es el formato del archivo /etc/services y se debe crear la expresion 
regular (una sola) que lo represente. 
5. Hacer una subrutina que implemente lo inverso de la anterior. Debe obtener por parametro un 
puerto y luego debe devolver una cadena con el servicio asociado. 

Clase 6 ­ Manejo de archivos y directorios
Introducción
Existen algunas funciones para trabajar sobre archivos y directorios en el sistema. Estas funciones no 
Carrera Linux 2008 ­ Programacion PHP                                                                 29

requieren de comandos externos sino que se comunican directamente con el Sistema Operativo para que 
las haga. 

Directorio Actual
La función getcwd devuelve una cadena con el directorio actual. Esta función no lleva parametros.
Ejemplo: 

echo "El directorio actual es: ", getcwd(), "\n";

mostrará por pantalla un mensaje informando el directorio actual. 

Cambio de directorio
La función chdir cambia el directorio actual al que se le especifique por parámetro.
Por ejemplo: 

chdir("/usr/bin");

cambiará el directorio actual a /usr/bin. 

Creación de un directorio
La función mkdir crea un directorio. Esta función lleva como primer parámetro el directorio que se 
quiere crear y como segundo parámetro (opcional) los permisos que se quieren otorgarle (NOTA: para 
escribir un valor en octal para usarlo de la misma forma en que se usa el chmod, el número debe 
empezar con 0).
Por ejemplo: 

mkdir("/home/pepe");

le crea el directorio personal al usuario pepe. 

mkdir("/home/pepe", 0700);

le crea el directorio personal al usuario pepe con los permisos 700. 

Eliminación de un directorio
Para eliminar un directorio se utiliza la función rmdir. Para poder llevar a cabo esta acción el diretorio 
debe estar vacío. Esta función solo lleva un parámetro que indique el directorio que se desea eliminar.
Por ejemplo: 

rmdir("/home/pepe");
Carrera Linux 2008 ­ Programacion PHP                                                                 30

Le quita el directorio personal al usuario pepe. 

Copiado de un archivo
La función copy sirve para hacer una copiar de un archivo. Esta función lleva de parámetros el nombre 
del archivo que se quiere copiar y el nombre del nuevo archivo. Si el nombre del nuevo archivo ya 
existe, entonces se perderán los datos del mismo.
Por ejemplo: 

copy("backup.tgz", "backup-2003-04-22.tgz");

Renombrar un archivo
La función rename sirve para cambiarle el nombre a un archivo. Esta función lleva de parámetros el 
nombre del viejo archivo y el nombre del nuevo archivo. Si el nombre del nuevo archivo ya existe, 
entonces se perderán los datos del mismo.
Por ejemplo: 

rename("backup.tgz", "backup-2003-04-22.tgz");

Eliminación de archivos
Para llevar a cabo esta tarea existe la función unlink. Esta función lleva como parámetro el archivo 
que se quiere eliminar.
Por ejemplo: 

unlink("backup.tgz");

Cambio de permisos
Es posible modificarle los permisos a un archivo de forma similar a utilizar el comando chmod. Para 
ello existe una función del mismo nombre, la cual lleva como parámetros el nombre del archivo y los 
nuevos permisos (los permisos igual que con mkdir).
Ejemplo: 

chmod("/home/mi_dir/solo_yo_lo_leo", 0700);

le da los permisos 0700 a al archivo "solo_yo_lo_leo". 

Cambio de dueño
Es posible modificar el dueño a un archivo de forma similar a utilizar el comando chown. Para ello 
Carrera Linux 2008 ­ Programacion PHP                                                                 31

existe una función del mismo nombre, la cual lleva como parámetros el nombre del archivo y el nombre 
del nuevo dueño.
Solo el superusuario puede cambiar los dueños de todos los archivos.
Ejemplo: 

chown("/home/mi_dir/solo_yo_lo_leo", "demian");

le otorga el archivo "solo_yo_lo_leo" al usuario "demian". 

Cambio de grupo
Es posible modificar el grupo a un archivo de forma similar a utilizar el comando chgrp. Para ello 
existe una función del mismo nombre, la cual lleva como parámetros el nombre del archivo y el nombre 
del nuevo grupo.
Solo el superusuario puede cambiar los grupos de todos los archivos.
Ejemplo: 

chgrp("/home/mi_dir/solo_yo_lo_leo", "nobody");

le otorga el archivo "solo_yo_lo_leo" al grupo "nobody". 

Separar directorio/archivo de una ruta completa
Si se posee la ruta completa a un archivo existen dos funciones para obtener estos datos por separados. 
La primera es dirname la cual devuelve el directorio y la segunda es basename la cual devuelve el 
nombre del archivo.
Ejemplo: 

$archivo = "/etc/X11/XF86Config";
echo "Archivo: ", basename($archivo), "\n";
echo "Directorio: ", dirname($archivo), "\n";

Esto generará las siguientes líneas: 

Archivo: XF86Config
Directorio: /etc/X11
Carrera Linux 2008 ­ Programacion PHP                                                                 32

Información sobre archivos

is_writeable
Esta función toma como parámetro el nombre de un archivo y devuelve verdadero si el archivo tiene 
permiso de escritura. 

is_readable
Esta función toma como parámetro el nombre de un archivo y devuelve verdadero si el archivo tiene 
permiso de lectura. 

is_executable
Esta función toma como parámetro el nombre de un archivo y devuelve verdadero si el archivo tiene 
permiso de ejecución. 

is_dir
Esta función toma como parámetro el nombre de un archivo y devuelve verdadero si el archivo es un 
directorio. 

is_file
Esta función toma como parámetro el nombre de un archivo y devuelve verdadero si el archivo es un 
archivo normal. 

is_link
Esta función toma como parámetro el nombre de un archivo y devuelve verdadero si el archivo es un 
link. 

file_exists
Esta función toma como parámetro el nombre de un archivo y devuelve verdadero si el archivo existe. 

filesize
Esta función toma como parámetro el nombre de un archivo y devuelve el tamaño (en bytes) del archivo 
especificado. 
Carrera Linux 2008 ­ Programacion PHP                                                                 33

fileowner
Esta función toma como parámetro el nombre de un archivo y devuelve dueño (UID) del archivo. 

filegroup
Esta función toma como parámetro el nombre de un archivo y devuelve grupo (GID) del archivo. 

fileatime
Esta función toma como parámetro el nombre de un archivo y devuelve la fecha (en formato timestamp) 
del último acceso a ese archivo. 

filemtime
Esta función toma como parámetro el nombre de un archivo y devuelve la fecha (en formato timestamp) 
de la última modificación a ese archivo. 

filectime
Esta función toma como parámetro el nombre de un archivo y devuelve la fecha (en formato timestamp) 
del último cambio al i­nodo correspondiente al archivo. 

stat
Esta función toma como parámetro el nombre de un archivo y devuelve un arreglo con toda la 
información obtenida por las funciones anteriores. 

Listado de Archivos y Directorios
Existe dos formas para obtener todos los archivos y subdirectorios que existan dentro de un directorio. 

Glob
La primer opción es la función glob. Esta función tiene como argumento el directorio y los archivos 
que se quieren listar. En esta función se especifican de la misma forma que hace el shell. Esto significa 
que el caracter * y el ? no seran interpretados literalmente sino que el * concordará con cualquier tipo 
y cantidad caracteres y el ? concordará con un solo caracter cualquiera.
glob me devolverá una lista donde cada elemento es el nombre de uno de los archivos encontrados.
glob omite por defecto todos los archivos y directorios que comienzen con un punto (.).
Por ejemplo, para obtener todos los archivos jpg de mi directorio imágenes: 

$archivos = glob("./imagenes/*jpg");
foreach($archivos as $archivo) {
echo "$archivo\n";
Carrera Linux 2008 ­ Programacion PHP                                                                 34

opendir, readdir, closedir
La segunda opción es similar al uso de archivos. Esta consta en abrir el directorio, leer de el todos los 
archivos y subdirectorios y luego cerrarlo. Para la primera operación se utiliza la función opendir
que es análoga a fopen. Esta función devuelve un descriptor de directorio (nombre de la variable con 
la cual se va a hacer referencia el directorio en mi programa en PHP) y luego una cadena con el 
directorio que se quiere ver.
Luego la función readdir va devolviendo por cada llamada un archivo. Por defecto, la función 
readdir no ignora (como lo hacia glob) el directorio . (directorio actual) y el .. (directorio padre). 
Como parámetro para readdir se debe utilizar un descriptor abierto con la función opendir.
Una vez leídos todos los archivos se cierra el directorio con closedir.
Ejemplo: 

$dir_h = opendir("/etc");
while($archivo = readdir($dir_h)) {
echo "$archivo\n";
}
closedir($dir_h);

Argumentos desde la línea de comandos
Cuando ejecutamos nuestros scripts es posible recuperar los argumentos pasados al mismo desde la 
línea de comandos. Para ello, existe un arreglo llamado argv, el cual se crea y lo completa 
automaticamente por PHP. Este arreglo contendrá en la posición 0 el nombre del script y en las 
posiciones siguientes tendrá todos los argumentos que restan.
Por ejemplo, si ejecutamos nuestro scripts de la siguiente forma: 

$ ./mi_programa -v -f datos.txt "Hola Mundo"

El vector argv tendrá: 

0 ./mi_programa
1 -v
2 -f
3 datos.txt
4 Hola Mundo

De esta forma es posible recuperar todos los argumentes.
También existe una variable llamada argc la cual contiene la cantidad de elementos que hay en el 
arreglo argv (en este caso 5). 
Carrera Linux 2008 ­ Programacion PHP                                                                 35

getopt
Si estamos interesados en que nuestro comando tome argumentos del estilo ­ seguido de una letra (o ­ 
seguido de una letra y un valor asociado a esa opción), disponemos de una función que interpreta al 
arreglo argv de manera de facilitarnos el reconocimiento de este formato.
A esta función se le debe proveer una cadena la cual consistirá de las letras que deseemos que se 
reconozcan como opciones válidas. Aquellas que posean un valor asociado se le debes poner un :
despues de la letra.
Luego, esta función devolverá un arregla en donde las claves serán las opciones ingresadas, y como 
valor tendrá falso en el primer caso y el argumento asociado en el segundo.
Por ejemplo: 

$ops = getopt("xhf:");
if(isset($ops["x"])) {
echo "Esta activada la opcion X\n";
}
if(isset($ops["h"])) {
echo "Esta activada la opcion H\n";
}
if(isset($ops["f"])) {
echo "Esta activada la opcion F\n";
}

En este ejemplo solo se aceptan las opciones h, x, y f (esta posee un valor asociado). Si ejecutamos el 
script: ./mi_prog -x -f hola mostrará por pantalla: 

Esta activada la opcion X


Esta activada la opcion F

Vale destacar que al poner falso en las variables que estan activadas (el valor asociado es falso, pero la 
entrada en el arreglo esta definida) se debe utilizar la función isset para determinar si esa posición 
esta o no elegida. 

Ejercicios
1. ¿Cual es la diferencia entre opendir/readir/closedir y glob? 
2. Hacer un programa que liste todos los archivos de un directorio (especificado como un 
argumento desde el shell) ordenados alfabeticamente. El programa debera mostrar todos los 
archivos del directorio especificado y tambien todos aquellos que existan dentro de algun 
subdirectorio del mismo. 
3. Hacer un programa que haga una copia de un directorio (especficado como un argumento desde 
el shell) a otro directorio (tambien especficado como un argumento desde el shell). Luego de la 
operacion ambos directorios deberian ser identicos.
NOTA: se deberan copiar todos los archivos del directorio como asi todos los existentes en 
subdirectorios del mismo. 
4. Hacer un programa que nos indique cuanto (por parametro se debe especificar si verlo en bytes, 
Carrera Linux 2008 ­ Programacion PHP                                                                 36

kilobytes, megabytes, gigabytes, etc) espacio se esta utilizando para cada usuario en el sistema. 
5. Hacer un programa que guarde en un archivo de texto plano todas las entradas de un directorio 
dado (junto con el tamaño del archivo). Luego se debera generar otro programa que compare el 
contenido de ese archivo con el estado actual en el disco.
El programa debera alertar tanto en el caso que se encuentre una entrada que esta en el archivo y 
no este en el disco, como asi tambien entradas que esten en el disco pero no esten en nuestro 
archivo de texto. Tambien se debera alertar si el tamaño ha variado. 

Clase 7 ­ Biblioteca estándar de funciones
Manejo de cadenas

addslashes
Esta función sirve para escapar las comillas dentro de una cadena. Esto será especialmente útil cuando 
se utilicen consultas dentro de una base de datos.
Si poseemos la cadena "Hola O'Reilly", si la pasamos por addslashes obtendremos otra cadena 
que tendrá la forma "Hola O\'Reilly".
Ejemplo: 

$cadena = "Hola O'Reilly";


$cadenaNueva = addslashes($cadena);
echo "$cadenaNueva"; # Hola O\'Reilly

chop ­ rtrim
Elimina los espacios en blanco del final de una cadena.
Ejemplo: 

$linea = fgets(STDIN);
$lineaLimpia = chop($linea); #Elimino el \n y todos los blancos que haya ingresado
el usuario

str_replace
Esta función nos permite hacer reemplazo dentro de una cadena. Teniendo una cadena de origen, 
podemos reemplazarla parte de la misma por una cadena a voluntad.
Su prototipo es: 

str_replace ( $cadena_buscada, $cadena_sustituta, $cadena_original)


Carrera Linux 2008 ­ Programacion PHP                                                                 37

Por ejemplo: 

$cadena = "aaaBBBccc";
$cadenaNueva = str_replace("BBB", "bbb", $cadena);
echo "$cadenaNueva\n"; # Mostrara aaabbbccc

strlen
Esta función nos devuelve la cantidad de caracteres que posee una cadena.
Ejemplo: 

$cadena = "Hola Mundo";


$largo = strlen($cadena); # Devuelve 10

strtoupper ­ strtolower
Estas funciones sirven para transformar toda una cadena a mayúsculas o a minúsculas, respectivamente.
Por ejemplo: 

$cadena = "Hola Mundo";


$cadenaMayusculas = strtoupper($cadena); # HOLA MUNDO
$cadenaMinusculas = strtolower($cadena); # hola mundo

ucfirst
Esta función pone en mayúscula el primer caracter de una cadena.
Por ejemplo: 

$cadena = "hola mundo";


$cadenaNueva = ucfirst($cadena); # Hola mundo

ucwords
Esta función pone en mayúscula el primer caracter de cada palabra dentro de una cadena.
Por ejemplo: 

$cadena = "hola mundo";


$cadenaNueva = ucwords($cadena); # Hola Mundo

wordwrap
Esta función corta a una cadena en caracteres de como maximo un tamaño, especificados por 
Carrera Linux 2008 ­ Programacion PHP                                                                 38

parámetro, agregando un separador entre las palabras que excedan ese límite.
Por ejemplo: 

$cadena = "Este es un mensaje de prueba, para cortarlo y ver que queda";


$nuevaCadena = wordwrap($cadena, 20, "\n");

y en $nuevaCadena quedará: 

Este es un mensaje\n
de prueba, para\n
cortarlo y ver que\n
queda.\n

Manejo de arreglos

array_merge
Esta función fusiona muchos arreglos pasados como argumentos en un único arreglo. Si los arreglos a 
fusionar tienen claves repetidas, entonces se tomará el valor de la última aparición. Si son númericas se 
agregarán todos al final.
Por ejemplo: 

$arreglo1 = array(45, 67, 23);


$arreglo2 = array("nombre" => "Pepe", "color" => verde);
$arregloNuevo = array_merge($arreglo1, $arreglo2);
# el nuevo arreglo es
# 0 => 45
# 1 => 67
# 2 => 23
# nombre => Pepe
# color => verde

array_pop
Devuelve el último elemento de un arreglo, y lo elimina del mismo. Si el arreglo esta vacío, devolverá 
vacío.
Ejemplo: 

$arreglo = array(45, 76, 12, 33);


$ultimoElemento = array_pop($arreglo); # 33
# $arreglo quedara con (45, 76, 12)
Carrera Linux 2008 ­ Programacion PHP                                                                 39

array_push
Agrega un elemento al final del arreglo.
Ejemplo: 

$arreglo = array(45, 76, 12, 33);


array_push($arreglo, 29);
# $arreglo quedara con (45, 76, 12, 33, 29)

NOTA: Usar array_push es lo mismo que utilizar los corchetes vacíos ([]) de la siguiente forma: 

$arreglo[] = 29;

array_shift
Devuelve el primer elemento de un arreglo, y lo elimina del mismo, reduciendo la cantidad de 
elementos en uno. Si el arreglo esta vacío, se devuelve vacío.
Ejemplo: 

$arreglo = array(45, 76, 12, 33);


$ultimoElemento = array_shift($arreglo); # 45
# $arreglo quedara con (76, 12, 33)

array_unshift
Esta función agrega un elemento al principio del arreglo, desplazando a los demás elementos.
Ejemplo: 

$arreglo = array(45, 76, 12, 33);


array_unshift($arreglo, 29);
# $arreglo quedara con (29, 45, 76, 12, 33)

count
Devuelve la cantidad de elementos de un arreglo.
Ejemplo: 

$arreglo = array(45, 76, 12, 33);


$cantidadElementos = count($arreglo); # 4

in_array
Esta función nos permite buscar un elemento dentro de un arreglo. Si lo encuentra nos dirá verdadero, 
Carrera Linux 2008 ­ Programacion PHP                                                                 40

sino falso.
Toma dos parámetros, el primero es el elemento a buscar, y el segundo el arreglo.
Ejemplo: 

$arreglo = array("hola", "jose", "pepe");


if(in_array("hola", $arreglo)) {
echo "Esta la palabra 'hola'\n"; # Esto saldra por pantalla
}
if(in_array("report", $arreglo)) {
echo "Esta la palabra 'report'\n"; # Esto NO saldra por pantalla
}

array_search
Esta función nos permite buscar un elemento dentro de un arreglo. Si lo encuentra nos devolverá la 
clave asociada al mismo o falso si no lo encuentra.
Toma dos parámetros, el primero es el elemento a buscar, y el segundo el arreglo.
Ejemplo: 

$arreglo = array("hola", "jose", "pepe");


$clave = array_search("jose", $arreglo); # 1
$clave = array_search("report", $arreglo); # false

sort
Ordena todos los elementos de un arreglo de menor a mayor. Además asignará indices nuevos a cada 
valor, por lo que cualquier índice o clave existente se perderá.
Ejemplo: 

$arreglo = array(45, 23, 79, 55);


sort($arreglo);
# ahora el arreglo esta ordenado.
# quedara como (23, 45, 55, 79)

asort
Ordena todos los elementos de un arreglo de menor a mayor, manteniendo la relación entre las claves y 
sus valores.
Ejemplo: 

$arreglo = array("pepe" => 26, "anibal" => 23, "emilio" => 30);
asort($arreglo);
# quedara ("anibal" => 23, "pepe" => 26, "emilio" => 30)
Carrera Linux 2008 ­ Programacion PHP                                                                 41

ksort
Ordena los elementos de un arreglo, de menor a mayor, según las claves.
Ejemplo: 

$arreglo = array("pepe" => 26, "anibal" => 23, "emilio" => 30);
ksort($arreglo);
# quedara ("anibal" => 23, "emilio" => 30, "pepe" => 26)

rsort
Análoga a sort, pero ordenandor de mayor a menor. 

arsort
Análoga a asort, pero ordenando de mayor a menor. 

krsort
Análoga a ksort, pero ordenando de mayor a menor. 

Manejo de fecha

time
Esta devuelva la fecha/hora actual con el formato timestamp de UNIX. Este formato se cuenta como la 
cantidad de segundos desde el Epoch de UNIX (1 de Enero de 1970 a las 00:00:00).
Ejemplo: 

$timestampActual = time();

date
Esta función sirve para darle formato a una fecha en formato timestamp. Posee dos argumentos, el 
primero es el formato y el segundo la fecha en cuestión (si solo se usa un parámetro se tomará por 
defecto la fecha actual).
La cadena del formato es una cadena normal, en donde algunos caracteres serán reemplazados por el 
campo de la fecha correspondiente. Entre los más comunes encontramos:

Caracter Descripción
d Día. 00­31
m Mes. 00­12
Carrera Linux 2008 ­ Programacion PHP                                                                 42

Y Año 4 dígitos. AAAA
y Año 2 dígitos. AA
H Hora. 00­23
i Minutos. 00­59
s Segundos. 00­59
Ejemplo: 

# Fecha actual sin la hora


$fechaActual = date("d/m/Y");

# Fecha actual con la hora


$fechaHoraActual = date("d/m/Y H:i:s");

# Fecha de una semana a partir de la fecha actual


$fechaUnaSemana = date("d/m/Y", time() + (60 * 60 * 24 * 7));

# Dia actual
$dia = date("d");

checkdate
Controla si una fecha es válida (Año bisiesto, días incorrectos, etc). Posee 3 parámetros: mes, dia y año. 

Ejemplo: 

if(checkdate(2, 31, 2006)) {


echo "La fecha 31/2/2006 es correcta\"; # Esto NO se vera
}

if(checkdate(12, 20, 2006)) {


echo "La fecha 20/12/2006 es correcta\"; # Esto SI se vera
}

Ejercicios
1. Hacer un programa que lea desde STDIN tantas lineas como haya. Luego las debera mostrar por 
pantalla ordenadas de menor a mayor por el largo de las mismas. 
2. Se pide cargar dos arreglos con numeros (leidos desde dos archivos de texto). Luego se debe 
ordenar ambos arreglos por separado. Finalmente se debe mostrar por la salida estandar los 
numeros de ambos arreglos ordenados en su totalidad, aplicando la siguiente idea: Se debe ir 
leyendo simultaneamente de cada arreglo un elemento, comparandolos y mostrando el menor, 
para luego leer el proximo desde el arreglo que se acaba de mostrar. Al final, se debe tener toda 
una salida ordenada. 
Carrera Linux 2008 ­ Programacion PHP                                                                 43

3. Dado un directorio cualquiera, se pide hacer un script que nos permita ver todos los archivos 
que correspondan a un mes pedido por parametro. 
4. Mostrar todos los archivos de un directorio (y de sus subdirectorios) ordenados por su fecha de 
ultimo acceso. 
5. Se pide hacer un script que filtre palabras en un archivo de texto (origen).
Este programa requiere que le pasen un archivo de texto por parametro. Tambien se posee otro 
archivo con palabras a filtrar (una por linea). Se tiene que generar un archivo nuevo con el 
contenido del archivo de origen pero reemplazando las palabras que aparezcan en el archivo de 
filtros por asteriscos (*). Se debe poner tantos asteriscos como letras tenga la palabra. 

Clase 8 ­ Servicios de Internet
Simple Mail Transfer Protocol (SMTP)
Uno de los servicios más comúnes en internet es el correo electrónico. Más precisamente, para enviar 
correo se utiliza el protocolo SMTP (Simple Mail Transfer Protocol). Para hacer uso de este protocolo, 
PHP posee una función llamada mail. Esta función no implementa este protocolo, sino que hará falta 
tener instalado sendmail en la máquina donde se ejecute el script.
Esta función tiene 3 parámetros obligatorios: el/los destinatarios, el asunto y el mensaje.
Veamos el ejemplo más simple: 

$destinatario = "alguien@algunlugar.com";
$asunto = "El coso tiene algo";
$mensaje = "Cuidado con los mensajes que divagan";

mail($destinatario, $asunto, $mensaje);

El formato del destinatario puede incluir más de una dirección (según el RFC 2822). Algunos formatos 
posibles, según el sitio de PHP, son: 
• usuario@example.com 
• usuario@example.com, otrousuario@example.com 
• Usuario <usuario@example.com> 
• Usuario <usuario@example.com>, Otro Usuario <otrousuario@example.com> 
El campo asunto no debería tener ningún salto de línea (\n) ya que esto podría hacer que el correo no 
pueda ser enviado satisfactoriamente. 
El campo mensaje si puede contener saltos de línea. También se recomienda que si existe alguna línea 
que contenga más de 70 caracteres, esta se cortada en dos. Para esto viene útil la función wordwrap. 
Entonces, si queremos estar seguros que el mensaje quede entre los límites definidos podemos hacer: 

$mensaje = wordwrap($mensaje, 70, "\n");


Carrera Linux 2008 ­ Programacion PHP                                                                 44

También es posible agregar otras cabeceras más especificas del protocolo SMTP. Para ello, se le puede 
pasar, opcionalmente, un cuarto parámetro con una cadena que contenga cabeceras SMTP para enviar 
tal cual se pasa.
Si por ejemplo, queremos configurar la dirección de respuesta (el From) podemos agregar la cabecera: 

$cabeceras = "From: micorreo@miservidor.com";


mail($destinatario, $asunto, $mensaje, $cabeceras);

Entre otras cabeceras comúnes encontramos Reply­To (la dirección a quien deben responder), CC 
(copia del email), BCC (copia oculta del email) y Content­Type (para setear que tipo de email es: texto, 
html, etc). Las cabeceras deben ser separadas por \r\n.
Podríamos tener entonces una cabecera como la siguiente: 

$cabeceras = "Content-type: text/html; charset=iso-8859-1\r\n


Reply-To: correo_real@miservidor.com\r\n
CC: quien_controla@unservidor.com\r\n
BCC: El Jefe quien_realmente_controla@unservidor.com";

mail($destinatario, $asunto, $mensaje, $cabeceras);

Post Office Protocol (POP)
Para descargar y consultar el correo electrónico se utiliza el protocolo POP3 (Post Office Protocol). 
Este nos permitirá consultar los correos, descargarlos, y obtener información sobre ellos. 

Conexión al servidor
Para conectarnos al servidor utilizaremos la función imap_open. Ella nos permite conectar a distintos 
servicios, pero por ahora utilizaremos solo lo necesario para POP3.
La función requiere 3 parámetros: el servidor con el formato {servidor/pop3:110}INBOX, el 
usuario y la contraseña.
Si se logra conectar al servidor, nos devolverá un objeto desde el cual podremos consultar la casilla, en 
caso contrario devolverá falso.
Ejemplo: 

$pop = imap_open("{pop.servidor.com/pop3:110}INBOX","usuario","password");
if(!$pop) {
die("Error: " .imap_last_error());
}

Cantidad de mensajes
La cantidad de mensajes que hay en la casilla puede obtener mediante la función imap_num_msg. 
Esta función nos devolverá un número con dicha cantidad. 
Carrera Linux 2008 ­ Programacion PHP                                                                 45

En código: 

$cantidadMensajes = imap_num_msg($pop);

Recuperando mensajes
Para recuperar los en utilizaremos la función imap_fetch_overview la cual nos dará un arreglo 
con un objeto con toda la información generica para cada uno de los mensajes elegidos.
De parámetros deberémos especificarle el recursos POP y la sequencia de mensajes. La secuencia 
puede ser tanto un único número de mensaje (se devuelve ese solo), una lista de números separados por 
comas (se devolverá cada uno de los elegidos) o dos números separados por un dos puntos (:) (lo cual 
nos traerá todo el rango, 1:3 trae 1, 2 y 3).
Entre los campos para cada mensajes nos encontramos con: 

Campo Descripción
subject Título del mensaje
from Quien envio el mensaje
to Destinatario
date Fecha de envío
message_id ID del mensaje
in_reply_to Es una respuesta al ID del mensaje que tiene
size Tamaño del mensaje, en bytes
uid Identificador del mensaje
msgno Número del mensaje
En nuestro ejemplo, traeremos todos los mensajes utilizando la cantidad (1:cantidad): 

$cantidadMensajes = imap_num_msg($pop);
if($cantidadMensajes > 0) {
$encabezados = imap_fetch_overview($pop, "1:$cantidadMensajes");
foreach($encabezados as $encabezadoMensaje) {
echo "$encabezadoMensaje[from]\t$encabezadoMensaje[subject]\n";
}
}

Para recuperar el cuerpo del mensaje poseemos la función imap_body. Esta función recibe dos 
parámetros, el recurso POP y el número de mensaje. Luego obtendremos una cadena con todo el 
cuerpo. Debemos aclarar que cada línea estará separada por un \r\n.
Para recuperar el cuerpo del mensaje 2 solo debemos hacer: 

$cuerpoMensaje = imap_body($pop, 2);


echo "$cuerpoMensaje";
Carrera Linux 2008 ­ Programacion PHP                                                                 46

Eliminación de mensajes
Para eliminar los mensajes del servidor se requieren dos pasos. Primero se deben marcar los mensajes 
que se quiere eliminar. Luego se debe dar la orden de eliminarlos.
Para el primero de los pasos se posee la función imap_delete. Como es de esperarse esta función 
requiere el recurso POP y el número de mensaje a eliminar.
Para el segundo paso se posee la función imap_expunge. Para esta, solo se necesita el recursos POP. 
Cabe destacar que solo hará falta hacer una única llamada a esta función, mientras que se harán varias a 
imap_delete. 
Por ejemplo: 

imap_delete($pop, 1);
imap_delete($pop, 2);
imap_delete($pop, 3);
imap_expunge($pop); // Los mensajes 1, 2 y 3 fueron eliminados por completo

File Transfer Protocol (FTP)
Este servicio es muy utilizado para transferir archivos. El FTP (File Transfer Protocol) es, en 
definitiva, ni más ni menos que un simple servidor de archivos. 

Conexión al servidor
Conectarse a un servidor de FTP requiere de dos pasos: la conexión y la autentificación.
Para realizar el primer paso utilizaremos la función ftp_connect. Esta función requiere de un 
parámetro básico que es la dirección del servidor.
Luego si todo a funcionado bien nos devolverá un recurso desde el cual acceder al FTP, en caso 
contrario nos devolverá falso. 
Para hacer el segundo paso utilizaremos la función ftp_login. Esta función requiere de 3 
parámetros: el recurso que nos permite comunicarnos con el FTP (el obtenido por ftp_connect), el 
nombre de usuario y la contraseña.
Esta función devolverá verdadero o falso según haya o no podido autentificarse contra el servidor. 
Por último, una vez terminada de usar la conexión, podemos cerrarla utilizando la función 
ftp_close y pasándole el recurso FTP como parámetro. 
En código: 

$servidor_ftp = "ftp.miservidor.com";
$usuario_ftp = "nombre_usuario";
$password_ftp = "secreta";

$ftp = ftp_connect($servidor_ftp);
if(! $ftp ) {
Carrera Linux 2008 ­ Programacion PHP                                                                 47

die("Error al conectarse a $servidor_ftp");


}

if (! ftp_login($ftp, $usuario_ftp, $password_ftp)) {


ftp_close($ftp);
die("Error al autentificarse contra el servidor");
}

// El programa...

ftp_close($id_con);

Subir archivos
Para subir archivos al servidor poseemos la función ftp_put. Esta función precisa del recurso FTP, 
una cadena que apunte al archivo local y otra al archivo remoto. Vale destacar que ambas rutas al 
archivo pueden ser tanto absolutas como relativas (como en el shell). El servidor FTP también posee un 
directorio actual para cada usuario conectado. 
Si todo a funcionado correctamente ftp_put devolverá verdadero, sino devolverá falso. Veamos un 
ejemplo (considerar que la conexión ya esta hecha y se posee el recurso FTP en la variable $ftp): 

$archivo_local = "datos.txt";
$archivo_remoto = "./datos/usuario_datos.txt";
if (! ftp_put($ftp, $archivo_remoto, $archivo_local)) {
echo "Error al tratar de subir el archivo $archivo_local\n";
}
// Si no hubo errores el archivo datos.txt estará en el servidor como
./datos/usuario_datos.txt

Descargando archivos
Para traer un archivo desde el servidor a nuestra máquina, debemos usar la función ftp_get. Esta es 
similar a ftp_put pero hará lo inverso y tendrá, por lo tanto, lo mismo parámetros pero invertidos el 
archivo local con el archivo remoto. 

$archivo_remoto = "libreria_quemefalta_lap-1.43.546376.rpm";
$archivo_local = "lib.rpm";

if (! ftp_put($ftp, $archivo_local, $archivo_remoto)) {


echo "Error al tratar de descargar el archivo $archivo_remoto\n";
}
// Si no hubo errores el archivo libreria_quemefalta_lap-1.43.546376.rpm estará en
la maquina local como lib.rpm
Carrera Linux 2008 ­ Programacion PHP                                                                 48

Eliminando y renombrando una archivo remoto
Para eliminar un archivo que es encuentre en el FTP debemos usar la función ftp_delete. 
Sencillamente habrá que pasar el recurso FTP y la ruta al archivo a borrar.
Si todo funciona bien nos devolverá verdadero o falso en caso contrario. 
Ejemplo: 

$archivoBorrar = "datos_temp.txt";
$ok = ftp_delete($ftp, $archivoBorrar);
if($ok) {
echo "Se ha borrado exitosamente el archivo $archivoBorrar\n";
} else {
echo "Ha ocurrido un error al tratar de borrar el archivo
$archivoBorrar\n";
}

Para renombrar tenemos la función ftp_rename la cual necesita del recurso FTP, el nombre de 
archivo viejo y el nuevo.
Si todo funciona bien nos devolverá verdadero o falso en caso contrario. 
Ejemplo: 

$archivoViejo = "datos_temp.txt";
$archivoNuevo = "datos_hoy.txt";
$ok = ftp_rename($ftp, $archivoViejo, $archivoNuevo);
if($ok) {
echo "Se ha renombrado exitosamente el archivo $archivoViejo\n";
} else {
echo "No se ha podido renombrar el archivo $archivoViejo a
$archivoNuevo\n";
}

Manejo de directorios
Al igual que en la máquina local, poseemos comandos para crear y borrar directorios como así también 
para cambiar el directorio actual, y recuperar el mismo. Respectivamente tenemos: 

Comando Descripción Retorno


ftp_mkdi Crea un directorio. Se debe especificar el recurso  falso en caso de error, o una cadena 
r FTP y un cadena con el nombre del directorio  con el nombre del directorio creado. 
Elimina un directorio. Se debe pasar por 
Verdadero o falso según haya podido o 
rmdir parámetro el recurso FTP y el directorio a 
no cambiar de directorio 
eliminar
ftp_chdi Cambia el directorio actual. Se debe pasar por  Verdadero o falso según haya podido o 
r parámetro el recurso FTP y el nuevo directorio.  no cambiar de directorio 
ftp_pwd Devuelve el directorio actual. Solo se debe pasar  Una cadena con la ruta del directorio 
Carrera Linux 2008 ­ Programacion PHP                                                                 49

el recurso FTP como parámetro. actual. 

Recuperando los archivos de un directorio
Para recuperar los nombres de los archivos desde un FTP poseemos dos funciones: ftp_nlist y 
ftp_rawlist. 
La primer alternativa es usar ftp_nlist. Esta función requiere del recurso FTP y del directorio del 
cual se quieren recuperar las entradas.
Nos devolverá una arreglo con cada una de las entradas encontradas (incluyendo el directorio . y el 
directorio ..).
Ejemplo: 

$dirActual = ftp_passwd($ftp);
$entradas = ftp_nlist($ftp, $dirActual);
foreach($entradas as $entrada) {
echo "$entrada\n";
}

La segunda alternativa será utilizando ftp_rawlist. ftp_rawlist funciona igual que 
ftp_nlist, pero nos devolverá una salida más detallada, para la cual deberemos crear una expresión 
regular para recuperar las partes de interes.
En código: 

$dirActual = ftp_passwd($ftp);
$entradas = ftp_rawlist($ftp, $dirActual);
foreach($entradas as $entrada) {
echo "$entrada\n";
}

Ejercicios
1. Hacer un programa que acepte por parametro una direccion de email de destinatario, un email 
de origen, un asunto y el nombre de un archivo de texto. Luego el programa debera enviar un 
email al destinatario con los datos suministrados. 
2. Modificar el ejercicio anterior para que levante el servidor y demas datos configurables desde 
un archivo de texto que posea la forma: 
opcion=valor

donde opcion sera uno de los aspectos configurable (como Servidor) y valor sea el valor 
correspondiente. 
3. Hacer un programa que elimine todos los emails desde un POP3 cuyos Remitentes se 
encuentren en una lista negra.
La lista negra consistira en un archivo de texto el cual contiene un email debajo de otro. 
Carrera Linux 2008 ­ Programacion PHP                                                                 50

4. Modificar el ejercicios anterior para que la lista negra este dividida en dos partes. La primer 
servira para especificar servidores prohibidos. De este modo con indicar spammer.com todo 
email que venga desde alli (jose@spammer.com, pepe@spammer.com) debera ser eliminado. 
La segunda parte servira para poner direcciones especificas (como funcionaba antes).
El formato del archivo se deja a criterio libre. 
5. Hacer un programa que descargue todo los archivos desde un ftp dado y un directorio dado del 
mismo (ambos pasados por parametros). El programa debera descargar todos los archivos del 
directorio como asi tambien los de todos los sudirectorios que puedan existir y debera quedar 
localmente una copia fiel del directorio remoto. 

Clase 9 ­ Referencias

Introducción

Hasta este momento, siempre que hemos programado, hemos estado utilizando variables. Estas variables siempre poseían un único contenido (un número, una cadena, un arreglo, etc) y ese mismo contenido 
siempre tenía un mismo nombre (el de la variable). Esto no necesariamente es siempre asi ya que PHP nos permite darle distintos nombres a un contenido a través de las referencias.
Una referencia me permitirá acceder un contenido definido anteriormente por otra variable. Lo que hará realmente es darle otro nombre al mismo contenido.
Para crear una referencia hay que utilizar el operador & de la siguiente forma: 

$var = 486;
$ref = &$var;

De esta forma hemos creado una variable normal llamada $var que tiene el valor 486. Luego hemos creado una referencia (llamda $ref) que hace referencia (valga la redundancia) al mismo 486.
Si ejecutamos: 

echo "var = $var\n";


echo "ref = $ref\n";

ambos mostrarán 486. Como la variable $ref y $var hacen referencia al mismo contenido, si modificamos una de ella, la otra se verá inevitablemente alterada.
Si por ejemplo: 

$ref = $ref + 1;

entonces: 

echo "var = $var\n";


echo "ref = $ref\n";

ambos muestran el valor 487. Esto se deba a que un mismo contenido (originalmente 486) puede tener distintos nombres al mismo tiempo. Una vez creada la referencia es indistinto si usamos $var o $ref
ya que ambos son nombres del mismo contenido. 

Referencias y Funciones

Cuando trabajamos en PHP las referencias nos serán especialmente útiles cuando trabajemos con funciones.
Para ejemplificar esto veamos la siguiente función: 

function incrementar($var) {
$var++;
echo "[incrementar] var = $var\n";
}

$contador = 1;
echo "[antes] contador = $contador\n";
incrementar($contador);
echo "[despues] contador = $contador\n";

Si corremos este programa veremos la salida: 

[antes] contador = 1
[incrementar] var = 2
[despues] contador = 1

La cual funcionaría como habría de esperarse. Sin embargo, nuestro objetivo al crear la función incrementar es que la variable que se paso por parámetro quede con el valor incrementado en 1.
Aquí es donde entran en juego las referencias. Veamos una versión modificada de la función anterior: 
Carrera Linux 2008 ­ Programacion PHP                                                                 51

function incrementar(&$var) {
$var++;
echo "[incrementar] var = $var\n";
}

Le hemos agregado un & en la declaración de la función. Esto le indica a PHP que ese parámetro se pasará por referencia. Al pasar los parámetros comunmente (como ya hemos visto) estos son pasados por 
valor. Esto quiere decir que la variable (en este caso $var) contendrá una copia de la variable pasada por parámetro (en este caso $contador). Esto no siempre es deseable. Si quiciesemos modificar dicha 
variable deberiamos utilizar una referencia. Como hemos visto al principio al utilizar una referencia, ambas variable apuntan al mismo contenido por lo que modificando una se modifica la otra.
Con esta versión modificada ahora obtendremos los resultados deseados: 

[antes] contador = 1
[incrementar] var = 2
[despues] contador = 2

Una ventaja de pasar los parámetros por referencias (ademas de poder modificarlos) es que no es necesario crear una copia de los mismo. Si lo que se intenta pasar es muy grande (digamos un arreglo con 
muchas entradas que son arreglos que a su vez tienen muchas entradas y etc), al crear una copia estaríamos desperdiciando espacio y tiempo. En cambio, al pasarlo por referencia solo hay que agregar un 
nuevo nombre para el contenido ya existente. 

Eliminando referencias y variables

PHP nos permite volver a dejar una variable que ya hemos utilizado en estado de indefinida (como si nunca la hubiesemos usado). Para ello existe la función unset. A esta función solo hay que darle

 como parámetro la variable a utilizar.
Por ejemplo: 
$x = 3;
unset($x);
echo "x = $x\n";

mostrará "x =" ya que la variable x esta vacía. Como x era el único nombre que tenia el contenido 
asociado (Que tenia valor 3), al eliminarse x se perderá ese valor (ya no hay nadie quien haga referencia 
a el). En cambio, si disponemos de una referencia, al aplicar unset solamente borraremos ese nombre 
asociado a ese contenido. Las demas referencias a ese nombre no se perderán, por lo tanto, el contenido 
seguirá existiendo.
Ejemplo: 
$x = 3;
$ref = &$x;
unset($x);
echo "x = $x\n";
echo "ref = $ref\n";

mostrará: 
x =
ref = 3

también funcionará al reves: 

$x = 3;
$ref = &$x;
unset($ref);
echo "x = $x\n";
echo "ref = $ref\n";
Carrera Linux 2008 ­ Programacion PHP                                                                 52

lo cual mostrará: 

x = 3
ref =

Ejercicios
1. ¿Que son las referencias y cuales son sus aplicaciones practicas? 
2. Se posee una variable a la cual se le crea una referencia. Si la variable es eliminada pero la 
referencia no, ¿se perderá el contenido? 
3. Una vez creada una referencia, ¿en que se diferencia la variable que tiene la referencia de la 
original? 
4. Realizar el juego ta­te­ti para dos jugadores. Para representar el tablero se deberá usar una 
matriz. 

Clase 10 ­ Manejo de objetos
Introducción a la programación orientada a objetos
Hasta el momento hemos estado programando dentro de lo que se llama el paradigma de 
programación estructurado. En este esquema, siempre partiamos desde el problema más grande y lo 
ibamos partiendo en pedazos más chicos para su resolución.
En el paradigma de objetos, la historia es un poco al reves, partiendo desde lo específico (un objeto) 
hasta lo general.
Un objeto esta compuesto por su estado (los atributos) y sus responsabilidades (los métodos). Los 
atributos son el conjunto de valores que guarda cada objeto. Los métodos son los servicios que presta 
ese objeto (por ejemplo, si se posee un objeto que representa a un Cliente, entonces se podría tener un 
método Cobrar el cual permita al sistema registrar un cobro del cliente). 
Los objetos existen dentro de un ambiente. Luego se podrán comunicar con otros objetos mediante el 
paso de mensajes (invocaciones a métodos). Un mensaje es un pedido de un objeto (emisor) a otro 
(receptor) un servicio, que este será ejecutado en el receptor por un método. 
Dentro de este paradigma también existe algo llamado Clases. Las Clases son "los moldes" de los 
objetos. O sea, para crear un objeto, debo tener una clase que lo defina. En realidad, un objeto será una 
instancia de una clase. Podríamos pensarlo como que el objeto es la clase en ejecución. 

Clases y objetos
El primer paso para crear un objeto, como hemos mencionado, es tener una clase de donde sacarlo. La 
sintaxis para crear una clase cualquiera es la siguiente: 
Carrera Linux 2008 ­ Programacion PHP                                                                 53

class NombreClase {

// Definicion de atributos

// Definicion de metodos

Para definir un atributo usaremos un de las siguientes 3 palabras reservadas: public, private, 
protected.
Antes de explicarlas veremos como se escribe: 

public $nombre;
private $apellido;
protected $edad;

Atributos
Si definimos un atributo como public, entonces este podrá ser accedido (tanto para leerlo como para 
modificarlo) desde afuera del objeto. O sea, cualquier objeto puede tener acceso a este atributo. 
Esto es, por lo general, malo. Es de muy mala práctica y trae muchos problemas que un objeto pueda 
modificar el estado de otro. Cada objeto es responsable por mantener su estado. Además, de esta forma, 
si solo el objeto mismo es quien se ocupa de manejar su estado, solo habría que cambiar en ese objeto 
en caso de necesitar hacer una modificación. 
Si definimos un atributo como private, solo puede ser accedido por el objeto mismo. Ningún otro 
objeto bajo ninguna circustancia podrá modificar dicho atributo. 
Finalmente, si lo definimos como protected, solo lo podrán acceder el objeto mismo u objetos que 
hereden de esa clase (ver Herencia).
Esto quiere decir que una subclase podrá usar los atributos definidos en la clase madre (los distintos 
objetos, instancias, de esta clase no podrán acceder a los atributos de otros objetos). 
Dentro de los métodos si queremos acceder a un atributo, entonces deberemos hacerlo escribiendo 
$this-> seguido del nombre dado al atributo ( sin el $). 

Métodos
Para definir un método utilizaremos la estructura function. Esta es idéntica que las funciones 
definidas por el usuario explicadas en clases anteriores salvo que estarán dentro de una clase. Por lo 
tanto, PHP las interpretará como métodos de dicha clase.
Los métodos también poseen una visibilidad como los atributos (public, private o protected) 
y cumplirán las mismas condiciones pero sobre el método. Si no se especifica ninguna de las 3 se toma 
por defecto que el método es public. 
Darémos un ejemplo de una clase sencilla para mostrar todo lo explicado: 
Carrera Linux 2008 ­ Programacion PHP                                                                 54

class Persona {
private $nombre;
private $apellido;
private $edad;
private $pais;

public function setNombre($nombre) {


$this->nombre = $nombre;
}

public function setApellido($apellido) {


$this->apellido = $apellido;
}

public function setEdad($edad) {


$this->edad = $edad;
}

public function setPais($pais) {


$this->pais = $pais;
}

public function getNombre() {


return $this->nombre;
}

public function getApellido() {


return $this->apellido;
}

public function getEdad() {


return $this->edad;
}

public function getPais() {


return $this->pais;
}

public function getNombreCompleto() {


return "$this->apellido, $this->nombre";
}
}

Instanciación
Una vez definida la clase, podemos crear objetos a partir de ella. Este proceso se llama instanciación. 
Para ello utilizaremos el operador new seguido del nombre de la clase y los paréntesis.
Luego, para acceder a un método, (o sea, enviarle un mensaje al mismo), escribiremos el la variable del 
objeto seguida por un ->, el nombre del método y sus parámetros.
Carrera Linux 2008 ­ Programacion PHP                                                                 55

Considerando la clase Persona, podríamos escribir: 

$persona1 = new Persona();


$persona1->setNombre("Pepe");
$persona1->setApellido("Estalag");
$persona1->setEdad(23);
$persona1->setPais("ARG");

echo "Persona: ", $persona1->getNombreCompleto(), "\n";

Herencia
El concepto de herencia significa poder definir una clase tomando como en base a otra. La primera 
será la clase hija mientras que la segunda será la clase padre. Al heredar desde una clase, la nueva clase 
poseerá automáticamente todos los atributos y métodos de la clase padre, pero podremos agregarle 
nuevos atributos y métodos (y/o modificarlos).
Las clases hijas se escriben al igual que cualquier otra clase (son clases despues de todo) con la 
excepción que hay que agregarle de que clase estan heredando. Para ello, luego del nombre de la clase 
hija, se debe agregar la palabra reserva extends seguida del nombre de la clase padre.
Veamos un ejemplo: 

class Empleado extends Persona {


private $sueldo;

public function setSueldo($sueldo) {


$this->sueldo = $sueldo;
}

public function getSueldo() {


return $this->sueldo;
}

public function getTrabajo() {


return "Empleado";
}
}

Aquí hemos definido una clase Empleado que extiende (hereda) de Persona. Esta relación también 
se le dice "es un" (Empleado es una Persona).
Si creamos un objeto de esta clase, podremos llamar tanto al método setSueldo y getSueldo, 
como a todos los métodos definidos para la clase Persona. 

Redefinición
Como habiamos mencionados anteriormente, cuando creamos una clase hija, esta hereda todo el 
comportamiento y los atributos del padre. Sin embargo, no siempre queremos que todo lo heredado 
Carrera Linux 2008 ­ Programacion PHP                                                                 56

funcione igual. Tenemos la posibilidad de redefinir los métodos que nos sean necesarios.
Expandiendo el ejemplo anterior, definiremos subclases de Empleado: Vendedor, Gerente.
El código de las clases es el siguiente: 

class Gerente extends Empleado {


public function getSueldo() {
return $this->sueldo * 5;
}

public function getTrabajo() {


return "Gerente";
}
}

class Vendedor extends Empleado {


private $ventas;
private $porcVentas;

public function venta($monto) {


$this->ventas[] = $monto;
}

public function getSueldo() {


$extra = array_sum($this->ventas) * $this->porcVentas;
return $this->sueldo + $extra;
}

public function setPorcVentas($porcVentas) {


$this->porcVentas = $porcVentas;
}

public function getTrabajo() {


return "Vendedor";
}
}

En este ejemplo vemos que al crear las nuevas clases hijas, hemos redefinido el método getSueldo y 
getTrabajo. Ahora los nuevos métodos trabajaran diferente al original, pero, visto desde afuera, no 
habrá diferencia entre pedirle el sueldo a un objeto del tipo Empleado, que al del tipo Gerente. 
Veamos todo esto en acción: 

$vendedor1 = new Vendedor();


$vendedor1->setNombre("Jose");
$vendedor1->setApellido("Gest");
$vendedor1->setEdad(25);
$vendedor1->setPais("ARG");
$vendedor1->setSueldo(500);
$vendedor1->setPorcVentas(0.1);
$vendedor1->venta(1000);
$vendedor1->venta(100);
$vendedor1->venta(700);
Carrera Linux 2008 ­ Programacion PHP                                                                 57

$vendedor2 = new Vendedor();


$vendedor2->setNombre("Pedro");
$vendedor2->setApellido("Arquimedes");
$vendedor2->setEdad(30);
$vendedor2->setPais("ARG");
$vendedor2->setSueldo(500);
$vendedor2->setPorcVentas(0.1);
$vendedor2->venta(7000);
$vendedor2->venta(400);
$vendedor2->venta(300);
$vendedor2->venta(600);

$gerente = new Gerente();


$gerente->setNombre("Armando");
$gerente->setApellido("Quilombo");
$gerente->setEdad(45);
$gerente->setPais("ARG");
$gerente->setSueldo(2000);

$empleado1 = new Empleado();


$empleado1->setNombre("Raul");
$empleado1->setApellido("Castillo");
$empleado1->setEdad(35);
$empleado1->setPais("ARG");
$empleado1->setSueldo(700);

$empleado2 = new Empleado();


$empleado2->setNombre("Paul");
$empleado2->setApellido("Blanco");
$empleado2->setEdad(28);
$empleado2->setPais("ARG");
$empleado2->setSueldo(700);

printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",


$empleado1->getNombreCompleto(),
$empleado1->getTrabajo(),
$empleado1->getSueldo());

printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",


$empleado2->getNombreCompleto(),
$empleado2->getTrabajo(),
$empleado2->getSueldo());

printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",


$vendedor1->getNombreCompleto(),
$vendedor1->getTrabajo(),
$vendedor1->getSueldo());

printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",


$vendedor2->getNombreCompleto(),
$vendedor2->getTrabajo(),
$vendedor2->getSueldo());
Carrera Linux 2008 ­ Programacion PHP                                                                 58

printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",


$gerente->getNombreCompleto(),
$gerente->getTrabajo(),
$gerente->getSueldo());

Polimorfismo
El último concepto que nos queda es el de polimorfismo. Se dice que dos objetos son polimórficos
cuando son intercambiables. Esto quiere decir que podemos poner cualquiera de los dos y el programa 
funcionará con ambos. Para ello ambos objetos deben tener, por lo menos, un método que tenga igual 
nombre e igual cantidad y tipo de argumentos. 
Para ejemplificar esto, haremos una clase Empresa: 

class Empresa {
private $personal;
private $costoFijo;

public function agregarEmpleado($empleado) {


$this->personal[] = $empleado;
}

public function setCostoFijo($costo) {


$this->costoFijo = $costo;
}

public function calcularTotalSueldos() {


$total = 0;
foreach($this->personal as $empleado) {
$total += $empleado->getSueldo();
}
return $total;
}

public function getGastosTotal() {


return $this->costoFijo + $this->calcularTotalSueldos();
}

public function listadoEmpleados() {


foreach($this->personal as $empleado) {
printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",
$empleado->getNombreCompleto(),
$empleado->getTrabajo(),
$empleado->getSueldo());
}
}
}

Aquí se puede apreciar el polimorfismo, por ejemplo, en el método calcularTotalSueldos. Allí 
Carrera Linux 2008 ­ Programacion PHP                                                                 59

cuando se recorre el arreglo se llama al método getSueldo de cada uno de los empleados. Cuando se 
ejecuta este método no se sabe que hay en el arreglo personal. Puede haber tanto objetos de tipo 
Empleado, como de tipo Gerente, como de tipo Vendedor, o una mezcla de ambos. Cualquiera 
sea el caso, se le pedirá al objeto que ejecute el método getSueldo sin saber ni como lo hace, ni de 
que tipo es el objeto, ni de donde saca la información.
También se ve lo mismo en el método listadoEmpleados el cual generá el mismo formato de 
listado que el expuesto en el ejemplo anterior.
Veamos un ejemplo del uso de esta nueva clase, considerando creados los objetos de empleados: 

$empresa = new Empresa();

$empresa->agregarEmpleado($empleado1);
$empresa->agregarEmpleado($empleado2);
$empresa->agregarEmpleado($vendedor1);
$empresa->agregarEmpleado($vendedor2);
$empresa->agregarEmpleado($gerente);
$empresa->setCostoFijo(7000);

$empresa->listadoEmpleados();

echo "Total Gastos: \$", $empresa->getGastosTotal(), "\n";

Constructores y destructores
Un constructor es un método que se ejecuta automaticamente al momento de instanciar una clase. De 
esta forma, disponemos de una herramienta para inicializar el estado de nuestro objeto a nuestra 
voluntad.
En PHP, y a partir de las versiones 5.X, el método constructor tiene por nombre __construct.
El constructor puede o no tener parámetros. Si los tiene, entonces será necesario pasarselos al momento 
de instanciar la clase. Los parámetros al constructor se escribiran entre los corchetes en el momento de 
hacer el new sobre la clase.
Por ejemplo, podríamos modificar la clase Empleado para que quede así: 

class Empleado extends Persona {


protected $sueldo;

public __construct() {
$sueldo = 0;
}

public function setSueldo($sueldo) {


$this->sueldo = $sueldo;
}

public function getSueldo() {


return $this->sueldo;
}
Carrera Linux 2008 ­ Programacion PHP                                                                 60

public function getTrabajo() {


return "Empleado";
}
}

De esta manero nos aseguraríamos que siempre se posee un valor cargado en el atributo sueldo, ya 
que si lo llegáramos a utilizar sin haberle cargado un valor (en nuestro ejemplo, sin haber llamado a 
setSueldo), nos tirará un error. 
El destructor es un método que se ejecuta cuando todas las referencias al objeto se hayan perdido. Esto 
ocurrirá cuando finalice el script o cuando forzadamente se eliminen las referencias.
El nombre del método, análogamente al constructor, deberá llamarse __destruct y no podrá recibir 
ningún parámetro. 

Ejercicios
1. Definir los 3 conceptos basicos del paradigma de objetos. 
2. Definir objeto. ¿Cual es la diferencia entre Clase y Objeto? 
3. Definir el concepto de herencia. De un ejemplo en donde seria util. 
4. Definir el concepto de redefinicion. De un ejemplo en donde seria util. 
5. Definir el concepto de polimorfismo. De un ejemplo en donde seria util. 

Clase 11 ­ Excepciones
Introducción
Las excepciones son un método para el manejo de errores. Básicamente son un canal separado para 
enviar errores. De esta forma nos permite eliminar de nuestro código los métodos más antiguos como 
devolver el error como valor de retorno de una función, una variable global, usar ifs, etc.
Para ello se utilizará una nueva estructura: try/catch. Esta estructura esta compuesta por un bloque 
de código, try, el cual podrá o no arrojar una excepción, y un bloque de código, catch, que se 
ejecutará cuando se arroje efectivamente la excepción. En caso contrario, el bloque del catch NO se 
ejecutará. 
Conceptualmente, el sistema de excepciones funciona de la siguiente manera. En algún punto donde se 
detecte una condición de error, se lanzará una excepción. En este momento, PHP dejará de ejecutar el 
script, e irá hacia atras sus pasos en la línea de llamadas hasta encontrar un bloque try/catch que 
capture la excepción. Cuando lo encuentre, reanudará la ejecución en el bloque de código del catch.
De no existir un bloque catch que atrape la excepción, PHP terminará la ejecución del script y 
mostrará un error fatal. 
Carrera Linux 2008 ­ Programacion PHP                                                                 61

Manejo básico
Para demostrar lo expuesto, haremos un pequeño ejemplo. Crearemos dos clases. La primera será 
ControladorTransferencia. Esta clase llevará un contando de cuantos bytes se han 
transmitidos y cual es el máximo admisible. Luego tendremos la clase Usuario que representará a un 
usuario logueado. Este tendrá un método descargar, para poder bajar un archivo y dentro de él se le 
pedirá al controlador de transferencia que estipule si puede o no bajar el archivo pedido. En caso de no 
poder, el controlador tirará una excepción.
Veamos el código: 

class ControladorTransferencia {
private $maximoBajada;
private $bytesTransferidos;

function __construct($maximoBajada) {
$this->maximoBajada = $maximoBajada;
$this->bytesTransferidos = 0;
}

public function transferir($bytes) {


if($this->bytesTransferidos + $bytes > $this->maximoBajada) {
throw new Exception("Excedido el limite maximo de
transferencia");
}
$this->bytesTransferidos += $bytes;
}
}

class Usuario {
private $username;
private $controladorTransferencia;

function __construct($nombre) {
$this->controladorTransferencia =
new ControladorTransferencia(100 * 1024 *
1024); // 100Mb
$this->username = $nombre;
}

public function descargar($archivo) {


$tamArchivo = filesize($archivo);
$this->controladorTransferencia->transferir($tamArchivo);
// Aqui codigo para enviar
}
}

En el método transferir de ControladorTransferencia se puede ver donde se tira la excepción. La 
estructura para tirar una excepción es throw seguida de un objeto Exception.
Aquí se puede ver que, en definitiva, a nivel código, una excepción es ni más ni menos que un objeto. 
Usamos la más básica de todas que es Exception pero luego veremos otras posibilidades. Es 
Carrera Linux 2008 ­ Programacion PHP                                                                 62

importante destacar que se debe hacer un new de la clase ya que sino estaríamos tratando de arrojar la 
clase misma ocurriendo un error de ejecución.
También podemos configurarle un mensaje de error para esa excepción en particular, suministrándole al 
constructor de la excepción una cadena arbitraria. 
Veamos estas clases en uso: 

$usuario = new Usuario("mister");

try {
$usuario->descargar("misteriuos_data.tgz");
} catch (Exception $e) {
echo "Excepcion atrapada\n";
echo "Archivo: ", $e->getFile(), "\n",
"Linea: ", $e->getLine(), "\n",
"Mensaje: ", $e->getMessage(), "\n";

echo "\nBacktrace:\n", $e->getTraceAsString();


}

Aquí aparece por primera vez el bloque try/catch. Como se ve en el bloque try hemos puesto 
todas las sentencias que puedan tirar una excepción (es este caso es una sola pero podrían ser más).
Luego viene un bloque catch, el cual tiene como "argumento" una excepción que se guarda en la 
variable $e. Esto lo hace automáticamente PHP y, a fines prácticos, nosotros solo usaremos esa varible 
dentro del bloque. La excepción nos da mucha información sobre el error. En particular, un objeto 
Exception tiene varios métodos interesantes. A saber: 
Método Descripción
getFile Nos devuelve el nombre del archivo .php desde el cual se arrojo la excepción
Nos devuelve el número de línea desde donde se arrojo la excepción (donde 
getLine
esta el throw).
Nos devuelve una cadena con el mensaje de error (el que configuramos 
getMessage
cuando creamos el objeto Exception)
Nos devuelve una cadena con todas las llamadas que se hicieron desde el nivel 
getTraceAsString más alto hasta el método que tiro la excepción. De esta forma podemos ir 
siguiendo el camino que llevo el programa y encontrar el error lógico.

Excepciones definidas por el usuario
Hasta aquí solo hemos utilizado la excepción Exception, pero PHP también nos permite crear 
nuestras propias excepciones. Esto servira para darle un significado mayor a la excepción. Al recibir 
una excepción diferente podemos saber más precisamente el error y podremos diferenciarlas de otras 
excepciones (ver el apartado siguiente Manejo de multiples excepciones).
También nos permite agregarle funcionalidades extra al objeto de excepción, agregándole también 
información extra particular para ese caso. 
Carrera Linux 2008 ­ Programacion PHP                                                                 63

Para crear una nueva excepción solamente hay que crear una clase que herede de la clase Exception. 
Esto solo basta para crear la nueva excepción. De todos modos, como mencionanmos antes, podemos 
agregarle más atributos y métodos.
En nuestro ejemplo, crearemos una excepción nueva para representar el limite excedido y guardaremos 
en ella los valores (máximo, actual y lo pedido) para luego dar más información cuando falle.
El código de la nueva clase y la modificación en la clase ControladorTransferencia para que 
emplee esta nueva excepción: 

class limiteExcedidoException extends Exception {


private $maximo;
private $actual;
private $pedido;

public function getMaximo() {


return $this->maximo;
}

public function getActual() {


return $this->actual;
}

public function getPedido() {


return $this->pedido;
}

public function setMaximo($maximo) {


$this->maximo = $maximo;
}

public function setActual($actual) {


$this->actual = $actual;
}

public function setPedido($pedido) {


$this->pedido = $pedido;
}
}

class ControladorTransferencia {
private $maximoBajada;
private $bytesTransferidos;

function __construct($maximoBajada) {
$this->maximoBajada = $maximoBajada;
$this->bytesTransferidos = 0;
}

public function transferir($bytes) {


if($this->bytesTransferidos + $bytes > $this->maximoBajada) {
$e = new limiteExcedidoException("Excedido el limite maximo de transferencia");
$e->setMaximo($this->maximoBajada);
$e->setActual($this->bytesTransferidos);
$e->setPedido($bytes);
throw $e;
}
$this->bytesTransferidos += $bytes;
}

Veamos ahora como atrapar esta nueva excepción: 

$usuario = new Usuario("mister");

try {
$usuario->descargar("users.php");
} catch (limiteExcedidoException $e) {
echo "Excepcion atrapada\n";
echo "Archivo: ", $e->getFile(), "\n",
"Linea: ", $e->getLine(), "\n",
"Mensaje: ", $e->getMessage(), "\n";

echo "Maximo admisible: ", $e->getMaximo(), "\n",


"Bytes Transferidos: ", $e->getActual(), "\n",
Carrera Linux 2008 ­ Programacion PHP                                                                 64
"Bytes pedidos: ", $e->getPedido(), "\n",
"Bytes excedentes: ",
($e->getActual() + $e->getPedido()) - $e->getMaximo(), "\n";

echo "\nBacktrace:\n", $e->getTraceAsString();

Para atrapar una excepción en particular cambiaremos el tipo Exception por el de nuestra excepción en el bloque catch. De esta forma, y para este ejemplo, la variable $e tendrá nuevos métodos que no 
poseen las excepciones comunes (getMaximo, getActual y getPedido). Por lo tanto, además de la información estándar hemos agregado información extra relacionada con los tamaños requeridos. 

Manejo de multiples excepciones

Puede ocurrir, y es muy común, que para un bloque try se puedan disparar varias excepciones diferentes. Puede ser necesario tratar de forma distinta cada excepción. Por lo tanto podemos definir tantos 
bloques catch como excepciones tengamos.
Cada bloque catch deberá definir a cada tipo de excepción. El primer bloque catch deberá tener la excepción más específica y el útlimo la más general (Exception). Si los escribimos al reves, 
Exception concordará con cualquier excepción tiremos y se utlizará ese sin revisar los demás. 
Modificaremos la clase Usuario para que arroje otra excepción: 

class Usuario {
private $username;
private $controladorTransferencia;

function __construct($nombre) {
$this->controladorTransferencia =
new ControladorTransferencia(1024); //*1024);//*100);
$this->username = $nombre;
}

public function descargar($archivo) {


if(!file_exists($archivo)) {
throw new Exception("El archivo $archivo no existe");
}
$tamArchivo = filesize($archivo);
$this->controladorTransferencia->transferir($tamArchivo);
// Aqui codigo para enviar
}

Luego agregaremos el manejo para ambas excepciones (limiteExcedidoException y Exception): 

$usuario = new Usuario("mister");

try {
$usuario->descargar("users.php");
} catch (limiteExcedidoException $e) {
echo "Excepcion atrapada\n";
echo "Archivo: ", $e->getFile(), "\n",
"Linea: ", $e->getLine(), "\n",
"Mensaje: ", $e->getMessage(), "\n";

echo "Maximo admisible: ", $e->getMaximo(), "\n",


"Bytes Transferidos: ", $e->getActual(), "\n",
"Bytes pedidos: ", $e->getPedido(), "\n",
"Bytes excedentes: ",
($e->getActual() + $e->getPedido()) - $e->getMaximo(), "\n";

echo "\nBacktrace:\n", $e->getTraceAsString();

} catch (Exception $e) {


echo "Excepcion atrapada\n";
echo "Archivo: ", $e->getFile(), "\n",
"Linea: ", $e->getLine(), "\n",
"Mensaje: ", $e->getMessage(), "\n";

echo "\nBacktrace:\n", $e->getTraceAsString();


}

Como se ve aquí primero se captura la excepcion limiteExcedidoException y luego Exception. PHP se encargará automáticamente de ejecutar el primer bloque catch que concuerde con la 
excepción tirada y nos asegurará que no se ejecuta ningún otro bloque catch. 

Ejercicios

1. ¿Que es un excepcion y para que sirve? 

2. ¿Cuantos bloques catch puede haber en una construccion try/catch? ¿porque? 
3. ¿Que información me provee una excepcion? 
4. ¿Como se extiende una excepcion? ¿Que funcion cumple? 
Carrera Linux 2008 ­ Programacion PHP                                                                 65

Clase 12 ­ Introducción a la programación web
Conceptos Generales sobre Programación Web
La programación web consiste basicamente, en generar páginas HTML dinamicamente. Esto quiere 
decir que cada vez que se quiera ver una página, esta deberá crearse en el momento y para quien la 
pida.
Cuando se accede a una página hay tres atores en escena: El cliente (un navegador), El servidor web y 
PHP (en este caso).
Los pasos son los siguientes: 
1. El cliente pide ver una página .php 
2. El servidor web reconoce que no es un HTML estático 
3. Se ejecuta el interprete de PHP y ejecuta la página .php 
4. La salida generada (todo lo que el script envíe a la salida está) por este programa se envia al 
cliente para que la visualice 
Para comunicarse entre el cliente y el servidor se utiliza el protocolo HTTP. Este protocolo sirve para 
mucho más que devolver páginas HTML pero por el momento solo usaremos esta característica.
En el paso 3 es donde ocurre la magia. Cuando se ejecuta la página se utiliza todo un lenguaje de 
programacion (PHP) para crearla. Esto implica que se usarán variables, decisiones, operaciones, ciclos, 
etc. En un programa, las variables mantienen el "estado", es decir, los valores procesados. Estos valores 
se pierden completamente cuando se termina de ejecutar la página.

Estructura básica de un HTML
Todo HTML debe tener por lo menos estos tres tags que definen la estructura básica: HTML, HEAD, 
BODY.
El tag HTML sirve para encerrar todo el archivo de html.
Sería: 

<HTML>

</HTML>

Entre medio de estos dos tags se escribirá todo el contenido de HTML que se quiera que muestre el 
archivo.
El tag HEAD sirve para determinar algunos parámetros generales del HTML que se este editando. Se 
puede setear el título de la página (el que normalmente el navegador utiliza como título de la ventana) o 
algunas reglas generales del manejo de fuentes, o metadata. Este tag sería el primero que se debe 
encontrar luego del <HTML>.
Para establecer el título se utiliza el tag TITLE.
Carrera Linux 2008 ­ Programacion PHP                                                                 66

Quedaría algo asi:

<HTML>
<HEAD>
<TITLE> El título </TITLE>
</HEAD>

</HTML>

El tag BODY es el que delimita el cuerpo del HTML. Dentro de este tag se escribirá todo lo que se 
quiera que se vea en la pantalla cuando se intente ver el archivo.
La estructura básica quedaría finalmente:

<HTML>
<HEAD>
<TITLE> El título </TITLE>
</HEAD>
<BODY>
Hola Mundo
</BODY>
</HTML>

En este ejemplo, se mostraría por pantalla el texto "Hola Mundo". 
NOTA: Los ejemplos de HTML que apareceran de aquí en adelante, son fragmentos de lenguaje que se 
escribe dentro del tag BODY a no ser que se indique lo contrario.
Primero que nada veamos que pasaría si escribimos esto:
Hola a todos,
queria informarles que esto sale mal

La salida sería:
Hola a todos, queria informarles que esto sale mal

Lo cual no es lo que se esperaba. Esto se debe a que cuando se interpreta el HTML, a no ser que se 
encuentre un tag, los caracteres que se encuentran se muestran directamente y se ignoran todos los 
espacios. Para poder lograr que se baje de línea hay que poner un tag que lo haga. Dicho tag es el tag 
BR. Este tag no tiene fin, simplemente cuando se lo encuentra el navegador bajará de linea. Sería:
Holas a todos,<BR>
queria informarles que esto casi sale bien

La salida sería ahora:
Holas a todos,
queria informarles que esto casi sale bien
Carrera Linux 2008 ­ Programacion PHP                                                                 67

Si bien mejor que antes no lo suficientemente bien. Para poner espacios se puede alinearlo todo usando 
tablas o poner los espacios. Para poner espacios se debe como escapar el espacio, lo cual se logra 
escribiendo &nbsp; 
También pueden especificarse párrafos. La ventaja de esto es que dentro de un párrafo se puede 
configurar la justificación del texto (izquierda: left, centrado: center, derecha: right). El tag que 
hace esto es el tag P. La opción para la justificación es align. Cuando se escribe un tag P, el navegador 
comenzará el párrafo comenzando inmediatamente desde la línea próxima. Si no se especifica el fin del 
tag (el </P>) se cerrará automaticamente cuando se termine el archivo. 
Veamos un ejemplo:
Entonces el dijo:<P ALIGN=CENTER>"No olvidar.<BR>Lo que ves ya se ha visto ya."

La salida será:
Entonces el dijo:

"No olvidar.
Lo que ves ya se ha visto ya."

El tag P dejo una línea en blanco y comenzo el nuevo párrafo. Si bien el HTML escrito es correcto, y a 
pesar de que los "ENTER" se ignoren a la hora de mostrarlos por pantalla, es buena costumbre bajar 
una línea luego de escribir un <P> o un <BR>. 

Dandole estilo al texto
Es posible darle estilos al texto. Que pasaría si en el ejemplo anterior, quicieramos que la parte entre 
comillas aparezca en itálicas (cursiva). Para ello existen el tag I. Quedaría algo así: 

Entonces el dijo:
<P ALIGN=CENTER>
"<I>No olvidar.<BR>

Lo que ves ya se ha visto ya.</I>"

Ahora el navegador lo mostrar en letra cursiva (también queda más claro el haberlo organizado 
diferente, ¿no?). 
En el siguiente cuadro se listan todos los tags similares que dan otros efectos:

TAG EFECTO

<B>...</B> Negrita

<I>...</I> Itálica (Cursiva)
Carrera Linux 2008 ­ Programacion PHP                                                                 68

<U>...</U> Subrayado

<SUB>...</SUB> Subindice

<SUP>...</SUP> Supraindice
También existe un tag para setear un texto como título. Para ello esta el tag H seguido de un número 
entre 1 y 6. Esto le dará el tamaño al título siendo el 1 el más grande y el 6 el más pequeño. Este tag 
también tiene la opción ALIGN para setear la justificación.
Por ejemplo: 

<H1 ALIGN=CENTER>Profecias</H1>

Pondrá un título bien grande y centrado que dira "Profecias" en nuestro HTML. 

Creando Links
Un link es una enlace entre dos páginas. De esta forma cuando el usuario aprete sobre el link, se lo 
llevará automaticamente a ese documento. La idea básica es que un link vincule o enlace información 
relacionada de forma tal que quien navege la página pueda ir descubriendo toda la información que 
busca.
Para crear un link se utiliza el tag A. Este tag tiene la opcion HREF la cual me permite especificar a que 
documento hace referencia. Por ejemplo:

Grandes obras:
<A HREF=la_biblia_segun_vox_dei.html>La Biblia segun Vox Dei</A>
<A HREF=the_lamb.html>The Lamb Lies Down On Brodway, Genesis</A>

Aquí se crearan dos links. El primero llevará al archivo la_biblia_segun_vox_dei.html. Sin embargo el 
usuario vera en la pantalla lo que se encuentre dentro del tag A, en este caso, La Biblia segun Vox Dei. 
Lo mismo ocurrirá con el segundo link.
El tag A tiene otras cuantas opciones. Veremos, sin embargo, una sola más, la opcion TARGET. Esta 
opción nos permite especificar a donde queremos que se habra el link. Puede llevar el nombre de un 
frame para que lo abra allí, o podra llevar un nombre que no este usado en ningún lado y abrirá al link 
en una nueva ventana, como un pop­up. Por lo general se le da el nombre _web para este tipo de target. 
Por ejemplo:

<A HREF=propaganda.html TARGET=_web>Gane mucho dinero</A>

En este ejemplo, cuando se aprete sobre el link (creyendo ganar mucho dinero) aparecerá un pop­up con 
propaganda.
Carrera Linux 2008 ­ Programacion PHP                                                                 69

Tablas
Las tablas son una de las herramientas más útiles del HTML y se usaran hasta el cansancio. Una tabla 
es simplemente un area del html que esta dividida en celdas, y en donde cada celda puede contener 
cualquier cosa de HTML.
Las tablas las utilizaremos para organizar visualmente el HTML como también para crear cuadros. 
Estas consisten en filas y columnas (aunque no necesariamente coincidan en cantidad).
El tag para crear tablas se llama TABLE. Este tag tiene varias opciones, entre ellas encontramos: 
ALIGN: Determina la alineación de toda la tabla en el HTML (al igual que con el tag P) 
BORDER: Determina el ancho del borde que tendrán las celdas. Si es 0 no tendra ningún border. Por 
defecto el valor es 1. 
WIDTH: Determina el ancho de la tabla. Se puede especificar en pixeles (poniendole un valor) o en 
porcentaje (poniendo un % luego del valor). Por ejemplo WIDTH=100 le dara un tamaño de 100
pixeles mientras que WIDTH=100% usará todo el ancho de la ventana. 
BGCOLOR: Determina el color de fondo que tendra la tabla. Los colores se escriben como una 
combinación de Rojo, Verde y Azul (RGB). Cada color puede variar entre 0 y 255 (o en hexadecimal 
entre 0 y FF). Se debe escribir un numeral (#) y luego los tres valores de los colores (en hexadecimal). 
Por ejemplo, para obtener el color azul sería #0000FF 
Para crear una fila se utilza el tag TR. Este tag tiene una opción ALIGN para alinear el texto dentro de 
esa fila, y una opción BGCOLOR para darle un color de fondo a la fila unicamente. Dentro de este tag se 
deberá especificar cada celda que habra en esa fila. 
Para crear una celda se utiliza el tag TD (también tiene las opciones ALIGN y BGCOLOR que se 
comportan igual que las de TR pero a nivel celda). Veamos un ejemplo completo de una tabla: 

<TABLE BORDER=1>
<TR>
<TD>Celda 1</TD>
<TD>Celda 2</TD>
</TR>
<TR>
<TD>Celda 3</TD>
<TD>Celda 4</TD>
</TR>
<TR>
<TD>Celda 5</TD>
<TR>
</TABLE>

La salida será: 

Celda 1 Celda 2
Celda 3 Celda 4
Celda 5
Carrera Linux 2008 ­ Programacion PHP                                                                 70

Como vemos no hemos especificado la última columna por lo cual quedará vacía. Como cantidad de 
columnas se tomará la fila que tenga más celda y aquellas filas que no lleguen a esa cantidad quedarán 
vacías.
Es posible juntar las ultimas dos celdas para que quede prolijo, para ello en la última celda deberiamos 
indicarle que debe utilizar dos columnas de ancho. Para ello esta la opción COLSPAN. Si le damos el 
valor dos se tomará las dos columnas. Quedaría así: 

<TABLE BORDER=1>
<TR>
<TD>Celda 1</TD>
<TD>Celda 2</TD>
</TR>
<TR>
<TD>Celda 3</TD>
<TD>Celda 4</TD>
</TR>
<TR>
<TD COLSPAN=2>Celda 5</TD>
<TR>
</TABLE>

Y ahora la salida sería correcta:
Celda 1 Celda 2
Celda 3 Celda 4
Celda 5

También puede hacerse esto a nivel filas (juntar dos filas en una columna) si utilizamos la opción 
ROWSPAN en vez de COLSPAN. 

Ejercicios
1. ¿Que es un pagina web dinamica? ¿A donde debe enviarse la salida de la misma y que funcion 
conocida de PHP utilizaria para ello? 
2. ¿En que se basa los archivos HTML? ¿Como esta conformado un tag? 
3. ¿De que sirve poder crear tablas en HTML? ¿Como se determina la cantidad de filas y 
columnas de una tabla? 
4. ¿Que hacen los navegadores con un conjunto consecutivo de caracteres blancos (espacios, 
ENTER, tabulaciones, etc)? ¿Que utilidad le encuentra a dicho hecho? 
5. Se necesita crear una serie de scripts que informen sobre algunos aspectos del estado actual del 
sistema.
Estos scripts debe generar: 
a. Un html que se basara en informacion que encuentre en el archivo /etc/lilo.conf. De 
dicho archivo debera extraer el campo message y todos los campos label. Luego debera 
mostrar el campo message y luego en una tabla centrada todos los labels que encontro. 
b. Un html que se basara en la informacion que encuentre en el archivo /etc/inittab. Este 
Carrera Linux 2008 ­ Programacion PHP                                                                 71

HTML debe mostrar una tabla con dos entradas (dos columnas) en donde la primera sera 
la accion y la segunda el comando. Desde el archivo /etc/inittab se debe extrar el campo 
accion y comando de todos aquellos que pertenezcan a los runlevels 3, 4 o 5. 
NOTA: Cada entrada del archivo inittab tiene el formato: 
id:runlevel1,runlevel2,...,runlevelN:accion:comando

Para mas informacion ver el manual inittab(5) 
c. Aqui se deberan genera un HTML (usuarios.html) con un listado de todos los usuarios. 
Cada usuario sera un link a otra pagina (llamada usuario_nombre.html, por ejemplo, 
para root sera usuario_root.html) que tendra la informacion del usuario. Toda la 
informacion de los usuarios se encuentra en /etc/passwd y la de los grupos en /etc/group) 
En particular cada pagina del usuario tendra la siguiente forma:
Primero en titulo 1 y centrado (h1) estara el nombre del usuario. Luego vendra una tabla 
que tendra en la primer fila, dos columnas: una que dira el UID y otra el GID. En la 
segunda fila dira el directorio personal y el shell. En la tercer fila debera informa la 
informacion extra que haya (este fila debe ocupar dos columnas).
Luego se debera mostrar otra tabla que liste todos los grupos a los cual pertenece dicho 
usuario. Cada entrada de este grupo sera un link a la informacion del grupo (ver mas 
adelante). 
d. Tambien se debe generar un archivo, grupos.html, el cual contendra un listado de todos 
los grupos existentes (segun el archivo /etc/group). Cada entrada sera un link a la 
informacion del grupo (similar a los usuarios). De cada grupo se debe poner un titulo 
centrado H1 con el nombre del grupo y luego una tabla de una sola columna que liste, en 
cada fila, a todos los usuarios de ese grupo. Cada usuario sera un link a la informacion 
del mismo. 

Es necesario crear tambien un html, menu.html, para acceder a cada uno de estos cuatro 
puntos. Tambien, cada html debe tener un link, abajo a la derecha, que diga "Volver" el 
cual me permitira volver a la pagina anterior (al menu.html, salvo cuando se trata de la 
informacion de un usuario o grupo, en donde llevar al listado correspondiente). 

NOTA: Por simplicidad se sugiere hacer dos scripts separados para el punto a y b, y uno 
solo para el punto c y d. 
Carrera Linux 2008 ­ Programacion PHP                                                                 72

Clase 13 ­ HiperText Markup Language(HTML) 
Parte 2
Listas
En HTML una lista es simplemente la enumeración o denotación de varios elementos. Estos elementos 
serán en definitiva, texto. Las listas servirán entonces para darle formato a la salida.
Una lista puede ser ordenada o desordenada. Aquellas que son ordenadas llevarán algún tipo de 
numeración, las otras llevarán simplemente alguna viñeta. 

Listas desordenadas
Las listas desordenadas quedan definidas por el tag <ul> ... </ul> (Unordered List). Dentro de 
este tag se especificarán todos los elementos de la lista. Cada elemento de la lista se definirá en el tag 
<li>...</li>.
Ejemplo: 

<ul>
<li><A HREF=http://www.atptennis.com>Tenis</A></li>
<li><A HREF=http://www.freeprogrammingresources.com>Free Books</A></li>

<li><A HREF=http://www.clarin.com.ar>Las noticias</A></li>


</ul>

De esta forma el HTML exibirá algo así: 
•  Tenis  
•  Free Books  
•  Las noticias  
Lo que es posible configurar de las listas desordenadas es que dibujo utilizar como viñeta. Entre los 
posibles estan un circulo, un cuadrado o un disco (por defecto). Para ello habrá que agregarle la opción 
TYPE al tag UL. Los valores de esa opción son CIRCLE, SQUARE y DISC respectivamente. El fin del 
tag LI (</LI>) puede ser, y normalmente lo es, omitido ya que es claro para el navegador que en 
donde encuentre otro tag <LI> significa que comienza otro elemento. 

Lista Ordenadas
Las listas ordenadas se diferencia de las anteriores en que cada elemento de la lista posee una posición 
(numérica o alfabética) , o sea, identificarían como una secuencia de pasos. El tag que se utiliza para 
estas listas es el tag <ol>...</ol> y para los elementos el tag <li> (mismo caso que con las listas 
desordenadas). El tag ol también posee un parámetro TYPE que permite determinar el tipo de 
numeración. Entre los posibles existen: 
Carrera Linux 2008 ­ Programacion PHP                                                                 73

Valor Numeración Ejemplo

A Alfabética Mayúscula A,B,C,D...

a Alfabética Minúscula a,b,c,d...

1 (defecto) Números Arábigos 1,2,3,4...

I Números Romanos Mayúscula I,II,III,IV...

i Números Romanos Minúsculas i,ii,iii,iv...

Frames
Hasta el momento todas las páginas que generamos ocupaban toda la ventana. Si se desea dividir la 
venta en partes de forma que podamos cargar varias páginas distintas dentro de la misma ventana, será 
necesario utilizar frames. Un frame es simplemente un "porción" de una ventana. Para utilizar frames 
es necesario crear un HTML que contenga solamente la definición de los frames y luego otro html por 
cada frame que se utilice.
Para crear un frame se utiliza el tag <FRAMESET>...</FRAMESET>. Es tag REEMPLAZA al tag 
BODY, por lo tanto, el tag BODY no estará presente. Un FRAMESET me permite dividir la ventana en 
filas o en columnas. Si luego se quiere dividir más la página se pueden anidar FRAMESETs. Este tag 
llevará un parámetro COLS(columnas) o un ROWS(filas), pero no ambos. Cada uno de ellos dividirá a la 
ventana en filas o en columnas. Las divisiones se pueden especificar en pixeles (ej. ROWS=100,300) 
o en porcentajes (ej. ROWS=40%,60%). Al igual que con las tablas se puede utilizar un asterisco (*) 
para aquellos valores que no deseemos especificar y que quedarán librados al tamaño disponible (ej. 
COLS=50,*). 
El tag FRAME es el que se utiliza para especificar que páginas cargar en cada frameset. Este tag tiene 
tres opciones básicas:
• SRC: especifica que página se va a cargar 
• NAME: es el nombre que tendrá el frame. Esto es utilizado por los links que quieran desplegar 
el contenido de una página en un frame distinto al que se encuentran. 
• SCROLLING: puede ser YES (siempre existirán las barras de desplazamiento), NO (nunca 
existirán las barras de desplazamiento, aun si el contenido no entra en la ventana), o nada 
(aparecerán las barras solo si son necesarias). 
Veamos como sería el HTML principal de una página de noticias que este dividida en tres columnas, en 
donde la primera tendrá un conjunto de opciones del sitio (ocupará el 15% de la ventana), la columna 
de la derecha tendrá los encabezados de noticias de otros sitios (ocupará un 15% de la ventana), y la 
columna central tendrá las noticias del sitio (ocupará lo que quede de la ventana).
El HTML sería:

<HTML>
<HEAD>
Carrera Linux 2008 ­ Programacion PHP                                                                 74

<TITLE>Muchos Frames</TITLE>
</HEAD>
<FRAMESET COLS=15%,*,15%>
<FRAME SRC=opciones.html SCROLLING=NO>

<FRAME SRC=cgi-bin/noticias.pl SCROLLING=NO NAME=Central>


<FRAME SRC=cgi-bin/noticias_ajenas.pl SCROLLING=NO NAME=Otros>
</FRAMESET>
</HTML>

Formularios
El HTML no solamente proporciona utilidades para darle formato a la salida sino que nos provee de 
algunos elementos para poder interactuar de forma más avanzada con el usuario. Estos componentes 
son la base para poder crear CGIs. Los formularios nos permitirán poner botones, cajas de texto, etc, en 
nuestras páginas para que el usuario pueda proveer información más completa y poder hacer verdaderas 
páginas dinámicas.
Si bien esto es parte de la programación de CGIs (discutida en la próxima clase) diremos que todo lo 
que se encuentre en un formulario y tenga asignado un nombre, podrá ser recuperado por el programa 
que lo reciba. Cada formulario tendrá también, un programa asociado para procesarlo. Dentro de una 
misma página se pueden tener varios formularios (aunque no se pueden anidar) y los componentes que 
esten en un formulario no se verán en los demás.
Un formulario queda definido por los tags <FORM> y </FORM>. El tag FORM no tiene una 
representación gráfica, sino que simplemente agrupa a todos los componentes que luego agreguemos 
en el.
Entre las opciones que tiene FORM podemos encontrar: 
• ACTION: aquí se especifica a que programa (scripts) se debe llamar cuando se sube el 
formulario (por ejemplo, ACTION=http://www.misitio.com/cgi-
bin/vender.pl) 
• METHOD: Determina con que método se subiran los datos del formulario. El método puede 
ser GET o POST.
Si el método es GET los valores viajarán a través de la URL (será visible al usuario) y tiene la 
desventaja de que el tamaño de la URL es limitado y pueden llegar a perderse parte de los datos 
si estos son muy grandes.
Si es POST los valores se pasaron por otra conexión al servidor. La ventaja del POST es que no 
se esta limitado con el tamaño, y la desventaja es que se "más lento" (se hace otra conexión). 
• NAME: Nombre que tiene el formulario. 
Ejemplo: 

<FORM ACTION=cgi-bin/procesar.pl METHOD=POST>

</FORM>
Carrera Linux 2008 ­ Programacion PHP                                                                 75

El tag INPUT
El tag INPUT es el utilizado para ingresar datos. Este tag permite crear cajas de texto, cajas de 
contraseña, botones, checkbox, opciones, botones de imágenes y campos escondidos.
Todas estas posibilidades tiene algo en común: todas tienen un nombre que las identifica y tienen un 
valor asociado. Estas opciones serán NAME y VALUE respectivamente.
El tag INPUT tendrá también una opción, TYPE, que determinará de cual de todos los componentes 
queremos usar. 
Si TYPE=TEXT entonces se creará una caja de texto. Si la opción VALUE esta especificada, dicho valor 
será el que contenga la caja por defecto. El tipo TEXT tiene dos opciones más: SIZE que determina el 
ancho de la caja de texto (cuantos caracteres se verán) y MAXLENGTH que determina cuantos caracteres 
admitirá como máximo. 
Si TYPE=PASSWORD sera similar a TEXT pero cuando se escribe dentro de esa caja de texto los 
caracteres aparecerán como asteriscos (*). 
Si TYPE=SUBMIT entonces se creará un botón que permite subir el formulario para ser procesado. El 
valor que tenga la opción VALUE será el texto que aparecerá dibujado sobre el botón. 
Si TYPE=IMAGE entonces se creará un botón que funciona igual que SUBMIT pero con la diferencia 
que este será una imágen. Para ello, se posee una opción extra, SRC, que determinará desde donde se 
obtendrá (la URL) la imágen que se desea mostrar. 
Si TYPE=HIDDEN entonces se creará un campo escondido. Este tipo de campo es especialmente útil 
para programar CGIs, en particular para pasar valores entre distintos formularios. 
Si TYPE=CHECKBOX entonces se crearán las clásicas casillas para seleccionar. En este caso el valor 
que tenga la opción VALUE será la que se muestre al lado del rectángulo de selección. Si se desea que 
por defecto la opción aparezca marcada se debe agregar la opción CHECKED. 
Si TYPE=RADIO entonces se crearán la selección de opciones unitaria. Es decir, el navegador agrupará 
a todos aquellos componentes de tipo RADIO que tenga el mismo nombre, y solo permitirá que se elija 
uno y solo uno de ellos. Al igual que con los CHECKBOX el valor que tenga la opción VALUE será el 
texto que se muestre al lado del circulo de selección. Si se desea que por defecto la opción aparezca 
marcada se debe agregar la opción CHECKED. 

El tag TEXTAREA
Este tag permite crear cuadros de texto bidimensionales. A diferencia de los INPUT TYPE=TEXT los 
TEXTAREA permiten ingresar varias líneas de texto. Cada línea estará delimitada por un \r\n (para 
cuando se procesa el formulario). Este tag tiene, por supuesto, la opción NAME para ser identificado 
luego desde el CGI. También posee la opciones COLS que determina la cantidad de columnas que 
ocupará el cuadro, y ROWS que determina la cantidad de filas que ocupará el cuadro (visualmente).
Este tag, y también a diferencia del tag INPUT, tiene un tag que lo cierra (</TEXTAREA>
obviamente). Todo lo que se encuentre dentro de estos dos tags se tomará como valor por defecto. Se 
debe aclarar que solo se permite texto plano dentro de estos dos tags, ya que lo que se escriba como 
Carrera Linux 2008 ­ Programacion PHP                                                                 76

HTML será ignorado y pasado directamente al cuadro de texto. 

El tag SELECT
Este tag se utiliza para crear tanto listas como combobox (listas desplegables). SELECT creará un 
cuadro con todas las opciones que se le otorguen y permitirá elegir una o más de ellas. Las opciones se 
determinan mediante el tag <OPTION>...</OPTION>. Lo que se encuentre dentro de estos tags 
será lo que vera el usuario por pantalla (y por defecto el valor que se obtendrá cuando se sube el 
formulario). Si se desea dar otro valor a cada opción se puede utilizar la opción VALUE dentro del tag 
OPTION y asignarle el valor que se desee.
También existe la opción SELECTED para que por defecto, esa opción aparezca seleccionada.
El tag SELECT también tiene algunas opciones. Primero tiene la opción NAME al igual que todos los 
demás componentes. Posee tambien la opción MULTIPLE la cual le dice al navegador se debe o no 
permitir que se elijan más de una opción. También posee la opción SIZE que determina la cantidad de 
elementos que se veran al mismo tiempo en pantalla. Si la cantidad de elementos es mayor que la 
especificada en SIZE, entonces aparecerá una barra de desplazamiento para poder moverse y elegir 
cualquier elemento.
Si no se especifico la opción MULTIPLE y SIZE=1 entonces la lista se convierte en una lista 
desplegable. 

Ejercicios
1. ¿Cual es la diferencia entre los metodos GET y POST? 
2. ¿Que formas de entrada tiene el usuario mediante el tag INPUT? 
3. ¿Cual es la diferencia entre el tag OL y UL? 
4. ¿Para que sirven los frames? 
5. ¿Como armaria una pagina que este dividida en 5 partes, de modo que queden 3 paginas en la 
primer fila y 2 en la segunda? 

Clase 14 ­ Programación web
Un programa en PHP, dentro de una página web, se puede pensar como un conjunto de secciones de 
código PHP introducidas dentro de un archivo HTML.
Entonces, definiremos un bloque de PHP, como lo hemos hecho al inicio, de la siguiente forma: 

<?php
# Codigo en PHP
?>

En donde <?php abre el bloque de código y ?> cierra dicho bloque. Todo lo que se encuentre dentro 
de este bloque de código se ejecutará como código PHP y la salida (o sea, todo lo que se escriba en la 
salida estándar) resultante irá al navegador. Para que nuestro programa genere HTML se utilizará la 
función echo.
Carrera Linux 2008 ­ Programacion PHP                                                                 77

Por ejemplo, si creamos el archivo hola.php: 

<HTML>
<HEAD>
<TITLE>Saludos!</TITLE>
</HEAD>
<BODY>
<?php
echo "Hola Mundo";
?>
</BODY>
</HTML>

Generaremos una página web en PHP que escribe Hola Mundo. 
Veamos un ejemplo un poco más complejo: 

<HTML>
<HEAD>
<TITLE>Ejemplo</TITLE>
</HEAD>
<BODY>
<?php

echo "La suma de antes era: $x";


while($x < 10) {
$x = $x + 1;
$s = $s + $x;
echo "$x dot<br>";
}
echo "La suma es: $s<br>";

?>
</BODY>
</HTML>

Cuando ejecutemos esta página, por primera vez, las variables $x y $s no existirán. Cuando empieza el 
ciclo while ambas variables se irán incrementando hasta llegar a $x=9 y $s=55. Esta información se 
verá en el navegador: 
La suma de antes era:
1 dot
2 dot
3 dot
4 dot
5 dot
6 dot
7 dot
8 dot
9 dot
10 dot
La suma es: 55
Carrera Linux 2008 ­ Programacion PHP                                                                 78

Como se podra apreciar, el primer echo no muestra ningún valor para $s, que es lo que intuitivamente 
uno supondría ya que es la primera vez que se ejecuta. Sin embargo, cuando volvemos a ejecutar la 
página, volverá a producir la misma salida. Esto se debe al hecho que no se comparten estados 
(variables) entre dos ejecuciones distintas. Cuando se ejecuta por segunda vez, todas las variables que 
se utilizaron antes, no existen hasta que se hayan utilizado. 
Esto no quiere decir que es imposible comunicarse entre dos páginas ya que esto es posible utilizando 
HTML (links y formularios) o mediante el protocolo HTTP (cookies). 

Paso de información entre páginas
Como hemos dicho anteriormente dos ejecuciones de una misma página no comparten sus variables. 
Sin embargo, si es posible pasar información entre dos páginas cualquiera (o la misma para el caso que 
sea). Cuando se trabaja sobre la Web existen dos métodos: GET (links) y POST (formularios).
Cuando se utilizan links es posible pasar información mediante la URL que llevan. Un link común 
sería:

<A HREF=index.html>Volver a la pagina principal</A>

Este link, simplemente apunta al index.html. Ahora, supongamos que poseemos un link que nos lleva a 
los proximos 200 resultados (a partir del resultado 400) de una búsqueda:

<A HREF=busqueda.php?desde=400&cantidad=200&criterio=crucis>Pagina siguiente</A>

En esta oportunidad era necesario pasarle a nuestro CGI cierta información para que funcionase como 
uno esperaría. Cuando se ejecute no será igual el resultado si se empieza a mostrar desde el resultado 
100 que desde el resultado 5000. El script procesará la búsqueda de igual forma en ambos casos pero 
mostrará cosas distintas.
Para pasar datos por la URL es necesario separar el archivo de los parámetros usando el signo ?. Luego 
cada uno de los parametros tendrá un nombre (fijo para poder encontrarlo despues) y un valor asociado 
(que es lo que personaliza la ejecución). Los distintos parámetros se separan luego por ampersands (&).
Desde PHP para obtener estos valores existe el arreglo $_GET. En este arreglo, las claves son los 
nombres de los parametros. $_GET es una variable como las demas que se utilizan en PHP. Esto quiere 
decir, que cuando se termino la ejecución del CGI, todo su contenido también se pierde junto con todas 
las variables. Este arreglo lo cargará PHP automáticamente con la ejecución de cada CGI. Si en una 
ejecución dada no se paso ningún parámetro por la URL, entonces $_GET estará completamente vacío. 
Si se paso una opción, entonces $_GET tendrá una única entrada.
Veamos esquematicamente como sería el ejemplo anterior:

<?php
# Si hay algo para buscar
if(isset($_GET["criterio"])) {

# Si no se especifico desde que resultado (probablemente la


# primera ejecucion), comenzamos desde 0
Carrera Linux 2008 ­ Programacion PHP                                                                 79

if(!isset($_GET["desde"])) {
$desde = 0;
} else {
$desde = $_GET["desde"];
}

# Si no se especifico de a cuantos mostrar, usamos un valor por defecto


if(!isset($_GET["cantidad"])) {
$cantidad = 200;
} else {
$cantidad = $_GET["cantidad"];
}

# Esta funcion seria la que ejecutase la consulta y la mostrara en


# pantalla. Para este ejemplo no es relevamente como lo hace, sino
# que lo haga
mostrar_resultados($_GET["criterio"], $desde, $cantidad);

# Crea el link a la proxima pagina


echo "<A HREF=busqueda.php?desde=", $desde + $cantidad,
"&cantidad=", $cantidad, "&criterio=", $_GETS["criterio"],
">Pagina Siguiente</A>";
}
?>

Se puede observar que el link de la próxima página irá aumentando su campo desde a medida que se 
van pasando las páginas, ya que siempre se le pasa el valor que tenia ($desde) más un incremento 
($cantidad). Los otros dos campos permanencen fijos (cantidad y criterio). 

Formularios
Cuando se necesita que el usuario interactue de manera más contundente (lease, tipee algo 
basicamente) debemos recurrir a los formularios.
Un formulario, como lo visto en la guia de HTML, es un conjunto de controles que permiten al usuario 
ingresar datos, seleccionar desde un combo, elegir un checkbox, etc. Sin embargo los formularios 
tienen otra propiedad: pueden ser enviados. Esto quiere decir que toda la información ingresada podrá 
ser utilizada luego (De ser enviada) por un CGI.
La forma en que se pasan los datos es similar a la de los links. En el caso de los formularios cada uno 
de los componentes tendrá un nombre (Fijo) que tendrá un valor asociado (lo que ingreso el usuario). 
Luego todo este conjunto de claves,valores estarán disponibles desde el arreglo $_POST.
La forma de utilizar $_POST es totalmente igual a la de usar $_GET. La diferencia reside en el origen 
de los datos (unos vienen por la URL, generados por nuestro programa y los segundos son lo que 
ingreso el usuario).
Veamos un ejemplo de un programa que nos dice si un número ingresado es o no es par:

<HTML>
<HEAD>
<TITLE>Par o no par, esa es la cuestion</TITLE>
Carrera Linux 2008 ­ Programacion PHP                                                                 80

</HEAD>
<BODY>
<FORM METHOD=POST>
Numero:<INPUT TYPE=TEXT NAME=nro VALUE=<?php echo $_POST[nro]; ?>
SIZE=5>
<INPUT TYPE=SUBMIT VALUE=Controlar>
<P>
<?php
# No se ingreso nada
if(!isset($_POST["nro"])) {
echo "No se ha ingresado ningun valor todavia";

# Si es par el modulo al dividirlo por 2 da 0


} elseif($_POST["nro"] % 2 == 0) {
echo "<H1>El numero es PAR!</H1>";

# Si se ingreso y no es par, entonces sera impar


} else {
echo "<H1>El numero es IMPAR!</H1>";
}
?>
</BODY>
</HTML>

Recordemos que al igual que $_GET, $_POST será eliminado cuando se termine de ejecutar el 
programa y será cargado nuevamente cuando se vuelva a correr el programa. Esta claro que $_POST
será cargado solamente con los valores ingresados en el momento en que se envio el formulario.
El programa es bastante lineal, y su única función es informar sobre los tres posibles estados: No se 
ingreso nada, o es la primera vez que se ejecuta ($_POST["nro"] no contiene ningún valor); Se 
ingreso un numero que es par (entonces $_POST["nro"] contiene un número par); o se ingreso un 
número impar (entonces $_POST["nro"] contiene un número impar).

Diferencias entre el método GET y el método POST
Si bien ambos métodos se utilizan básicamente igual poseen algunas diferencias entre ellos.
Una de ellas ya la mencionames, y es el origen desde donde vienen los datos. En el método GET 
vendran junto con la URL, en cambio, en el metodo POST viene por otra conexión.
Antes de continuar aclararemos que las diferencias técnicas mencionadas aquí no afectan a la forma de 
programar, sino que se deben utilizar para entender el proceso y saber cuando conviene enviar datos por 
GET y cuando por POST. 
Los datos del GET, al ir a traves de la URL, viajan al servidor Web junto con el pedido de la página. El 
servidor interpretará la URL, la dividirá y se la enviará a nuestro programa. En cambio, cunado los 
datos son enviados usando el metodo POST, se generan dos conexiones. La primera sera la común en la 
que se pide la página necesaria. A esta, le sigue otra conexión por la cual se enviarán los datos del 
POST. Luego, el servidor se encargará de juntar los datos del POST para enviárselos a nuestro 
programa.
El método POST nos permitirá pasar una mayor tamaño de datos. El método GET, al estar limitado por 
la URL, no aceptará aproximadamente más de 512bytes. En cambio el tamaño de un POST es del orden 
Carrera Linux 2008 ­ Programacion PHP                                                                 81

de los megas. 

Ejercicios
1. ¿Como es el ciclo para interactuar con un usuario mediante formularios? ¿Como se recuperan 
desde una pagina web los valores ingresados por el ususario? 
2. Hacer una pagina que liste todos los usuarios del sistema (usando de base el archivo 
/etc/passwd). Cada usuario debe ser un link a otra pagina, la cual debera mostrar toda la 
informacion disponible del mismo (usando de base el mismo archivo).
Ambos listados deberan estar dentro de tablas HTML. 
3. Hacer una pagina que permita al usuario ingresar un numero. Luego la pagina ira indicando si el 
numero es menor, mayor o igual a uno elegido al azar. Dicho numero al azar debera ser el 
mismo durante todo el juego (se debera ir pasando entre las diferentes paginas en un tag INPUT 
del tipo HIDDEN). 
4. Modificar el programa anterior para que el juego se reinicie solo cuando el usuario halla 
adivinado el numero. Tambien se debe agregar un boton para reiniciar el juego manualmente.
Agregar tambien un contador para que indique en cuantos intentos se adivino el numero. 
5. Se requiere crear un Message Board (libro de visitas) para un sitio web. Un message board (de 
aqui en adelante MB) consiste simplemente en permitir al usuario dejar mensajes en el sitio y 
que todos puedan ver estos mensajes (los mensajes no tienen relacion entre ellos).
Por restriccion del sitio no todos los usuarios pueden escribir en el MB. Solo aquellos que esten 
registrados lo podran hacer.
Se debera crea una serie de scripts para agregar usuarios (y ver su informacion), ingresar 
mensajes, y ver los mensajes ingresados. Para registrar a un usuario se le debe pedir cierta 
informacion:
* nickname: alias con el que se vera al usuario
* nombre y apellido: reales del usuario
* email: direccion de correo electronico
* contraseña: su contraseña

Una vez dado de alta al usuario este podra ingresar mensajes. Cuando se ingresa un mensaje se 
debe permitir ingresar el usuario, la contraseña y el mensaje propiamente dicho.
Los usuario seran listados dentro de una lista desplegable (o sea SELECT no multiple con 
SIZE=1), y la contraseña en una caja de contraseñas (PASSWORD). El mensaje, por tener un 
tamaño considerablemente largo, debe ser ingresado mediante un TEXTAREA. Tambien sera 
registrada la fecha y hora en que se realizo la transaccion.
El usuario solo podra agregar el mensaje si la contraseña ingresada es correcta. 

Los mensajes se listaran uno debajo del otro con el siguiente formato: 
Fecha y hora
Nick_del_usuario (email) escribio:
Mensaje
Carrera Linux 2008 ­ Programacion PHP                                                                 82

Donde "Fecha y hora" es la fecha y hora en que se genero el mensaje, "Nick_del_usuario" es un 
link a al informacion del usuario, "email" es un link al email (o sea, un 
mailto:usuario@serv.com) y "Mensaje" es el mensaje ingresado por el usuario. Cabe destacar 
que el Mensaje debe estar separado por lineas de la misma forma en que la ingreso el usuario.
Como el sitio sera muy visitado se pide que se muestren de a 5 mensajes por vez ordenados del 
mas reciente al mas antiguo. Se debe proveer entonces, en la parte inferior de la pagina, links 
para ir hacia atras y hacia adelante. 

Clase 15 ­ Cookies y Manejo de Sesiones
Las cookies son una forma de pasar información entre el servidor y el cliente de forma tal que no se 
pierda entre distintos pedidos de páginas. Esto se utiliza ya que cada vez que el cliente pide una página 
se crea una conexión nueva independiente de las páginas que ya ha pedido, por lo que nos permite ir 
pasando información entre formularios. Las cookies tienen la ventaja que se envian una sola vez y esta 
se sigue reenviando a todas las páginas que se visiten posteriormente sin necesidad de agregar código 
extra (a no ser que se desee modificar el valor de la misma).
Las cookies deben ser enviadas junto con la cabecera HTTP de respuesta que genera el servidor cuando 
un cliente pide una página. Por eso las cookies deben ser enviadas antes de que haya cualquier tipo de 
salida en HTML (antes del tag <HTML> y antes de que haya un solo espacio en blanco).
Para enviar una cookie disponemos de la funcion setcookie: 

setcookie($nombre, $valor, $expira, $path, $dominio, $seguro);

Las únicas opciones que son obligatorias son $nombre y $valor. $nombre debe ser único ya que 
no pueden existir dos cookies con el mismo nombre. 
La opción $expira determina el tiempo que durará (en segundos) la cookie. Luego de que pase ese 
tiempo se deberá generar una nueva cookie. Para darle un tiempo útilizaremos la función time() que 
nos devuelve la cantidad de segundos a la fecha de hoy y a eso le sumaremos el tiempo que deseemos 
que dure. Por ejemplo, time() + 3600 hará que la cookie expire dentro de una hora. 
La opción $dominio especifica un dominio al cual unicamente le será válido al navegador devolver la 
cookie. Si se especifico el dominio www.misitio.com solo será enviada la cookie si la página pedida 
pertenece a ese dominio (sino todos los sitios podrian ver información confidencial). 
La opción $path es similar a domain. Solo enviará la cookie si la página pedida pertenece a ese 
directorio (o subdirectorio). 
Finalmente si la opción $seguro esta activada solo se enviará la cookie si el servidor y el cliente 
soportan el uso de encriptación (SSL ­ Secure Socket Layer). 
Para recuperar el valor de una cookie existe un arreglo llamado _COOKIE. Este arreglo posee una 
entrada para cada cookie que se halla enviado, en donde la clave será el nombre de la cookie y el valor 
será el valor que tenga la cookie. 
El siguiente ejemplo consta de 4 archivos: 
Carrera Linux 2008 ­ Programacion PHP                                                                 83

Archivo: menues.php 

<?php
$menues = array("Configurar" => "configurar.php", "Principal" => "principal.php",
"No Principal" => "no_principal.php");

function mostrar_menu($menu_actual, $menues) {


echo "< P ALIGN=center>";
foreach($menues as $nombre => $link) {
echo $separador;
$separador = " - ";
if($menu_actual == $nombre) {
echo "<B>$nombre</B>";
} else {
echo "<A HREF=$link>$nombre</A>";
}
}
echo "</P>";
echo "<hr>"; # Genera una linea divisora
}

function crear_lista($nombre, $opciones, $defecto) {


echo "<SELECT NAME=$nombre SIZE=1>";
foreach($opciones as $texto => $valor) {
$seleccionado = "";
if($defecto == $valor) {
$seleccionado = "SELECTED";
}
echo "<OPTION VALUE=$valor $seleccionado>$texto</OPTION>";
}
echo "</SELECT>";
}
?>

Archivo: configurar.php 

<?php
require_once("menues.php");
$colores = array("Roj izo" => "#FF9999", "Verd oso" => "#99FF99", "Azul ado" =>
"#9999FF");

if(isset($_COOKIE["color"])) {
$color_elegido = $_COOKIE["color"];
}

if(isset($_POST["actualizar"])) {
setcookie("color", $_POST["color"]);
$color_elegido = $_POST["color"];
}
?>
Carrera Linux 2008 ­ Programacion PHP                                                                 84

<HTML>
<HEAD>
<TITLE>Configuracion de color</TITLE>
</HEAD>
<BODY BGCOLOR=<?php echo $color_elegido;?>>
<?php
mostrar_menu("Configurar", $menues);
?>
<FORM METHOD=POST>
Eliga un color:
<?php
crear_lista("color", $colores, $color_elegido);
?>
<br>
<INPUT TYPE=SUBMIT NAME=actualizar VALUE=Actualizar>
</FORM>
</BODY>
</HTML>

Archivo: principal.php 

<?php
require_once("menues.php");
$colores = array("Roj izo" => "#FF9999", "Verd oso" => "#99FF99", "Azul ado" =>
"#9999FF");

if(isset($_COOKIE["color"])) {
$color_elegido = $_COOKIE["color"];
}

if(isset($_POST["actualizar"])) {
setcookie("color", $_POST["color"]);
$color_elegido = $_POST["color"];
}
?>
<HTML>
<HEAD>
<TITLE>Configuracion de color</TITLE>
</HEAD>
<BODY BGCOLOR=<?php echo $color_elegido;?>>
<?php
mostrar_menu("Configurar", $menues);
?>
<FORM METHOD=POST>
Eliga un color:
<?php
crear_lista("color", $colores, $color_elegido);
?>
<br>
<INPUT TYPE=SUBMIT NAME=actualizar VALUE=Actualizar>
</FORM>
</BODY>
Carrera Linux 2008 ­ Programacion PHP                                                                 85

</HTML>

Archivo: no_principal.php 

<?php
require_once("menues.php");
$color_elegido = $_COOKIE["color"];
?>
<HTML>
<HEAD>
<TITLE>Pagina Principal</TITLE>
</HEAD>
<BODY BGCOLOR=<?php echo $color_elegido;?>>
<?php
mostrar_menu("Principal", $menues);
?>
<H1 align=center>¡ESTA ES LA PAGINA PRINCIPAL!</H1>
La moraleja del dia es:<br><br>
<i>El problema no es que los programas tenga errores,
sino que los errores tenga programas.
</i>
</BODY>
</HTML>

La idea de este ejemplo es mostrar que las cookies se siguen enviando solas sin necesidad de agregar 
nada. Para ello disponemos de 3 páginas: configurar.php, principal.php y no_principal.php.
En la primera de ellas configuraremos que color de fondo queremos ver. Luego si pasamos a cualquiera 
de las otras dos veremos que estan del color que seteamos sin necesidad de agregar nada.
Primero que nada haremos una aclaración global. El archivo menues.php tiene definido un arreglo con 
todos los menues que existan y una función la cual muestra el menu actual. De esta forma es sencillo 
agregar más opciones al menu, ya que solo hara falta agregar una entrada en dicho arreglo y bastará 
para que se refleje en todas las páginas. La función mostrar_menu queda como ejercicio 
interpretarla y entenderla. 
La función crear_lista genera los tag de HTML necesarios para crear un combo con todas las 
opciones que se le pasen a travez del arreglo $opciones. 
El archivo configurar.php es el que almacena toda la magia de este sistema. La idea general es tener una 
cookie que se llame color y que tenga como valor el color que se quiere mostrar (en el formato que usa 
HTML). Si la cookie no esta seteada quedará el tag BGCOLOR de BODY vacío, que por lo general, los 
navegadores lo interpretan como blanco. 
Para comenzar saltearemos los primeros dos ifs y analizaremos el HTML generado.
El tag BODY posee la opción BGCOLOR (para darle el color de fondo) seteada con el valor de una 
variable (color_elegido) que será la que contenga el color. Luego se ejecutará la función 
mostrar_menu para mostrar el menu del sistema con la opción actual seleccionada (Configurar). 
Luego se crea un formulario y un tag SELECT (con la función crear_lista) para poder elegir entre 
todos los colores que hay definidos. 
Ahora analizemos el segundo if. Este se ejecutará cuando se presione sobre el botón actualizar. Su 
Carrera Linux 2008 ­ Programacion PHP                                                                 86

tarea será la de crear la cookie si no existe y modificarla si existe. Simplemente hace falta llamar a la 
función setcookie para hacer esto. El primer parámetro es el nombre de la cookie (color en nuestro 
ejemplo) y el segundo el valor (el que fue seleccionado en el SELECT). Esta función se encargará de 
crear la cookie si no existe o de modificarla si ya existe. Por lo tanto, cuando se envie esta página, le ira 
al navegador la respuesta junto con una cookie que se reenviará en las proximas paginas que pida. 
Como acabamos de seleccionar un color, le cambiamos el valor a la variable color_elegido al que 
se acaba de elegir para que en esta misma ejecución ( que no recibio ninguna cookie) se vea el color 
elegido. 
El segundo if es para setear el color cuando se accede a la página y ya se esta enviando la cookie. Si 
ya habiamos seteado el color y navegamos por las demás páginas, cuando volvamos aquí será necesario 
(al igual que en las demás páginas) setear el color basandose en la cookie existente. Por eso, si la cookie 
existe se usa ese color. 
Las otras dos páginas son similares. Simplemente toman el valor de la cookie y lo mandan a la opción 
BGCOLOR directamente. Si la cookie no llega a existir simplemente quedará vacío el color y el 
navegador mostrará el fondo en blanco. El resto de la página es HTML puro para completar con algo 
interesante en el ejemplo. 
Veamos otro ejemplo. Este ejemplo sirve para contar cuantas veces se presionó el boton de refresh en 
una página. 
Archivo: cuenta_refresh.php 

<?php
if(isset($_COOKIE["cont"])) {
$contador = $_COOKIE["cont"] + 1;
} else {
$contador = 0;
}
setcookie("cont", $contador);
?>
<HTML>
<HEAD>
<TITLE>Cuenta refresh</TITLE>
</HEAD>
<BODY>
<h1>Contador de refreshs</h1>
Se apretaron <b><?php echo $contador; ?></b> veces el boton de refresh<br>
Presione el boton de refresh para incrementar el contador
</BODY>
</HTML>

La magia de este ejemplo reside en el if. Este if determina si existe o no la cookie llamada cont. Si no 
existe (recién se carga la página) inicializa el contador en 0 y genera una cookie con valor 0. Si llega a 
existir le suma 1 al valor anterior y crear (o modifica mejor dicho) una cookie con igual nombre pero 
con un valor 1 más grande. 
Cada vez que se recargue la página la cookie se enviará y se incrementará hasta el infinito o hasta que 
alguien se aburra de apretar refresh. 
Carrera Linux 2008 ­ Programacion PHP                                                                 87

Sesiones
Al utilizar cookies toda la información que nos interesa viaja constantemente entre el cliente y el 
servidor. Con cada acceso de página toda la información tiene que viajar dos veces. Esto, además de 
poco eficiente, hace que sea más probable que alguien modifique esa información intencionalmente, 
alterando el normal funcionamiento del sitio. 
Para ello existen las sesiones. Una sesión es una conjunto de variables que permanencen en el servidor 
y solo viaja del cliente al servidor (y viceversa) un identificador de la misma. De esta forma, es posible 
tener para cada cliente la información pertinente (distinta para cada usuario) en forma local y solo viaja 
el mínimo de información necesaria. Utilizando sesiones resulta más sencillo identificar que usuario 
esta accediendo a cada pagina ya que cada usuario tendra su propia sesión. 

Inicio de una sesión
Para crear o utilizar una sesión en PHP utilizaremos la función session_start. Esta función no 
lleva ningún parámetro y su tarea es crear una nueva sesión o utilizar una que ya exista. Hay que 
destacar que las sesiones deben inicializarse, al igual que con las cookies, antes de que halla cualquier 
tipo de salida HTML.
Cuando tenemos una sesión podemos crear variables de sesiones. Estas variables no se perderán cuando 
se termine el script, sino que quedarán almacenadas en el servidor para la próxima vez que se corra el 
script con esa misma sesion (para el mismo usuario).
Para inicializar la sesión solo hay que ejecutar: 

session_start();

Cuando se genera la sesión se le crea un identificador único, el cual puede ser obtenido mediante la 
función session_id. 

Variables de sesión
Luego tenemos dos formas de crear variables de sesiones. La primera es utilizando la función 
session_register. Esta lleva como parámetro el nombre de la variable PHP que se guardará. Por 
ejemplo:

session_register('persona');
$persona = "Mr Blue Sky";

Aquí la variable $persona (no importa cuando se llama a session_register, puede ser antes o 
despues de usar la variable) estará disponible en la sesión. También es posible guardar arreglos de igual 
forma:

session_register('personas');
$persona = array("Mr Blue Sky", "Mister IO", "Vespuscio");
Carrera Linux 2008 ­ Programacion PHP                                                                 88

La segunda forma de guardar variables de sesión es utilizando el arreglo _SESSION. Este es un 
arreglo que crea automaticamente PHP (al igual que _POST y _GET) el cual contiene todas las 
variables de sesión creadas en el momento de la ejecución. Si lo modificamos, los cambios se verán 
reflejados en la próxima ejecución. Esta forma es la recomendada ya que es la más clara y la más 
segura. Para hacer el mismo ejemplo de antes:

$_SESSION['persona'] = "Mr Blue Sky";


$_SESSION['personas'] = array("Mr Blue Sky", "Mister IO", "Vespuscio");

Las variables de sesión se podran acceder, entonces, desde el mismo arreglo _SESSION. Si en otro 
script queremos mostrar todas las personas que tenemos cargadas hasta el momento solo hara falta:

foreach($_SESSION['personas'] as $nombre) {
echo "$nombre<br>";
}

ya que $_SESSION['personas'] es un arreglo válido que ya fue cargado. 

Destrucción de la sesión
Para terminar con la sesión debemos llamar a la función session_destroy (no lleva argumentos). 
Esta función debe ser llamada luego de llamar a session_start, asi PHP puede identificar que 
sesión destruir.
Esta función no elimina la cookie de la sesión que viaja entre el cliente y el servidor, por lo que habra 
que agregar un mecanismo extra para determinar cuando se termino la sesión. 

Controlando las variables de sesión
Cuando utilizamos sesiones es útil saber si esta o no cargada una variable en la sesión. Para ello (y una 
vez abierta la sesión con session_start) dispondremos de la función session_is_register
la cual dándole el nombre de la variable nos dira verdadero o falso si esta o no esa variable registrada.
Por ejemplo: 

if(session_is_register('persona')) {
echo "La persona esta presente<br>";
} else {
echo "La persona no ta<br>";
}

Si antes de ejecutar este código, habíamos ejecutado el ejemplo anterior, el if será verdadero sino será 
falso. 

Verificando la sesión
Como no es posible eliminar la cookie que utiliza la sesión, siempre la sesión estará presente. Para 
saber si un usuario esta o no "logueado" en la sesión, debemos guardar por lo menos una variable fija 
Carrera Linux 2008 ­ Programacion PHP                                                                 89

que mientras este, la sesión será válida. Cuando el usuario se salga del sistema (mediate 
session_destroy o por que se le acabo el tiempo) esta variable sí se perdera y nuestro script podrá 
notarlo.
Para ello, por ejemplo, guardaremos en la sesión una variable que le daremos el nombre ID_SESION 
(puede ser cualquiera) y le daremos el id de la sesión actual.
Cuando el usuario inicia la sesión ejecutaremos (luego de session_start): 

$_SESSION['ID_SESSION'] = session_id();

session_register("ID_SESSION");
$ID_SESSION = session_id();

ya que es lo mismo.
Luego en cada script al cual solo los usuarios válidos puedan acceder, habrá que controlar por lo menos 
que esta variable exista: 

session_start();
if(!session_is_register("ID_SESSION")) {
echo "ERROR!!! PELIGRO!!! DANGER!!! CORRAN POR SUS VIDAS!!!";
exit(); # No ejecuta mas nada
}

Si paso por este if, entonces es seguro mostrar la página.
Veamos un ejemplo: 
Archivo: control_acceso.php 

<?php
session_start();
if(!session_is_registered("ID_SESION")) {
include('error.html'); # Trae la pagina con el mensaje de error
exit(); # Termina la ejecucion del script
} else {
echo "<h1 align=center>Acceso Permitido</h1>";
}
?>
Archivo: login.php 

<?php
require_once("funciones.php");
session_start();
mostrar_menu("LOGIN", $menues);

echo "<BODY BGCOLOR=#FFFFAA>";


if(session_is_registered("ID_SESION")) {
Carrera Linux 2008 ­ Programacion PHP                                                                 90

echo "<h1>Acceso Permitido (Cuantas veces te quieres loguear hoy?)</h1>";


} else {
$_SESSION["ID_SESION"] = session_id();
echo "<h1>Has creado una nueva sesion!</h1>";
}
echo "<h2>ID_SESION: ", $_SESSION["ID_SESION"], "</h2>";
echo "</BODY>";
echo "</HTML>";

# Para mostrar en la proxima pagina de donde viene guardamos el


# nombre de esta pagina en la sesion.
$_SESSION["pagina_anterior"] = "LOGIN";

?>
Archivo: pagina1.php 

<?php
require_once("control_acceso.php");
require_once("funciones.php");
mostrar_menu("Pagina 1", $menues);
echo "<h2>ID_SESION: ", $_SESSION["ID_SESION"], "</h2>";

# Gracias a que guardamos el valor en pagina_anterior sabemos


# desde donde viene el usuario
echo "<h3>Vienes de la pagina <FONT SIZE=+2>$_SESSION[pagina_anterior]</FONT></
h3>";

# Para mostrar en la proxima pagina de donde viene guardamos el


# nombre de esta pagina en la sesion.
$_SESSION["pagina_anterior"] = "Pagina 1";
?>
<BODY BGCOLOR=#66DD44>
<u>Oido al pasar</u>:<br><br>
Todos los rios desembocan en el mar, pero el mar nunca desborda.
<i>-- Proverbio chino</i>
</BODY>
</HTML>
Archivo: pagina2.php 

<?php
require_once("control_acceso.php");
require_once("funciones.php");
mostrar_menu("Pagina 2", $menues);
echo "<h2>ID_SESION: ", $_SESSION["ID_SESION"], "</h2>";

# Gracias a que guardamos el valor en pagina_anterior sabemos


# desde donde viene el usuario
echo "<h3>Vienes de la pagina <FONT SIZE=+2>$_SESSION[pagina_anterior]</FONT></
h3>";

# Para mostrar en la proxima pagina de donde viene guardamos el


Carrera Linux 2008 ­ Programacion PHP                                                                 91

# nombre de esta pagina en la sesion.


$_SESSION["pagina_anterior"] = "Pagina 1";
?>
<BODY BGCOLOR=#7777DD>
<u>Oido al pasar</u>:<br><br>
La verdad siempre resplandece al final, cuando ya se ha ido todo el mundo.
<i>-- Julio Cerón</i>
</BODY>
</HTML>
Archivo: logout.php 

<?php
require_once("control_acceso.php");
require_once("funciones.php");
mostrar_menu("LOGOUT", $menues);
session_destroy();
?>
<BODY BGCOLOR=#666677>
<H1 ALIGN=CENTER>Venias de la pagina <?php echo $_SESSION[pagina_anterior]; ?>
y ahora... Estas afuera...</H1>
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<P ALIGN=RIGHT><FONT SIZE=-2>adios . . .</FONT></P>
</BODY>
</HTML>
Archivo: funciones.php 

<?php
$menues = array("LOGIN" => "login.php", "Pagina 1" => "pagina1.php", "Pagina 2"
=> "pagina2.php", "LOGOUT" => "logout.php");

function mostrar_menu($menu_actual, $menues) {


echo "<P ALIGN=center>";
foreach($menues as $nombre => $link) {
echo $separador;
$separador = " - ";
if($menu_actual == $nombre) {
echo "<B>$nombre</B>";
} else {
echo "<A HREF=$link>$nombre</A>";
}
}
echo "</P>";
echo "<hr>"; # Genera una linea divisora
}
?>
Archivo: error.html 

<HTML>
<HEAD>
<TITLE>Acceso denegado</TITLE>
Carrera Linux 2008 ­ Programacion PHP                                                                 92

</HEAD>
<BODY BGCOLOR=#FF9988>
<H1 ALIGN=CENTER>¡ACCESO DENEGADO!</H1>
Usted esta tratando de acceder a un area restriginda a la cual (ovbiamente)
usted no tiene acceso.<br>
Presione <A HREF=login.php>aqui</A> para ir a la pagina principal o vayase a
otro sitio distinto que sea mas divertido que este.
<br>
Ah, ¡y muchas gracias por visitar nuestro sitio web!
</BODY>
</HTML>
Este ejemplo consta de 4 páginas principales: login.php, pagina1.php, pagina2.php y logout.php.
El inicio del sistema debe ser utilizando el script login.php. Este script crea una nueva sesión y si no 
existía asigna el nuevo id a la variables de sesión ID_SESION (usada para controlar los accesos). Si ya 
existía esa variable simplemente emite un mensaje.
Este proceso da de alta la sesión (en un sistema que tiene muchos usuarios antes de hacer este paso se 
deberia verificar que el usuario y exista y la contraseña sea correcta). Luego se puede viajar a las demas 
páginas.
Las páginas pagina1.php y pagina2.php son casi idénticas (salvo por la sabiduría del mensaje que 
muestra) por lo que discutiremos una sola de ellas.
La magia esta en que todas las páginas que tenga que ser restrigindas incluyan el archivo 
control_acceso.php. Este archivo revisa si existe la variable ID_SESION, si no existe, es porque el 
usuario se ha deslogueado o a tratado de acceder a una página sin haber pasado por la de login.
En cualquier caso, la variable de sesion ID_SESION no estará definida y le traerá el archivo error.html 
(con un hermoso mensaje de error) y terminará la ejecución del script (con la función exit) para que no 
se ejecute más nada. Si la variable existía, mostrará un mensaje demostrativo (Este mensaje no suele 
estar en sistemas reales). 
Finalmente el script logout.php destruir todas las variables de sesión por lo que el usuario estará "fuera 
del sistema". Para ello simplemente utiliza la función session_destroy.
Una vez ejecutada esta página será imposible acceder a pagina1.php o pagina2.php o al mismo 
logout.php (intentarlo para ver el mensaje de error). 

Desconectando a los usuarios
Si bien le es posible a los usuarios desconectarse utilizando el logout (que debería dar siempre mi 
sistema), sería bueno poder desconectar a los usuarios si al cabo de un tiempo el usuario no hizo nada 
(o sea no accedio a ninguna página). 
Esto se limita dandole un tiempo máximo a la cookie de ID de sesión para que no se acepte más luego 
de ese tiempo.
Una forma es configurándolo en el archivo de configuración de PHP (php.ini). Allí hay que buscar la 
entrada session.cookie_lifetime y ponerle el valor (en segundos) al cual queremos que se 
desconecte el usuario por inactividad. Por defecto tiene valor 0 que es ilimitado.
La segunda opción es setearlo manualmente para cada acceso. Es posible, entonces, modificar 
manualmente la duración de la cookie. Para ello existe la función set_cookie_params a la cual 
Carrera Linux 2008 ­ Programacion PHP                                                                 93

podemos pasarle cuanto deseamos que dure la cookie a partir del momento en que se devuelve la 
página. Esto habría que setearlo en el archivo control_acceso.php (o el análogo que usen) para que cada 
vez que se accede a una página se renueve el tiempo.
Sería: 

session_start();
session_set_cookie_params(900); # 900 segundos = 15 minutos

Si en 15 minutos el usuario no accede a nada, la cookie se eliminará del servidor. Por lo tanto, cuando 
quiera volver a acceder, la verificación en control_acceso.php fallará y estará fuera del sistema. 

Ejercicios
1. ¿Como funciona una cookie? ¿Como puedo recuperarlas desde mis scripts? 
2. ¿De que sirve una sesion? ¿Como se pueden utilizar desde PHP? 
3. Modificar el programa 3/4 de los ejercicios de la clase 14, para que los valores del numero al 
azar, cantidad de aciertos, cantidad de fallos y cantidad de pasos se pasen a traves de cookies 
4. Modificar el programa anterior para que los datos se guarden en una sesion en lugar de enviarse 
por cookies 
5. Se pide crear un carrito de compras sencillo.
Como base de datos de articulos utilizaremos un diccionario llamado articulos el cual sera 
similar al siguiente: 
my $articulos = array("Tornillo" => 0.1, "Tuerca" => 5.76, "Sillas" =>
39.25);

y un articulo con la cantidad de stock que hay de cada uno: 
my $stock = array("Tornillo" => 1000, "Tuerca" => 200, "Sillas" => 50);

luego se debe generar una pagina que liste todos los articulos existentes y le permita al usuario 
agregar a su carrito cuantos desee. 

Finalmente, debe existir un link a una pagina que le haga un listado de todo lo pedido con total 
incluido. 
Carrera Linux 2008 ­ Programacion PHP                                                                 94

Clase 16 ­ Introducción a las bases de datos 
relacionales y al Lenguaje de Definición de 
Datos
MySQL es un motor de base de datos. La pregunta es ahora, ¿que es un motor de base de datos? Bien, 
un motor de base de datos es un servidor el cual presta servicios para acceder y manipular datos. Esto 
se hace utilizando el lenguaje SQL (Structured Query Language ­ Lenguaje Estructurado de Consulta).
Dentro del motor los datos se almacenarán en tablas que a su vez estas se encuentran dentro de una base 
de datos. Para aclarar un poco, diremos que dentro de un mismo motor pueden existir varias base de 
datos distintas funcionando simultaneamente. Una base de datos agrupará datos del mismo proyecto 
(aunque esto es totalmente arbitrario). En una base de datos se almacenarán tablas (también conocidas 
como relaciones). En las tablas es en donde efectivamente se almacenará la información. Una tabla 
consiste en uno o más atributos, donde un atributo es un tipo de valor que si quiere guardar. Por 
ejemplo, si tenemos una tabla que guarda la información de un cliente, esta tendrá como atributos el 
nombre, el código, la dirección, el teléfono, etc. Dentro de la tabla se podrá ir, luego, insertando 
entradas con estos datos. A estas entradas se las conoce como filas, tuplas o registros. En definitiva una 
tabla será como una matriz donde las columnas representan los atributos y las filas las tuplas.
Dentro de una tabla exisitrá uno o más campos que sirven para identificar a una fila de forma unívoca. 
Estos campos se los conoce como claves alternativas. Podrán existir varias claves alternativas distintas y 
se eligirá una como clave primaria. La clave primaria es una clave alternativa que se usará cuando se 
quiera hacer referencia a una entrada específica de la tabla.
La idea de tener toda la información en un solo motor es para evitar la redundancia. De esta forma si 
cambia, por ejemplo, el nombre de un cliente, entonces solo hará falta cambiarlo en la tabla de clientes 
y automaticamente se vera reflejado en cualquier parte del programa que obtenga el nombre del cliente. 
Esto se logra ya que la información de, en este caso el cliente, se encuentra en un único lugar. Cuando 
se necesite buscar o hacer referencia a ese cliente se lo hará por la clave primaria logrando así el 
cometido. Existiran otras tablas que necesitarán registrar al cliente (por ejemplo en una venta). Estas 
tablas tendrán solamente como uno de sus campos a la clave primaria del cliente (digamos su código). 
De esta forma, cualquier cambio que hagamos en la tabla de clientes no afectará a las demás que 
pueden funcionar independientemente de este hecho. En la tabla de ventas, el atributo del código del 
cliente será una clave foránea o externa (o sea, que hace referencia a otra tabla). Se le puede obligar al 
motor de base de datos que compruebe en el momento de insertar una fila, en la tabla ventas, exista en 
la tabla clientes al cliente que se esta tratando de ingresar. Esto es útil para asegurar que no entre basura 
en la información. 
Existen tres sublenguajes dentro de lo que hoy en día es SQL: 
a. Data Definition Lenguage (DDL) (Lenguaje de Definición de Datos): Básicamente esto 
incluirá las sentencias CREATE, DROP, ALTER 
b. Data Manipulation (Management) Language (DML) (Lenguaje de Manipulación 
(Administración) de Datos): Básicamente esto incluirá las sentencias SELECT, INSERT, 
DELETE, UPDATE 
Carrera Linux 2008 ­ Programacion PHP                                                                 95

c. Security Management Language (SML) (Lenguaje de Administración de Seguridad): 
Básicamente esto incluirá las sentencias GRANT, REVOKE 

Introducción al servidor MySQL
Para instalar el servidor MySQL primero se deberá descargar el paquete desde su sitio web 
(www.mysql.org). La instalación es sencilla, bajando el paquete que contiene los binarios 
(recomendado).
En principio se debe desempaquetar el tgz en el directorio /usr/local/mysql. Ese será el directorio raíz 
de nuestro servidor.
Luego hay que darle los siguientes comandos desde el shell: 
cd /ur/local/mysql
scripts/mysql_install_db
chown -R root .
chown -R mysql data
chown -R mysql .

Una vez hecho esto ya estará listo para ser minimamente ejecutado.
Luego para iniciarlo dentro del directorio support­files se encuentra el script mysql.server (este puede 
ser usado para ponerle en el rc.d y se ejecute automaticamente). Entonces ejecutaremos:
support-files/mysql.server start

y si todo marcho bien el servidor se estará ejecutando.
Para conectarnos con el servidor utilizaremos el comando mysql. Desde el shell simplemente 
ejecutaremos:
mysql

y nos habremos conectados contra el servidor utilizando el usuario actual. Una vez hecho este paso se 
podran ingresar todos los comandos que se describiran a partir de ahora. 
El manejo de usuarios se verá en clases posteriores, por lo tanto, será necesario conectarse como root al 
servidor ya que es el único usuario que existe en el motor al momento de instalarlo (¡y hasta no tiene 
contraseña!). 

El Lenguaje de Definición de Datos (DDL)
NOTA: De aquí en adelante en la sintaxis de los comandos lo que se encuentre encerrado entre 
corchetes se interpretará como que es de caracter opcional. Los corchetes no forman parte de la 
sintaxis de la sentencia en sí, solo sirve para expresar la opcionalidad de lo que encierran.
Cuando se encuentre un símbolo de tubería (|) se interpretará como un opción. Se podrá utilizar lo que 
se encuentra a la izquierda del mismo o la derecha pero no ambas opciones.
Carrera Linux 2008 ­ Programacion PHP                                                                 96

CREATE
El primer comando del DDL es el CREATE. CREATE nos permitirá crear base de datos y tablas. Para 
crear una base de datos escribiremos: 

CREATE DATABASE nombre_de_la_bd;

Esto creará la nueva base de datos. Luego sera necesario elegirla para poder crear las tablas dentro de 
ella. Para eso utilizaremos el comando USE: 

USE nombre_de_la_bd;

Lo complejo aquí es crear las tablas ya que en ellas reside toda la inteligencia. Para ello utilizaremos 
CREATE de la siguiente forma: 

CREATE TABLE nombre_tabla (definicion_create,...) opciones;

La definicion_create serán todas los atributos que tendra la tabla además de que allí se podran 
definir, por ejemplo, la clave primaria.
La sintaxis de definicion_create es: 

nombre_columna tipo [NOT NULL | NULL] [DEFAULT valor] [AUTO_INCREMENT] [PRIMARY


KEY]
| PRIMARY KEY (col1, col2, ...)
| UNIQUE (col1, col2, ...)

La primera de las opciones sirve para agregar un campo en la tabla. nombre_columna será el 
nombre que tendrá el campo y tipo será el conjunto de valores que aceptará ese atributo (ver cuadro 
más adelante). La opción NOT NULL o NULL sirve para especificar si ese campo puede o no tomar el 
valor NULL. El valor NULL significa que no se tiene información sobre ese campo y es distinto a 
cualquier otro valor que pueda llegar a contener ese campo.
La opción DEFAULT sirve para que en el caso de que un campo quede librado al motor para ser 
llenado, el motor utilizará el valor que nosotros le especifiquemos.
La opción AUTO_INCREMENT se utiliza para que ese campo vaya auto incrementandose 
automaticamente a medida que se agregan valores.
Finalmente si se especifica la opción PRIMARY KEY, ese atributo quedara elegido como clave 
primaria.
La segunda alternativa se utiliza para especificar cual o cuales atributos serán la clave primaria. Si la 
clave primaria esta compuesta por más de un atributo debera ser especificada de esta forma y no 
dándole la opción PRIMARY KEY a cada atributo.
Finalmente la opción UNIQUE sirve para especificar que columnas serán claves alternativas, es decir, 
que columnas tendran valores que no podran repetirse en ninguna otra fila.
Entre los tipos de datos que hay para una columna podemos encontrar: 
Carrera Linux 2008 ­ Programacion PHP                                                                 97

Tipo  Tamaño (bytes) 

TINYINT  1 

SMALLINT  2 

MEDIUMINT  3 

INTEGER  4 

BIGINT  8 

FLOAT  4 u 8 

DATE  3 

DATETIME  8 

TIMESTAMP  4 

TIME  3 

CHAR(M)  M bytes donde 1 <= M <= 255 

L+1 bytes donde L<=M y 1<=M<=255
VARCHAR(M) 
L es la cantidad de caracteres usados 

TINYBLOB/TINYTEXT  L+1 L<2^8 

BLOB/TEXT  L+2 L<2^16 

MEDIUMBLOB/MEDIUMTEXT  L+3 L<2^24 

LONGBLOB/LONGTEXT  L+4 L<2^32 

ENUM(valor1,valor2,...)  1 o 2 
Finalmente el campo opciones en la definición de la tabla es: 

[ COMMENT = "Comentario" ]
[ TYPE = {BDB|HEAP|ISAM|MyISAM|InnoDB|Merge} ]

La primer opción sirve para darle una descripción a la tabla para explicar su contenido. La segunda 
opción sirve para especificar el tipo de tabla que se utilizará. Por defecto se utiliza el tipo MyISAM que 
es el propio de MySQL. El otro tipo interesante es InnoDB que da soporte para hacer transacciones. 
Carrera Linux 2008 ­ Programacion PHP                                                                 98

DROP
La sentencia DROP se utilizará para destruir una tabla o una base de datos. Cuando se ejecuta DROP
sobre una tabla se perderá todo su contenido y además la estructura de la tabla. Si se baja una base de 
datos se perderán todas las tablas con todos su contenido. Para borrar una tabla ejecutaremos: 

DROP TABLE nombre_de_la_tabla;

y para bajar una base de datos ejecutaremos: 

DROP DATABASE nombre_de_la_base_de_datos;

ALTER
Cuando se desea hacer una modificación a una tabla que ya existe (y probablemente tenga muchos y 
valiosos datos cargados) se utiliza la sentencia ALTER TABLE. La sintaxis de esta sentencia es la 
siguiente: 

ALTER TABLE nombre_tabla especificacion

especificacion será la acción a tomar sobre la tabla. Encontraremos: 

ADD COLUMN definicion_create [FIRST | AFTER nombre_columna]


ADD PRIMARY KEY (col1, col2, ...)
DROP COLUMN nombre_columna
DROP PRIMARY KEY
MODIFY definicion_create
CHANGE nombre_columna definicion_create

La primera de las posibilidades nos permite agregar una nueva columna a la tabla. Para ello 
utilizaremos la misma sintaxis que en el CREATE (definicion_create). Lo diferente esta en el 
opcional último parámetro. Este nos permite determinar en que posición agregaremos el atributo: si irá 
al principio (FIRST) o luego de que columna (AFTER). Si no se especifica ninguno irá al final. 
La segunda posibilidad nos permite asignarle la clave primaria a la tabla (similar a como se hacia en el 
CREATE). 
La tercera y cuarta posibilidad nos permiten quitar una columna (junto con todos sus datos) o quitarle 
las claves primarias a la tabla. 
La últimas dos posibilidades nos permiten cambiar a un atributo. Si utilizamos CHANGE podremos 
cambiarle al atributo no solo la definición sino tambien el nombre del atributo (recuerden que en 
definicion_create habia que especificar el nombre de la columna).
Si utilizamos MODIFY le podremos cambiar todas las opciones a una columna salvo su nombre. 
Carrera Linux 2008 ­ Programacion PHP                                                                 99

Ejemplo
Esta es una base de datos de ejemplo creada con datos generados al azar la cual servirá para los 
ejemplos de esta clase y las siguientes.
El script con los datos a cargar puede ser descargado desde el sitio. 
La base de datos de ejemplo(aviones.sql): 

# Para ejecutar este script es necesario tener corriendo un servidor de MySQL.


# Una vez levantado el servidor pueden hacer desde la linea de comandos:
# cat aviones.sql | mysql

# En el modelo de datos, el asterisco al final de una linea denota que


# la tabla posee una cardinalidad de N y en donde no posee asterisco
# posee una cardinalidad de 1. Por ejemplo, si vemos las tablas AVION
# y VUELO podemos leer que un AVION tiene MUCHOS VUELOS o que cada VUELO
# tiene un UNICO AVION asignado.
# El modelo de la base de datos aviones es el siguiente:
Carrera Linux 2008 ­ Programacion PHP                                                                 100

# NOTA: En MySQL lo que empieza con un # es un comentario

DROP DATABASE IF EXISTS aviones;


CREATE DATABASE aviones;
USE aviones;

DROP TABLE IF EXISTS AEROPUERTO;


CREATE TABLE AEROPUERTO (
ATO_ID int(10) unsigned NOT NULL auto_increment,
ATO_NOMBRE varchar(20) NOT NULL default '',
ATO_PIS_ID int(10) unsigned NOT NULL default '',
PRIMARY KEY (ATO_ID),
KEY(ATO_PIS_ID)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS AVION;


CREATE TABLE AVION (
AON_ID int(10) unsigned NOT NULL auto_increment,
AON_AEROLINEA varchar(20) NOT NULL default '',
AON_TATO_TIPO char(1) NOT NULL default '',
PRIMARY KEY (AON_ID),
KEY (AON_TATO_TIPO)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS ESCALA;


CREATE TABLE ESCALA (
ELA_VLO_ID int(11) unsigned NOT NULL default '0',
ELA_ORDEN int(11) unsigned NOT NULL default '0',
ELA_ATO_ID int(11) unsigned NOT NULL default '0',
ELA_HORA_SALIDA datetime default NULL,
PRIMARY KEY (ELA_VLO_ID,ELA_ORDEN),
KEY (ELA_ATO_ID)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS PASAJE;


CREATE TABLE PASAJE (
PJE_ID int(10) unsigned not null auto_increment,
PJE_VLO_ID int(10) unsigned NOT NULL default '0',
PJE_TATO_CLASE enum('Primera','Negocios','Turista') NOT NULL default 'Primera',
PJE_NRO tinyint(4) NOT NULL default '0',
PJE_PRO_ID int(10) unsigned not null,
PRIMARY KEY(PJE_ID),
KEY(PJE_VLO_ID),
KEY(PJE_TATO_CLASE),
KEY(PJE_PRO_ID)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS TIPO_ASIENTO;


Carrera Linux 2008 ­ Programacion PHP                                                                 101

CREATE TABLE TIPO_ASIENTO (


TATO_TIPO_AVION char(1) NOT NULL default '',
TATO_CLASE enum('Primera','Negocios','Turista') NOT NULL default 'Primera',
TATO_DESDE_NRO tinyint(3) unsigned NOT NULL default '0',
TATO_HASTA_NRO tinyint(3) unsigned NOT NULL default '0',
TATO_PRECIO DECIMAL(9,2) NOT NULL default '0',
TATO_CANTIDAD int(10) unsigned NOT NULL default '0',
PRIMARY KEY (TATO_TIPO_AVION,TATO_CLASE),
KEY (TATO_CLASE)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS PASAJERO;


CREATE TABLE PASAJERO (
PRO_ID int(10) unsigned not null auto_increment,
PRO_NOMBRE varchar(40) NOT NULL default '',
PRO_APELLIDO varchar(40) NOT NULL default '',
PRO_EDAD tinyint(4) NOT NULL default '0',
PRO_PIS_ID int(10) unsigned not null,
PRIMARY KEY(PRO_ID),
KEY (PRO_PIS_ID)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS PAIS;


CREATE TABLE PAIS (
PIS_ID int(10) unsigned not null auto_increment,
PIS_NOMBRE varchar(40) NOT NULL default '',
PIS_NOMBRE_CORTO char(3) NULL default '',
PRIMARY KEY(PIS_ID)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS VUELO;


CREATE TABLE VUELO (
VLO_ID int(10) unsigned NOT NULL auto_increment,
VLO_AON_ID int(10) unsigned NOT NULL default '0',
PRIMARY KEY (VLO_ID),
KEY(VLO_AON_ID)
) ENGINE=InnoDB;

##################################################################################
######
# Reglas de integridad

ALTER TABLE AVION


ADD CONSTRAINT AON_TATO_TIPO_FK
FOREIGN KEY (AON_TATO_TIPO)
REFERENCES TIPO_ASIENTO(TATO_TIPO_AVION);

ALTER TABLE VUELO


ADD CONSTRAINT VLO_AON_ID_FK
FOREIGN KEY (VLO_AON_ID)
REFERENCES AVION (AON_ID);
Carrera Linux 2008 ­ Programacion PHP                                                                 102

ALTER TABLE ESCALA


ADD CONSTRAINT ELA_VLO_ID_FK
FOREIGN KEY (ELA_VLO_ID)
REFERENCES VUELO (VLO_ID);

ALTER TABLE ESCALA


ADD CONSTRAINT ELA_ATO_ID_FK
FOREIGN KEY (ELA_ATO_ID)
REFERENCES AEROPUERTO (ATO_ID);

ALTER TABLE PASAJE


ADD CONSTRAINT PJE_VLO_ID_FK
FOREIGN KEY (PJE_VLO_ID)
REFERENCES VUELO (VLO_ID);

ALTER TABLE PASAJE


ADD CONSTRAINT PJE_TATO_CLASE_FK
FOREIGN KEY (PJE_TATO_CLASE)
REFERENCES TIPO_ASIENTO (TATO_CLASE);

ALTER TABLE PASAJE


ADD CONSTRAINT PJE_PRO_ID_FK
FOREIGN KEY (PJE_PRO_ID)
REFERENCES PASAJERO (PRO_ID);

ALTER TABLE AEROPUERTO


ADD CONSTRAINT ATO_PIS_ID_FK
FOREIGN KEY (ATO_PIS_ID)
REFERENCES PAIS (PIS_ID);

ALTER TABLE PASAJERO


ADD CONSTRAINT PRO_PIS_ID_FK
FOREIGN KEY (PRO_PIS_ID)
REFERENCES PAIS (PIS_ID);

Ejercicios
1. ¿Que es y para que sirve SQL? 
2. ¿Es posible modificar la estructura de una tabla luego de ser creada? ¿Que problemas puede 
traer aparejados? 
3. Explicar para que sirve las sentencias CREATE, DROP y ALTER. ¿A que sublenguaje del SQL 
corresponden? 
4. Se pide generar el modelo para una aplicación que posee las siguientes características: 
Se quiere generar una agenda. La misma usará como base un conjunto de personas. De las 
misma se quiere poder almacenar: nombre y apellido; dirección; país; telefonos muchos y de 
distintos tipos (casa, celular, trabajo, fax); fecha de nacimiento; observación.
Se debe tener precargados en la base de datos a los distintos países. Luego se debe poder 
almacenar eventos. Los eventos tendrán una descripción, una observación, una fecha asociada (y 
Carrera Linux 2008 ­ Programacion PHP                                                                 103

además la hora y duración), y, opcionalmente, una hora asociada. Para cada evento, se debe 
poder agregar los participantes (uno o más) del mismo. Estos deben estar ya cargados en la base 
como una persona.
Los eventos deben estar categorizados según una lista de categorias cargada. 
5. Se sugiere modelar algún sistema a voluntad sobre algún tema de interes particular. 

Clase 17 ­ Lenguaje de Manipulación de Datos
INSERT
La sentencia INSERT es la que se utiliza para agregar filas a una tabla.
Su sintaxis es: 

INSERT INTO nombre_tabla VALUES (valor1, ..., valorN), (...), ....

Esta sentencia agregará valores a la tabla nombre_tabla. Lo que se encuentra entre paréntesis será 
un registro a agregar. Hay que destacar que la cantidad de valores corresponderá a la cantidad de 
columnas que tiene la tabla. El valor1 corresponderá a la primer columna, el segundo valor a la 
segunda columna y así sucesivamente. También se permite especificar varias tuplas en una misma 
sentencia INSERT separándolas por comas. 
Por ejemplo para agregar un registro a la tabla PAIS podríamos escribir: 

INSERT INTO PAIS (PIS_ID, PIS_NOMBRE, PIS_NOMBRE_CORTO) VALUES (NULL, 'Argentina',


'ARG');

o si supieramos que ID queremo darle (235 por ejemplo), podríamos escribir: 

INSERT INTO PAIS (PIS_ID, PIS_NOMBRE, PIS_NOMBRE_CORTO) VALUES (235, 'Argentina',


'ARG');

DELETE
La sentencia DELETE sirve para eliminar tuplas de una tabla.
Su sintaxis es: 

DELETE FROM nombre_tabla [ WHERE definicion_where ]

Si se llama esta sentencia sin la cláusula WHERE, DELETE eliminará todos los registros de la tabla. 
Esto no es lo mismo que hacer un DROP, ya que la tabla seguirá existiendo. La cláusula WHERE se 
Carrera Linux 2008 ­ Programacion PHP                                                                 104

utiliza para seleccionar que tuplas se quiere borrar. Las tuplas a borrar serán todas aquellas que 
cumplan con la condición especificada en definicion_where. Esta definición se verá en detalle en 
el apartado del SELECT. 
Si por ejemplo quicieramos borrar toda la tabla de paises podríamos escribr: 

DELETE FROM PAIS

o si por ejemplo quicieramos borrar todos los pasajes del vuelo 15 podríamos escribir: 

DELETE FROM PASAJE WHERE PJE_VLO_ID = 15

UPDATE
UPDATE se utiliza para actualizar valor en un registro que ya existe.
Su sintaxis es: 

UPDATE nombre_tabla SET col1=expr1 [, col2=expr2, ... ] [ WHERE definicion_where ]

Esta sentencia actualizará las columnas especificadas luego de la cláusula SET al valor que se les 
asigna allí. La cláusula WHERE cumple la misma función que para la sentencia DELETE. 
Si desearamos cambiarle el nombre de la aerolina del avion 23 escribiríamos: 

UPDATE AVION SET AON_AEROLINEA = 'TranSink' WHERE AON_ID = 23

o si deseareamos subirle un 10% a todos los precios podríamos escribir: 

UPDATE TIPO_ASIENTO SET PRECIO = PRECIO * 0.1

SELECT
SELECT es el alma del motor de base de datos. Esta es la instrucción más utilizada ya que es la que se 
utiliza para recuperar información de las tablas ya existentes.
Su sintaxis es: 

SELECT [DISTINCT | ALL] * | columnas | expresiones


FROM referencia_tabla [, referencia_tablas, ...]
WHERE definicion_where
GROUP BY columna | nro_columna [, columna | nro_columna]
HAVING definicion_where
ORDER BY columna | nro_columna [ASC | DESC] [, columna | nro_columna [ASC | DESC]
]
Carrera Linux 2008 ­ Programacion PHP                                                                 105

LIMIT [offset, ] cantidad_filas

Este sentencia permitirá obtener columnas o expresiones desde una o más tablas que cumplan con un 
criterio de búsqueda dado. Las columnas y expresiones que devolverá son las especificadas al principio. 
El * equivale por todas las columnas de todas las tablas que se esten utilizando.
La opción DISTINCT sirve para que todas las filas que pertenezcan al resultado sean distintas (las filas 
que son iguales se descartan automaticamente).
La cláusula FROM nos permite espeficiar sobre que tablas vamos a trabajar.
La referencia_tabla se define como: 

nombre_tabla [, otra_tabla | INNER JOIN otra_tabla ON condicion]

la parte que se encuentra entre corchetes puede repetirse indefinidamente.
Si se eligen tablas separandolas por coma lo que se hará es combinar cada fila de la primer tabla con 
todas las filas de la segunda tabla. De esta forma se obtienen todas las combinaciones posibles. Si se 
utiliza INNER JOIN se vinculan las tablas con respecto a la condición establecida (por lo general será 
tabla1.atributo_clave=tabla2.atributo_clave). O sea, primero se buscaran las filas 
de la tabla uno y luego con esos resultados se buscará en la tabla dos las filas que concuerden con la 
condición dada. 
Tomemos el ejemplo más sencillo, traer todos los datos de todos los aeropuertos que esten registrados. 
Para ello escribiremos: 

SELECT * FROM AEROPUERTO

Como el nombre del país no aparece, relacionaremos esta tabla con la de paises para obtener los 
nombres. Ahora quedaría como: 

SELECT * FROM AEROPUERTO, PAIS WHERE ATO_PIS_ID = PIS_ID

Para seguir mejorando la consulta, solo traeremos los campos que nos interese. Para nuestro ejemplo 
traeremos el nombre del aeropuerto con su id y ademas el nombre del país.
Finalmente nos quedará: 

SELECT ATO_ID, ATO_NOMBRE, PIS_NOMBRE FROM AEROPUERTO, PAIS WHERE ATO_PIS_ID =


PIS_ID

Cláusula WHERE
La cláusula WHERE se utilizará para aplicar el criterio de búsquedas. Allí se podran utilizar todos los 
operadores de comparación clásicos (= < <= > >= !=) para crear condiciones y las condiciones se 
pueden juntar utilizando AND (y) y OR (o).
Si por ejemplo se busca al cliente 2425 la condicion podría ser: 
Carrera Linux 2008 ­ Programacion PHP                                                                 106

WHERE CODIGO=2425

Si por ejemplo quicieramos ver toda la información de los aviones pero solo de aquellos que sean del 
tipo A, podríamos escribir: 

SELECT AON_ID, AON_AEROLINEA FROM AVION WHERE AON_TATO_TIPO = 'A'

En este ejemplo, no traeremos el campo AON_TATO_TIPO porque ya sabemos que tendrá siempre el 
valor A. 

Clásula GROUP BY y HAVING
La cláusula GROUP BY se utiliza para agrupar los resultados. Esta cláusula agrupará a los resultados 
cuyas columnas tengan los mismo valores. Las columnas que se utilizarán para agrupar deben ser 
enumeradas. Cuando se agrupa se pueden utilizar algunas funciones para seleccionar.
Si quicieramos saber cuantas escalas tiene un vuelo (contando el punto de partida y el de llegada), 
deberiamos agrupar la tabla ESCALA por el campo que identifica a un vuelo (ELA_VLO_ID) y contar 
cuantos registros hay. Esto nos quedará como: 

SELECT ELA_VLO_ID, COUNT(1) FROM ESCALA GROUP BY ELA_VLO_ID

La cláusula HAVING es similar a la del WHERE pero en vez de filtrar sobre todas las filas, lo hará sobre 
las resultantes de la agrupación. 
Si quicieramos acotar el resultado de la consulta anterior, por ejemplo, trayendo solamente aquellos que 
tengan 4 o más escalas, podríamos escribir: 

SELECT ELA_VLO_ID, COUNT(1) FROM ESCALA GROUP BY ELA_VLO_ID HAVING COUNT(1) >= 4

Clásula ORDER BY y LIMIT
La cláusula ORDER BY sirve para que el resulta salga ordenado por una o más columnas. A cada 
columna se le puede poner DESC para que ordene en forma descendentemente o ASC para que lo haga 
en forma ascendente (por defecto). 
Como ejemplo obtendremos un listado con la cantidad de pasajes que tiene cada persona ordenados del 
que más pasajes haya tenido al que menos haya tenido. Luego, para aquellos con iguales cantidades, lo 
ordenaremos por apellido y nombre. Para ello escribiremos: 

SELECT PRO_APELLIDO, PRO_NOMBRE, COUNT(1) AS CANTIDAD


FROM PASAJERO, PASAJE WHERE PRO_ID = PJE_PRO_ID
GROUP BY PRO_NOMBRE, PRO_APELLIDO
ORDER BY CANTIDAD DESC, PRO_APELLIDO, PRO_NOMBRE
Carrera Linux 2008 ­ Programacion PHP                                                                 107

Aclararémos que si queremos utilizar para ordenar una función agregada (COUNT en este ejemplo), en 
vez de un campo (pudimos haber ordenado el listado por apellido y nombre solamente), se le debe dar 
un ALIAS a dicha función para que la cláusula ORDER BY pueda encontrarla. 
También se pueden limitar la cantidad de resultados utilizando la cláusula LIMIT. Si solo se especifica 
la cantidad se devolverán las primeras cantidad_filas de resultados. Si se espeficia offset, 
(desplazamiento) se devolverá esa cantidad de filas pero partiendo desde el offset especificado. 
Si quicieramos hacer un ranking de las 100 personas que más pasajes haya comprado, podríamos 
agregarle a la consulta anterior: 

SELECT PRO_APELLIDO, PRO_NOMBRE, COUNT(1) AS CANTIDAD


FROM PASAJERO, PASAJE WHERE PRO_ID = PJE_PRO_ID
GROUP BY PRO_NOMBRE, PRO_APELLIDO
ORDER BY CANTIDAD DESC, PRO_APELLIDO, PRO_NOMBRE
LIMIT 100

Subconsultas
Una subconsulta es simplemente una consulta dentro de otra. O sea, es un mecanismo que nos permite 
ejecutar un SELECT dentro de otra consulta (por lo general otro SELECT). El SELECT que se ejecuta 
dentro de otra consulta se lo conoce como subconsulta y a la otra consulta como consulta externa 
(outer query). 
La subconsulta, también conocida como subquery, siempre debe escribirse entre paréntesis.
Para ver como se escribe una subconsulta veremos un ejemplo. Recuperaremos todos los vuelos con sus 
aeropuertos de destino (donde termina el viaje). El problema esta que cada vuelo puede tener una 
cantidad de escalas distinta (o sea que el campo ELA_ORDEN variará según el vuelo). Con lo visto 
hasta ahora no habría forma de resolverlo en una única consulta. Una forma de resolverlo con 
subconsultas es comparando en la cláusula WHERE el campo ELA_ORDEN con el máximo orden de 
cada vuelo (la subconsulta). Esto nos quedaría: 

SELECT VLO_ID, ATO_NOMBRE, ELA_ORDEN


FROM VUELO, ESCALA, AEROPUERTO
WHERE VLO_ID=ELA_VLO_ID AND ELA_ATO_ID=ATO_ID AND
ELA_ORDEN =
(SELECT MAX(E2.ELA_ORDEN)
FROM ESCALA AS E2
WHERE E2.ELA_VLO_ID = VLO_ID)

Como se puede ver la subconsulta esta escrita entre paréntesis. Además como hemos utilizado la misma 
tabla que en la consulta externa, en la consulta interna (se dice que es una subconsulta correlacionada) 
deberémos darle un alias para que MySQL pueda diferencia entre los campos de una y de la otra.
En este ejemplo podemos ver que la subconsulta solo devuelve un único valor, pero podría devolver 
más.
Carrera Linux 2008 ­ Programacion PHP                                                                 108

Para ello en vez de utilizar solo el igual, utilizaremos, además, el operador ANY. De esta forma nos 
quedará la condición como columna = ANY (subconsulta), lo que significará que el campo 
columna puede concordar con cualquiera de los que devuelva subconsulta. También podemos 
utilizar el operador IN en lugar de = ANY (en realidad IN es como un alias de = ANY).
Como ejemplo generaremos un listado con la cantidad de pasajes comprados por persona que vivan en 
el mismo país que alguno de los aeropuertos existentes. Esta consulta nos quedará: 

SELECT PRO_APELLIDO, PRO_NOMBRE, COUNT(1) AS CANT


FROM PASAJERO, PASAJE
WHERE PRO_ID = PJE_PRO_ID AND
PRO_PIS_ID IN (SELECT ATO_PIS_ID FROM AEROPUERTO)
GROUP BY PRO_APELLIDO, PRO_NOMBRE
ORDER BY PRO_APELLIDO, PRO_NOMBRE

Como último ejemplo, utilizaremos una subconsulta pero para traer un dato extra dentro del listado de 
campos. Traeremos la cantidad de pasajes vendidos para cada vuelo, pero solo para aquellos vuelos que 
hayan vendido más de 200 pasajes. Además traerémos la cantidad de escalas que posee cada uno de los 
vuelos seleccionados. Como la tabla VUELO con ESCALA tiene una relación de 1 a muchos y VUELO
con PASAJE también, no podemos relacionarlas todas directamente en el FROM.
Para ello escribiremos la siguiente consulta. 

SELECT VLO_ID, COUNT(1) AS CANT_PASAJES,


(SELECT COUNT(1)
FROM ESCALA
WHERE ELA_VLO_ID = VLO_ID) AS CANT_ESCALAS
FROM VUELO, PASAJE
WHERE VLO_ID = PJE_VLO_ID
GROUP BY VLO_ID HAVING CANT_PASAJES > 200
ORDER BY CANT_PASAJES DESC

Para mejorar la salida hemos decidido asignarle una alias a la subconsulta. Esto es una buena 
costumbre y además será extremadamente necesario hacerlo cuando estemos programando y querramos 
recuperar dicha columna. 

INSERT INTO tabla SELECT ...
Existe una variación del INSERT. Esta variación consiste en utilizar el resultado de un SELECT para 
agregar valores en una tabla en vez de tener que especificar uno cada tupla. Se debe tener en cuenta que 
el resultado de la búsqueda deberá devolver la misma cantidad de columnas (con en el mismo orden y 
los mismo tipos de datos) que tiene la tabla en la cual se quieren ingresar los datos.

Ejercicios
Considerar el modelo de datos definido en la clase anterior. 
1. Escribir un INSERT para cada una de las tablas existentes 
Carrera Linux 2008 ­ Programacion PHP                                                                 109

2. Escribir una consulta que devuelva todos los pasajes y la informacion de los pasajeros para un 
vuelo determinado (para el vuelo 46 por ejemplo). 
3. Escribir una consulta que devuelva la cantidad de personas que hay por pais. Modificar la 
consulta para que agregue otra columna indicando cual es el porcentaje que representa cada 
cantidad. 
4. Averiguar escribiendo una consulta, cual es el pais que mas vuelos pasan por el. 
5. Escribir una consulta que traiga la recaudacion total de cada vuelo y la cantidad de pasajes 
vendidos. 
6. Traer un listado de todos los vuelos con sus aeropuertos de origen y destino. Ademas se debe 
indicar en el mismo listado, la cantidad de escalas que realiza y la cantidad de pasajes vendidos. 

Clase 18 ­ Lenguaje de Administración de 
Seguridad.
Como funciona la seguridad
Primero que nada diremos que MySQL identifica a un usuario mediante su nombre de usuario y el 
host desde el cual se esta conectando. De esta forma podemos tener dos usuarios con igual nombre 
pero que tienen distintos conjuntos de privilegios (ya que se el usuario pepe en localhost es 
distinto que pepe en algun_otro_lado.com).
En principio, el servidor controla la seguridad en dos momentos: 
1. Cuando el usuario se loguea, se controla que su usuario/host/contraseña sean correctos. 
2. Con cada sentencia que el usuario ejecuta, se controla que tenga los privilegios necesarios para 
realizarla. Si el usuario pide hacer un SELECT, un CREATE o un DROP se contrará que tenga 
los permisos, en caso de no tenerlos se le negará la sentencia. 

La sentencia GRANT
Este sentencia se utiliza para otorgar privilegios a un usuario (o crearlo si no existe).
Su sintaxis es: 

GRANT tipo_privilegio
ON objetos
TO usuario [ IDENTIFIED BY 'password' ]

GRANT otorga el privilegio especificado en tipo_privilegio sobre los objetos definidos en 
objetos al usuario definido en usuario. Opcionalmente se le puede agregar una contraseña para 
dicho usuario agregando la cláusula IDENTIFIED BY.
Al ejecutar esta sentencia, si el usuario no existe, es creado.
Carrera Linux 2008 ­ Programacion PHP                                                                 110

Los tipos de privilegios posibles (tipo_privilegio) son: 

Privilegio Descripción
ALL [PRIVILEGES] Otorga todos los privilegios simple, excepto GRANT
OPTION 
ALTER Permite usar ALTER TABLE 
CREATE Permite usar CREATE TABLE 
CREATE TEMPORARY Permite usar CREATE TEMPORARY TABLE 
TABLES
DELETE Permite usar DELETE 
DROP Permite usar DROP TABLE 
INDEX Permite usar CREATE INDEX y DROP INDEX 
INSERT Permite usar INSERT 
SELECT Permite usar SELECT 
SHOW DATABASES Permite ejecutar SHOW DATABASES, el cual muestra 
todas las bases de datos de la base
SHUTDOWN Permite usar mysqladmin shutdown 
UPDATE Permite usar UPDATE 
USAGE Sinónimo de NO PRIVILEGES
GRANT OPTION Permite otorgar privilegios
Los objetos permitidos son: 
nombre_tabla | base_datos.* | *.*

Esto nos permite otorgar los privilegios sobre una sola tabla (nombre_tabla), sobre todas las tablas 
de una base de datos (base_datos.*) o sobre todas las tablas de todas las bases de datos (*.*). 
Finalmente, usuario define al usuario que se quiere crear / otorgar privilegios. Como mencionamos 
anteriormente, un usuario esta identificado por su nombre y su host. Por lo tanto, el formato normal 
para usuario es 'nombre'@'host'. Un ejemplo podría ser, 'pepe'@'locahost'.
MySQL permite el uso de wildcards en el campo host. Estos son el símbolo de porcentaje (%) y el 
guión bajo (_). Ambos son análogos al asterisco (*) y al signo de interrogación (?) del shell. El 
primero, %, concuerda con cualquier caracter, cualquier cantidad de veces. De esta forma podríamos 
definir a un usuario como 'pepe'@'%.tuxsys.com.ar' para que el usuario 'pepe' pueda 
conectarse desde cualquier dominio tuxsys.com.ar. O podríamos definir a un usuario como 
'pepe'@'%' para que pueda loguearse desde cualquier lugar del planeta.
El guión sirve para lo mismo que el porcentaje pero solo concuerda con un caracter. 
Por ejemplo, para crear un usuario pepe en la máquina local, que trabaja en un proyecto sobre una base 
de datos llamada aviones y con contraseña 'epep', podríamos escribir: 
Carrera Linux 2008 ­ Programacion PHP                                                                 111

GRANT USAGE on aviones.* TO 'pepe'@'localhost' IDENTIFIED BY 'epep';

o para permitir al mismo usuario consultar todas las tablas de dicha base da datos: 

GRANT SELECT ON aviones.* TO 'pepe'@'localhost';

La sentencia REVOKE
Esta sentencia se utiliza para quitarle privilegios a un usuario.
Su sintaxis es: 

REVOKE tipo_privilegio
ON objeto
FROM usuario

Los parámetros tipo_privilegio, objeto y usuario son los mismo que para la sentencia GRANT. 
Para quitarle todos los privilegios a un usuario se puede utilizar la siguiente sintaxis: 

REVOKE ALL PRIVILEGES ON *.* FROM 'pepe'@'localhost'

Utilidades Relacionadas

mysql
Esta aplicación es el cliente, para modo texto, que viene por defecto en toda paquete de MySQL. Desde 
él podemos conectarnos a cualquier base de datos.
Para ello simplmemente debemos ejecutarlo desde la línea de comandos solo por su nombre. Por 
defecto, si no especificamos un host o un usuario, tomará a la máquina local y al usuario con el que nos 
hayamos logueado en el sistema.
Para especificarle el host al cual nos queremos conectar deberemos suministrarle la opción -h seguida 
del nombre del host.
Para especificarle el usuario deberemos especificarle la opción -u seguida del nombre del usuario.
Si el usuario con el cual nos queremos conectar posee contraseña deberemos especifcicarle además la 
opción -o, en caso contrario no nos podremos loguear.
También podemos especificarle sobre que base de datos queremos trabajar (ahorrándonos de hacer 
luego un USE de la misma). Para ello simplemente nombraremos como último parámetro el nombre de 
la misma. 
Carrera Linux 2008 ­ Programacion PHP                                                                 112

mysqladmin
Esta herramienta nos permite ejecutar algunas tareas administrativas sobre nuestro servidor, como crear 
bases de datos, observar las consultas en proceso, chequear el estado actual y más.
La sintaxis de este comando es: 

mysqladmin [OPCIONES] comando [OPCIONES_COMANDO]

Entre los comando que existen podemos destacar: 
Comando Descripción
create Crea una base de datos con el nombre base_datos 
base_datos 
drop Elimina la base de datos que posee el nombre base_datos 
base_datos 
kill id, id, Termina a la fuerza bruta consultas que se esten ejecutando 
...  (ver processlist) 
password Cambia la contraseña del usuario con el que se esta 
"nueva_contr conectando mysqladmin 
aseña" 
ping  Cheque si el servidor esta levantado. 
processlist  Muestra una lista con todos los hilos que se estan ejecutando 
en el servidor. En cada hilo se ejecuta una consulta. Aquí 
podemos ver que id del hilo le corresponde a que consulta, 
como así también que usuario la esta ejecutando (y desde que 
host), sobre que base de datos, cuanto tiempo lleva 
ejecutándose y en que estado se encuentra. 
shutdown  Detiene el servidor 
status  Muestra algunas estadísticas sobre el estado del servidor. En 
particular se verá: El tiempo (en segundos) que se ha estado 
ejecutando el servidor; La cantidad de hilos activos (clientes); 
La cantidad de consultas procesadas; La cantidad de consultas 
que han tomado más que long_query_time (definido por 
parámetro al inicializar el servidor) en ejecutarse; La cantidad 
de tablas que ha abierto el servidor; La cantidad de tablas 
abiertas en el momento; 
variables  Muestra el contenido de las variables globales de MySQL 
version  Muestra la versión actual 

mysqlcheck
Esta herramienta se utiliza para comprobar y corregir tablas que hayan quedado rotas por algún motivo. 
Carrera Linux 2008 ­ Programacion PHP                                                                 113

Solo sirve para tablas del tipo MyISAM. 
Su sintaxis es: 

mysqlcheck [OPCIONES] base_datos [tablas]


mysqlcheck [OPCIONES] --databases base_datos1 [base_datos2 base_datos3 ... ]
mysqlcheck [OPCIONES] --all-databases

En el primero de los casos, se aplica el comando sobre todas las tablas de base_datos, a no ser que se 
especifiquen tablas.
El segundo de los casos se aplica sobre todas las tablas de las bases de datos especificados.
Finalmente, el útlimo modo es sobre todas las tablas de todas las bases de datos.
Entre las opciones importantes encontramos: 
Opción Descripción
--check  Comprueba si la tabla esta en un estado correcto. 
--repair  Repara una tabla si posee errores 
--optimize Optimiza las tablas. Esto es recuperar el espacio empleado por 
registros que han sido eliminados. MySQL siga guardando dicho 
espacio para reutilizarlo con nuevos registros y no tener que 
volver a pedir ese espacio al Sistema Operativo. 

mysqldump
Esta utilidad sirve para hacer copias de respaldo de bases de datos/tablas.
Este comando generará un archivo con todas las sentencias SQL para poder volver a crear las tablas y 
cargar los datos de las bases especificadas.
Su sintaxis es: 

mysqldump [OPCIONES] base_datos [tablas]


mysqldump [OPCIONES] --databases base_datos1 [base_datos2 base_datos3 ... ]
mysqldump [OPCIONES] --all-databases

En el primero de los casos se generará el SQL necesario para generar la base de datos base_datos 
completa. Si se especifica además las tablas (separadas por espacios) se generará solo de aquellas tablas 
y no de la base completa.
La segunda posibilidad nos permite generar SQL para varias base de datos pasándole como parámetro 
--databases y luego el nombre de cada una de las bases que queremos.
Por último, podemos hacerlo sobre todas las bases de datos de nuestro sistema utilizando el parámetro 
--all-databases. 
En todos los casos, mysqldump enviará todo el SQL necesario a la salida estándar. Para guardar en un 
archivo para utilizarla luego, deberemos redireccionar la salida al mismo: 

mysqldump --all-databases > mi_backup.sql


Carrera Linux 2008 ­ Programacion PHP                                                                 114

Entra las OPCIONES importantes podemos encontrar: 
Opción Descripción
--add-drop- Esta opción agregar delante del CREATE TABLE un DROP
table  TABLE. De esta forma, podemos correr el script sobre una 
base que ya exista sin que nos arroje errores al tratar de crear 
las tablas.
-- Permite generar SQL compatible con otros motores de bases 
compatible=ti de datos. Entre los posibles valores de tipo podemos 
po  encontrar: ansi, mysql323, mysql40,
postgresql, oracle, mssql, db2, maxdb,
no_key_options, no_table_options, o
no_field_options 
--no-create-db No agrega la línea del CREATE DATABASE al bajar una 
base de datos. 
--no-create-
No agrega los CREATE TABLE de cada tabla 
info 
--no-data  No agrega los INSERT con el contenido de las tablas. Esto 
nos permite obtener un archivo con solo la estructura de la 
base de datos sin los datos. 

mysqlhotcopy
Este script nos permite crear backups de la base de datos duplicando las mismas en un nuevo directorio.
Su sintaxis es: 

mysqlhotcopy base_datos1 [base_datos2 basedatos3 ...] /nuevo/directorio

De esta forma, se generará una copia de la/s base/s de datos base_dato1, base_dato2, etc en el 
directorio /nuevo/directorio. 

mysqlimport
Esta aplicación sirve para cargar datos desde archivos de texto a tablas (es una aplicación sobre la 
sentencia LOAD DATA INFILE). 
El formato del archivo debe ser un registro por línea y cada campo separado por un delimitador 
(generalmente una tabulación o una coma).
La sintaxis del comando es: 

mysqlimport [OPCIONES] base_datos archivo_datos1 [archivo_datos2 ...]

El nombre de la tabla se determinará por el nombre del archivo, quitandole cualquier extensión que 
posea. Por lo tanto, los archivos AVION.txt, AVION.text o AVION.csv harán referencia a la tabla AVION. 
Carrera Linux 2008 ­ Programacion PHP                                                                 115

Entre las opciones destacadas podemos encontrar: 
Opción Descripción
-- Es una lista (separada por comas) de los nombres de las 
columns=lista_c columnas. De esta forma se concordarán las columnas en 
olumnas  el archivo de texto con la correspondiente en la tabla de 
la base de datos. 
--delete  Vacía la tabla antes de agregar los registros 
--fields-
terminated- Determina que caracter es el delimitador de los campos. 
by=caracter 
--ignore  En caso de que se trate de agregar un registro que ya 
existe (clave duplicada) el nuevo registro se ignora y se 
continua insertando los demás. 
--replace  En caso de que se trate de agregar un registro que ya 
existe (clave duplicada) el viejo registro se reemplaza 
por el último y se continua insertando los demás. 

mysqlshow
Esta herramienta nos permite consultar sobre la estructura de las bases de datos.
Su sintaxis es: 

mysqlshow [OPCIONES] [base_datos [tabla [columna]]]

Este comando mostrará información dependiendo la cantidad de argumentos, según el orden 
establecido.
Si no se le pasa ningún argumento, mostrará todas las bases de datos que haya en el sistema.
Si soló se completa el argumento base_datos, mostrará todas las tablas que haya dentro de dicha base 
de datos.
Si además se completa tabla, entonces mostrará la estructura de la misma. Incluyendo todas las 
columnas, con sus tipos de datos y demás configuraciones.
Si se especificá columna solo se mostrará la información del punto anterior pero solo para la columna 
especificada. 
Entre las opciones disponibles podemos encontrar: 
Opción Descripción
--keys  En el caso de esta viendo la información de una tabla, también se 
agregan todos los índices creado sobre la misma. 
--status  Muestra información extra sobre las tablas. 
Carrera Linux 2008 ­ Programacion PHP                                                                 116

Ejercicios
1. ¿Como se aplica la seguridad en MySQL? 
2. ¿Que sentencias se poseen para manejar usuarios? ¿A que sublenguaje de SQL pertenecen? 
¿Hasta que nivel puedo aplicar la seguridad? 
3. Crear un usuario "stokes" con contraseña "akl84hg" para que solo pueda consultar las tablas de 
las clases anteriores. Corroborar que el usuario no pueda crear, borrar ni modificar tablas. 
4. ¿Que herramienta utilizaria para hacer una copia de respaldo de una base de datos? Justifique su 
respuesta 

Clase 19 ­ Indices e Integridad Referencial
Aumentando la velocidad de acceso
Cuando se esta trabajando con tablas que poseen pocos registros, no es posible notar si el sistema tiene 
o no una buena performance. De movida, con cada SELECT que se ejecuta se deberá barrer todos los 
registros de la tabla para encontrar aquellos que concuerden con el criterio pedido. Al aumentar la 
cantidad de registros el sistema comienza a volverse más y más lento, aún para las consultas más 
sencillas. Esto ocurre ya que para realizar una búsqueda, el motor necesariamente necesita recorrerse 
toda la tabla (FULLSCAN) para verificar que registros concuerdan.
Esta situación puede y debe ser remediada haciendo uso de índices. Un índice es una estructura auxiliar 
la cual ayuda a encontrar registros sin necesidad de hacer un barrido completo de la tabla. Existen 
varios tipos de índices pero actualmente, MySQL soporta solo un tipo: el Arbol­B.
Los índices se crean sobre una o más columnas de una tabla. Esto implica que toda esa información 
estará "duplicada", o sea, que el índice ocupará un espacio un poco mayor al tamaño total de las 
columnas seleccionadas. Al usar el índice se aumentará la velocidad al tratar de recuperar registros en 
base a esas columnas pero tendrá el costo de actualizarse cuando se inserta o borra una fila. Es por eso 
que los índices pueden ser beneficiosos pero si se usan en exceso pueden llegar a no serlo. 
Un Arbol­B es una estructura que posee forma de árbol que crece de la raíz hacia la hojas. En un arból 
habrá un nodo raíz el cuál tendrá N hijos. A su vez cada hijo de la raíz puede tener N hijos y así 
sucesivamente. A cada camino que se va formando se lo llama rama. Aquellos nodos que se encuentren 
al final de cada rama se los denomina hoja.
Si se arma un Arbol­B sobre una columna, por ejemplo CODIGO de la tabla CLIENTES, en promedio 
para buscar un CODIGO en una tabla de 1.000.000 de registros, tomará 20 accesos. Este valor es 
mucho menor a barrerse el millón de registros. 
Los índices se crearán sobre las columnas en las cuales hagamos consultas frecuentemente. Por lo 
expuesto anteriormente, no es beneficioso poner índices en todas las columnas. Por lo tanto, habrá que 
analizar que consultas se harán y en donde conviene crear los índices.
Internamente, MySQL, al determinar una(s) columna(s) como clave primaria, generará un índice único 
sobre dichas columnas. Por lo tanto, sobre la clave primaria siempre se tiene buena velocidad de 
Carrera Linux 2008 ­ Programacion PHP                                                                 117

acceso. Esto se debe a que las relaciones siempre se hacen sobre las claves primarias por lo tanto si no 
se posee dicha columna indexada tomará mucho tiempo relacionar dos tablas.
Los índices pueden o no aceptar valores duplicados. Si creamos un índice único, entonces los valores 
de esa columna nunca se repetirán. Cuando utilizabamos el UNIQUE en el CREATE TABLE, lo que se 
creabá era un índice que aseguraba esto.
Una vez creado el índice MySQL se encargará automaticamente de determinar cuando conviene 
utilizarlo y cuando no. Por lo tanto, no hará falta en cada consulta escribir explicitamente que índice 
debe usar ni como. 
En MySQL para crear un índice se utilizará el comando: 

CREATE [UNIQUE] INDEX nombre_indice ON tabla ( campos )

En donde, la palabra UNIQUE es opcional y determina si el índice aceptará o no aceptará duplicados.
nombre_indice es simplemente el nombre que se la dará al indice (para poder eliminarlo luego si hace 
falta).
tabla es el nombre de la tabla sobre la cual se creará el índice. 
Y campos son todos los campos (1 o más) que tomará el índice. Si se necesitan más de un campo se los 
debe separar por comas. 
Una vez creado el índice es posible eliminarlo si hace falta. Para ello se utlizará el comando DROP
INDEX de la siguiente forma: 

DROP INDEX nombre_indice ON tabla

En donde, nombre_indice es el nombre que se le dió al indice cuando se creo y tabla es el nombre de la 
tabla sobre la cual esta el índice. 

Integridad Referencial
Cuando comenzamos a hablar de base de datos hicimos mención de la integridad referencial. La 
integridad referencial significa poder decirle al motor explícitamente que campo hace referencia a que 
clave primaria de que tabla. Por lo tanto, tendriamos las relaciones metidas dentro del motor(reglas de 
integridad), lo cual nos asegura que la base siempre esta en un estado consistente. Esto significa que 
nunca encontraríamos relaciones mal hechas o códigos que no existen.
Las tablas estandar (MyISAM) no pueden utilizar integridad referencial. Para ello hay que crear las 
tablas del tipo InnoDB como hemos visto en clases anteriores (utilizando la opción TYPE en el 
CREATE TABLE). Además existe otra restricción: para crear una relación ambas columnas, la clave 
foránea como la clave referenciada, deben tener un índice creado. Esto se debe a que en el caso 
contrario, la performance disminuiría significativamente con cada INSERT, DELETE y UPDATE ya 
que las reglas de integridad se deben verificar en cada una de estas operaciones.
Para definir una relación entre dos tablas utilizaremos la sentencia ALTER TABLE de la siguiente 
forma: 
Carrera Linux 2008 ­ Programacion PHP                                                                 118

ALTER TABLE tabla


ADD [CONSTRAINT nombre_constraint] FOREIGN KEY (columnas_clave_foranea)
REFERENCES tabla_independiente (columnas_independiente

[ ON DELETE CASCADE | SET NULL | NO ACTION | RESTRICT ]


[ ON UPDATE CASCADE | SET NULL | NO ACTION | RESTRICT ]

Aquí tabla es la tabla que posee una columna que es clave foránea. Esta es la columna que hará 
referencia a otra tabla.
nombre_constraint es el nombre que se le dará a la relación. Esta alternativa (es opcional) existe 
simplemente para respetar el estándar ya que MySQL la ignora.
columnas_clave_foranea son el nombre de la o las columnas (separadas por comas) que hacen 
referencia a la tabla independiente.
tabla_independiente es la tabla la cual es referenciada y columnas_independientes su clave primaria 
(que deberán concordar con las de columnas_clave_foranea).
Antes de ver las otras opciones veamos un ejemplo: 

CREATE TABLE CLIENTES (


CES_ID INT UNSIGNED NOT NULL,
CES_RAZON_SOCIAL VARCHAR(50) NOT NULL,
CES_DIRECCION VARCHAR(100) NOT NULL
) TYPE=InnoDB;

ALTER TABLE CLIENTES ADD PRIMARY KEY (CES_ID);

CREATE TABLE VENTAS (


VAS_NUMERO INT UNSIGNED NOT NULL,
VAS_CES_ID INT UNSIGNED NOT NULL,
VAS_FECHA DATETIME NOT NULL,
VAS_MONTO_TOTAL DECIMAL(13,2) NOT NULL,
) TYPE=InnoDB;

ALTER TABLE VENTAS ADD PRIMARY KEY (VAS_NUMERO);

CREATE INDEX NDX_CLIENTES ON VENTAS (VAS_CES_ID);

ALTER TABLE VENTAS ADD FOREIGN KEY (VAS_CES_ID) REFERENCES CLIENTES (CES_ID);

En este ejemplo, CLIENTES es la tabla independiente. Además su clave primaria esta compuesta por la 
columna CES_ID. Por lo tanto, toda tabla que haga referencia a un cliente, debe poner el código de 
esta columna. VENTAS es la tabla que hace referencia a un cliente. Por lo tanto se definió una columna, 
VAS_CES_ID, que contendrá el código del cliente que realizó la operación. Como será una clave 
foránea se creó un índice sobre la misma. Luego, el ALTER TABLE correspondiente relaciona la 
columna VAS_CES_ID de la tabla VENTAS con la columna CES_ID (clave primaria) de la tabla 
CLIENTES. 
Como recomendación práctica diremos que es mejor, dentro del script que generá la base de datos, 
Carrera Linux 2008 ­ Programacion PHP                                                                 119

definir primero todas las tablas y luego todas las relaciones. De esta forma siempre que se vaya a 
definir una relación ya se poseen las tablas intervinientes creadas y no hay que estar moviendo 
definiciones por todo el archivo para que al momento de definir la relación ambas tablas existan. 
Por último veamos las opciones restantes ON DELETE y ON UPDATE. Esta reglas le dicen al motor 
que hacer en caso que se borre o actualice el valor de la clave referenciada (en el ejemplo CES_ID de 
CLIENTES). Hay 4 acciones posibles: CASCADE, SET NULL, NO ACTION y RESTRICT. Las 
acciones son similares para DELETE y UPDATE con la única diferencia que DELETE borrará y 
UPDATE actualizará.
La opción CASCADE propagará la operación a las tablas referenciadas. En el ejemplo, si borramos un 
cliente se borrarán de la tabla VENTAS todos los registros que contengan a ese cliente.
La alternativa SET NULL pondrá el valor NULL en la columna de la clave foránea (VAS_CES_ID) si y 
solo si la columna acepta valores nulos. Si no los acepta no se podrá realizar la operación (el DELETE
o UPDATE fallarán).
La opción NO ACTION (no recomendada) no tomará ninguna acción y la base quedará en un estado 
inconsistente.
Finalmente, la opción RESTRICT prohibirá la ejecucíon del DELETE o del UPDATE y nunca podrá ser 
eliminada o actualizada la clave primaria de la tabla independiente. 

Ejercicios
1. ¿Para que se utilizan los indices? 
2. ¿Que ventajas trae utilizar indices? 
3. ¿Que desventajas trae utilizar indices? 
4. Se pide agregar todas las reglas de integridad referencial a la agenda creada anteriormente. 
5. Se pide agregar todas las reglas de integridad referencial al sistema generado a voluntad. 

Clase 20 ­ PHP y MySQL
Introducción
Para utilizar MySQL desde PHP hay que conocer solo un par de funciones que viene incluidas con 
PHP.
La idea es la misma que al utilizar el cliente de MySQL: primero se debe crear una conexión y elegir 
sobre que base de datos se quiere trabajar. Luego es posible ejecutar las sentencias.
Para ejecutar un sentencia los pasos serán: ejecutar la sentencia e ir recuperando de a una las filas del 
resultado. 

Creando una conexión
Para conectarse a un servidor MySQL se utiliza la función mysql_connect. Esta función lleva 
Carrera Linux 2008 ­ Programacion PHP                                                                 120

como parámetros la dirección del servidor, con que usuario se va a conectar y cual es su contraseña. 
Recordemos que al instalar MySQL por defecto solo esta el usuario root y sin contraseña, que si bien 
no es lo más seguro sirve para poder practicar.
La función mysql_connect devolverá un recurso a traves del cual podremos utilizar el motor en su 
totalidad. En caso de que la conexión haya fallado por algun motivo, mysql_connect devolverá 
falso.
Ejemplo: 

$link = mysql_connect("127.0.0.1", "root", "");


if(!$link) {
echo mysql_error($link). "<br>";
exit;
}

NOTA: la función mysql_error devuelve una cadena con el error de la última operación realizada. 
La función exit termina la ejecución del script. 

Seleccionando una Base de Datos
El siguiente paso es elegir sobre que base de datos se desea trabajar. Para ello se emplea la función 
mysql_select_db que lleva como parámetros el nombre de la base de datos y la conexión creada 
anteriormente (que devuelve mysql_connect). 
Esta función devolverá verdadero si se pudo realizar la operación y falso en caso contrario.
Ejemplo: 

$ok = mysql_select_db("aviones", $link);


if(!$ok) {
echo mysql_error($link). "<br>";
exit;
}

El ejemplo es similar al anterior. Si falla no será posible utilizar la base de datos y se termina le 
ejecución del script. 

Enviando Sentencias
Para enviar cualquier sentencia de SQL se puede utilizar la función mysql_query. Esta función lleva 
como parámetro una cadena con la sentencia (aquí no hace falta poner el carácter ; ) y la conexión al 
motor. 
Como esta sentencia es muy utilizada, es posible (y muy común) llamarla sin el parámetro de conexión. 
Si este no se especifica, se utilizará el de la última conexión hecha. Como la mayoría de las veces se 
trabaja con una sola conexión, nos ahorra de escribir siempre la variable de la conexión, aumentando, 
además, la posibilidad de errores de tipeo y tiempo en depurarlo luego. En realidad, todas las funciónes 
que lleven como parámetro la conexión, pueden omitirse seguramente este parámetro al trabajar con 
una sola conexión.
Carrera Linux 2008 ­ Programacion PHP                                                                 121

Esta función devuelve un recurso que representa el resultado. Si hubo algún error devolverá falso y la 
función mysql_error nos dirá cual fue el error.
Ejemplo: 

$consulta = "INSERT INTO AVIONES VALUES (1, 'AeroExplote', 'Z')";


$ok = mysql_query($consulta);
if(!$ok) {
echo mysql_error(). "<br>";
}

En este ejemplo hemos agregado una fila a la tabla AVIONES. 

Recuperando los resultados
Una vez ejecutada una sentencia será necesario, en ocasiones, recuperar los resultados. Algunas 
sentencias, como INSERT, UPDATE o DELETE, no devuelven ningún resultado, en cambio, el 
SELECT devuelve cero o más filas como resultado. 
Para recuperar los resultados tenemos, en principio, dos funciones: mysql_fetch_row y 
mysql_fetch_array. 
La función mysql_fetch_row irá devolviendo de a uno los resultados en forma de un arreglo con 
indices numéricos. Devolverá falso una vez que se trate de leer más alla de la última fila del resultado.
Ejemplo: 

$consulta = "SELECT AES_ID, AES_AEROLINEA, AES_TIPO FROM AVIONES ORDER BY TIPO";


$resultado = mysql_query($consulta);
if(!$resultado) {
echo mysql_error(). "<br>";
}
echo "<TABLE ALIGN=CENTER BORDER=1>";
echo "<TR ALIGN=CENTER>";
echo "<TH>ID</TH>";
echo "<TH>Aerolinea</TH>";
echo "<TH>Tipo</TH>";
echo "</TR>";
while($avion = mysql_fetch_row($resultado)) {
echo "<TR>";
echo "<TD>$avion[0]</TD>";
echo "<TD>$avion[1]</TD>";
echo "<TD ALIGN=CENTER>$avion[2]</TD>";
echo "</TR>";
}
echo "</TABLE>";

Este ejemplo creará una tabla en HTML con los resultados de la consulta. Para cada ciclo del while, se 
cargará en el arreglo $avion una fila del resultado, de forma que en la posición 0 se encuentre el valor 
de la primer columna seleccionada, en la 1 el valor de la segunda columna seleccionada y así 
sucesivamente.
Esta función tiene la desventaja que al modificar el orden de los campos (o al agregar) los indices se 
Carrera Linux 2008 ­ Programacion PHP                                                                 122

modificarán y habra que retocar el código por todas partes.
Para solventar esta deficiencia podemos utilizar la función mysql_fetch_array. Esta función 
opera de la misma forma que la anterior, pero devuelve un arreglo asociativo, en donde las claves serán 
los nombres de las columnas seleccionadas.
Modificando el ejemplo anterior nos quedaría: 

$consulta = "SELECT AES_ID, AES_AEROLINEA, AES_TIPO FROM AVIONES ORDER BY TIPO";


$resultado = mysql_query($consulta);
if(!$resultado) {
echo mysql_error(). "<br>";
}
echo "<TABLE ALIGN=CENTER BORDER=1>";
echo "<TR ALIGN=CENTER>";
echo "<TH>ID</TH>";
echo "<TH>Aerolinea</TH>";
echo "<TH>Tipo</TH>";
echo "</TR>";
while($avion = mysql_fetch_row($resultado)) {
echo "<TR>";
echo "<TD>$avion[AES_ID]</TD>";
echo "<TD>$avion[AES_AEROLINEA]</TD>";
echo "<TD ALIGN=CENTER>$avion[AES_TIPO]</TD>";
echo "</TR>";
}
echo "</TABLE>";

Como se puede apreciar, para acceder al ID, por ejemplo, se hará a traves de $avion["AES_ID"]
en vez de $avion[0]. Esto demuestra que la posición no es importante al utilizar 
mysql_fetch_array. 

Cerrando la conexión
Para cerrar la conexión se utiliza la función mysql_close que lleva como parámetro la conexión. Por 
lo general no se utiliza mucho esta función ya que al finalizar el script se cierran automáticamente todas 
las conexiones abiertas.
Ejemplo: 

mysql_close($link);

Funciones varias
Veremos otras dos funciones que pueden ser de utilidad: mysql_num_rows y mysql_insert_id.
La primera de ellas devuelve la cantidad de filas que produjo un resultado válido devuelto por 
mysql_query.
Ejemplo: 
Carrera Linux 2008 ­ Programacion PHP                                                                 123

$consulta = "SELECT ID, AEROLINEA FROM AVIONES WHERE TIPO='A'";


$r = mysql_query($consulta);
echo "La consulta devolvio ". mysql_num_rows($r) . "<br>";

La función mysql_insert_id devuelve el último id generado automáticamente por una columna 
con atributo AUTO_INCREMENT. 
Ejemplo: 

$consulta = "INSERT INTO AVIONES VALUES (NULL, 'VueleBajo VueleTierra', 'W')";


mysql_query($consulta);
$id = mysql_insert_id();
echo "Se genero el avion cuyo ID es $id<br>";

De esta forma es posible crear el ID automáticamente y luego utilizarlo para relacionarlo en otras 
tablas. 

Ejercicios
1. ¿Como se hace para recuperar el resultado de una consulta? 
2. ¿Que diferencias presentan los distintos metodos? 
3. Hacer un sistema que permita cargar encuestas dentro de una base de datos. Luego se debera 
crear una pagina que muestre la encuesta actual (marcada en la base de datos como tal) y 
permita a los usuarios votar en la misma, registrando el voto.
Luego se debera crea otra pagina que permita consultar el estado de cualquier encuesta viendo 
cuante gente voto en cada opcion y que porcentaje respresenta el mismo. 
4. Primero, considere la base de datos definida anteriormente.
Luego se desea generar una página que permita consultar los vuelos disponibles y asignar los 
pasajes para dichos vuelos.
El primer paso es generar una página que permite encontrar si hay vuelos disponibles 
mencionando el Origen y el Destino. El sitio debe informar sobre que vuelos tiene ese trayecto, 
en que fecha salen, los aeropuertos de salida/ llegada y cantidad de pasajes libres por clase.
Luego se debe poder ir, presionando sobre el vuelo, a otra página que de la información 
detallada del vuelo y que sea posible asignar (vender) pasajes. Esta pagina debe informar todo 
sobre el vuelo: que avión es el que lo realiza (ID + AEROLINEA + TIPO), todas sus escalas 
(con toda la información del Aeropuerto) con los horarios correspondientes y en orden, el total 
recaudado por Clase con la cantidad de asientos ocupados y el total de asientos, y el total 
recaudado.
Con toda esta información en pantalla el usuario podrá decidir si viajar o no en ese vuelo. Luego 
debería presentar un link para ir a la asignación de pasajes. Aqui se deben mostrar todos los 
asientos que haya en el avión. Aquellos que ya estan ocupados los marcará como ocupados y los 
que esten libres deberá poner un checkbox al costado para poder seleccionarlos. Con todos los 
asientos que el usuario haya marcado se asignarán luego los pasajes. 
5. Se desea realizar un pequeño sistema para generar un GuestBook. Un GuestBook (o Libro de 
Visitas) sirve para que los navegantes dejen sus mensajes en la página y que estos puedan ser 
Carrera Linux 2008 ­ Programacion PHP                                                                 124

vistos por todo el mundo.
El sistema debe permitir: 

Que los usuarios dejen mensajes. Para ello el usuario debera completar: nombre, email, 
calificacion del sitio y el mensaje. Luego el sistema registrará además la fecha y hora en que se 
dejó dicho mensaje. Permitir ver los mensajes por páginas. O sea que se deben ver los últimos 
10 mensajes, permitiendo volver hacia atrás de a 10 mensajes hasta que se acaben.
Generar un cuadro basado en la calificación con la siguiente forma: 
+--------------------------------------+
| Calificacion | Cantidad | Porcentaje |
|--------------+----------+------------|
| Excelente | 60 | 30% |
|--------------+----------+------------|
| Muy Bueno | 40 | 20% |
|--------------+----------+------------|
| Bueno | 60 | 30% |
|--------------+----------+------------|
| Regular | 20 | 10% |
|--------------+----------+------------|
| Pesimo | 20 | 10% |
+--------------------------------------+

Las calificaciones deben estar en una tabla (pueden ser las cinco mencionadas, o pueden ser 
más o pueden ser menos, el sistema debe funcionar para cualquier cantidad) y al usuario se le 
deberá presentar el <SELECT> correspondiente para que eliga. 

También podría gustarte