Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Introduccin
Aunque PHP y ASP tienen bsicamente la misma funcionalidad, su sintaxis es completamente distinta y su semntica tambin presenta diferencias, por lo que aunque lo que podamos hacer con ASP tambin lo podamos hacer en PHP (y viceversa), la adaptacin de uno a otro lenguaje puede resultar algo complicada al principio. ASP (Active Server Pages) es, ms que un lenguaje de programacin en s, una tecnologa que permite insertar en una pgina HTML cdigo que se ejecutar en el servidor. Este cdigo puede ser Java, JavaScript o, ms comnmente, VBScript. Por lo tanto cuando en este curso hagamos referencia al lenguaje ASP, y no a la tecnologa, nos referiremos a VBScript. Por su parte, PHP ("PHP: Hypertext Preprocessor") provee de una tecnologa similar a ASP para insertar cdigo en las pginas HTML, pero PHP adems de la tecnologa es el lenguaje. En PHP slo podemos incluir cdigo en un lenguaje, PHP, que ser el lenguaje que vamos a estudiar en el presente curso. PHP es un lenguaje interpretado basado principalmente en C, C++ y Java, con los que comparte prcticamente toda su sintaxis y semntica, y aporta tambin algunas caractersticas de lenguajes interpretados como Perl y Bash. Debido a esto, una de sus principales caractersticas y una gran baza a su favor es que la curva de aprendizaje para programadores que ya conozcan estos lenguajes es muy suave, prcticamente pueden sentarse delante del ordenador y comenzar a escribir cdigo. En cuanto a la tecnologa detrs de PHP, ya en la versin 3.0 el intrprete de PHP era bastante ms rpido que los intrpretes existentes de ASP, lo que junto con su buena integracin con el servidor HTTP Apache y su capacidad de acceder a unos 20 sistemas de Bases de Datos distintos, lo ha convertido en un fuerte competidor frente a las soluciones de Microsoft. Con la versin 4.0 de PHP que ha visto la luz hace pocos meses la situacin ha mejorado todava ms: el intrprete es ms rpido (hasta 12 veces ms rpido que el de la versin 3.0); se ha perfeccionado la integracin de PHP con otros servidores adems de Apache, entre otros IIS; y se ha modularizado todo el diseo interno, entre otras cosas independizado el intrprete del lenguaje PHP (Zend) del mdulo de comunicacin con el servidor, con lo que a partir de ahora es posible utilizar PHP como lenguaje interpretado en cualquier otro proyecto (ya se est trabajando para utilizar PHP como lenguaje para procedimientos en MySQL.) El presente curso est estructurado en dos secciones: En la primera se introduce la sintaxis y semntica bsica de PHP, haciendo especial hincapi en sus diferencias con ASP; En la segunda parte veremos ms a fondo algunas de las caractersticas de PHP con las que tendremos que trabajar. Por ltimo, enumeraremos algunas caractersticas ms de PHP que nos hemos dejado en el tintero.
2. El lenguaje PHP
PHP es bastante diferente en su sintaxis a ASP. ASP est basado en VBScript, mientras que PHP toma bastantes caractersticas de lenguajes como C, C++ y Java, y algunas tambin de Perl. A continuacin analizaremos en detalle estas diferencias al tiempo que vamos introduciendo las bases de la programacin en PHP.
Aunque haya extensiones diferentes para PHP 3 y 4, no tienen efecto en el intrprete que las procesar IGUAL. En general, PHP 4 es compatible con 3, salvo unas pocas excepciones. Este curso se centra en PHP 4, as que no analizaremos estos casos de incompatibilidad con las versiones anteriores.
2.2. Delimitadores
El cdigo ASP se delimita dentro del HTML entre los signos '<%' y %>'. Por ejemplo: <%@ Language=VBScript %> <html> <body> <%IF Hour(time)>20 OR Hour(time)<4 THEN%> Buenas noches. <%ELSE%> Buenos das. <%END IF%> </body> </html> En PHP disponemos de cuatro opciones para delimitar el cdigo: <? echo 'Primer mtodo de delimitar cdigo PHP'; ?> <?php echo 'Segundo mtodo, el ms usado'; ?> <script language="php"> echo 'Algunos editores (como el FrontPage) Slo entienden este mtodo'; </script> <% echo 'Mtodo de compatibilidad con ASP'; %>
Los mtodos primero y cuarto no siempre estarn disponibles, ya que se pueden activar o desactivar al compilar el intrprete de PHP. En general, preferiremos usar el segundo mtodo. El ejemplo anteriormente expuesto en ASP podra traducirse as a PHP: <html> <body> <?php if ( Hour(time)>20 || Hour(time)<4) { ?> Buenas noches. <?php } else { ?> Buenos das. <?php }?> </body> </html> O tambin as, utilizando la funcin echo para imprimir cadenas de texto: <html> <body> <?php if ( Hour(time)>20 || Hour(time)<4) { echo Buenas noches.; } else { echo Buenos das.; } ?> </body> </html> Adems, se puede imprimir de forma rpida con <%=$var%>, al igual que en ASP.
2.4. Comentarios
En PHP hay tres formas de introducir comentarios en el cdigo, frente al ' de ASP: /* Comentarios estilo C. * Pueden extenderse durante varias lneas. */ 3
// Comentarios estilo C++. Cubren hasta el final de la lnea. # Comentarios estilo Bash/Perl. Cubren hasta el fin de lnea. Hay que hacer notar que los comentarios de una lnea cubren hasta final de lnea O HASTA EL FIN DEL BLOQUE PHP ('?>' o el que corresponda.)
2.5. Variables
Las variables son una parte fundamental de todo lenguaje de programacin. En ellas se almacenan valores con los que se puede operar, se pueden comparar entre s y se puede hacer variar el flujo del programa en funcin de su valor. Vamos a ver cmo trabajar con variables en PHP.
A pesar de esto, el tipo es importante en algunos casos (para efectuar operaciones o llamadas a funciones.) En estos casos, PHP se encarga de realizar las transformaciones necesarias de forma automtica. $mivar = 123; echo $mivar; En el ejemplo anterior, PHP convierte el valor entero 123 a la cadena de texto 123 antes de pasrselo a la funcin echo. $mivar = 3; $mivar = 2 + $mivar; En este caso $mivar comienza almacenando la cadena 3. En la segunda lnea, y para realizar la suma, se convierte al entero 3, se realiza la suma y se asigna a $mivar el entero 5.
Tambin se puede forzar la conversin a un tipo especfico, por ejemplo: $mivar = (string)123; Y se puede cambiar el tipo de una variable con: $mivar = 12; settype($mivar, "double");
2.5.3. mbito
El mbito de una variable hace referencia a dnde est disponible esa variable y dnde no, y depende del contexto en el que haya sido definida la variable: En el cuerpo de un fichero, las variables son GLOBALES al fichero y a cualquier cdigo que se haya incluido con los comandos include o require (explicados ms adelante.) En una funcin, son LOCALES a esa funcin y no pueden ser accedidas desde fuera. Dentro de una clase, slo pueden ser accedidas a travs del operador -> sobre el nombre del objeto (las clases se explicarn con detalle ms tarde.)
Aunque todos estos conceptos (includes, funciones, clases) los presentaremos ms tarde, introduciremos ya una posible fuente de errores: Los programadores acostumbrados a C deben llevar cuidado con las variables globales, ya que no se comportan como en C. Por ejemplo, considrese el cdigo siguiente: $mivar = 3; function mifuncion() { echo $mivar; } En C, la funcin mifuncion() imprimira '3'. En cambio en PHP no imprimira nada (si no da un error) ya que la variable $mivar de mifuncion es una variable DISTINTA a la global y local a esta funcin. Para acceder a las variables globales desde una funcin, hay que utilizar la palabra reservada global: $mivar = 3; function mifuncion() { global $mivar; echo $mivar; }
2.5.4. Referencias
En PHP se puede definir alias para las variables, es decir, tener dos (o ms) nombres distintos para un mismo dato. Se puede ver de forma similar a tener dos punteros en C haciendo referencia a la misma zona de memoria. Para definir una referencia utilizamos el carcter & delante de la variable referenciada: $alias = &$variable
As podremos acceder al mismo dato por $alias o $variable . Las modificaciones hechas sobre una u otra repercuten en el mismo dato. Debe quedar claro que la referencia no significa que $alias apunta a $variable , si no que tanto $alias como $variable apuntan a un mismo contenido en memoria. Se puede eliminar una referencia con la funcin unset(): $a = 1; $b = &$a; unset ($a); // Pero $b sigue valiendo 1 Las referencias tambin se pueden usar para pasar o devolver parmetros por referencia en las funciones, como se ver ms tarde.
El tamao, representacin interna y valores mximos dependen aunque lo normal son 32 bits con signo (+- 2 billones.)
Internamente se representan mediante 64 bits en formato IEEE (hasta 1.8e308 con una precisin de 14 dgitos decimales.)
Los arrays de PHP admiten tambin cadenas como ndices, de forma simultnea a los enteros. Un mismo array puede funcionar a la vez de forma indexada (como un vector) o de forma asociativa (como una tabla hash): $MiArray[nombre] = Homer; echo $MiArray[3]; echo $MiArray[nombre]; // 8 // Homer
Para definir un array multidimensional, simplemente indicamos ms ndices: $MiOtroArray[1][2][pepe][0] = 4 dimensiones!!!; Tambin podemos definir arrays utilizando los constructores del lenguaje array() o list(), as: $OtroArrayMas = array( 1, hola, 5); Donde los valores se asignan por orden a los ndices 0, 1 y 2, o de esta otra forma, donde indicamos explcitamente el ndice: $YOtroArray = array( 0 => 1, 1 => hola, 2 => 5, 3 => 8, nombre => Homer ); Se pueden definir arrays multidimensionales llamadas anidadas al constructor array(). mediante composicin de varias
Un carcter determinado en notacin octal \x[0-9A-Fa-f]{1,2} El carcter indicado en hexadecimal Si se delimitan entre comillas simples (), las variables no se expanden y adems las nicas secuencias de escape que se reconocen son \\ y \' (barra invertida y comillas simples.) Debido a estas limitaciones, este segundo mtodo es bastante ms rpido que el primero a la hora de manipular o imprimir cadenas, ya que el anlisis y proceso al que son sometidas las es menor. Utilizando la sintaxis here doc de Perl, cuya estructura es: $cadena = <<<DELIMITADOR texto texto texto ... texto DELIMITADOR Despus del operador <<< especificamos un delimitador que marcar el final del texto. Debemos llevar cuidado al elegir este delimitador, ya si aparece en algn lugar del texto, podramos acabar con un resultado incorrecto. Tras la lnea con el <<< y el delimitador, escribimos la cadena de texto, que puede expandirse por tantas lneas como queramos. Las variables dentro del texto se expanden y no hace falta escapar las comillas. Para finalizar la cadena, debe aparecer una lnea que contenga nicamente el delimitador. Por ejemplo: $cadena = <<<FINCAD Esto es un ejemplo de cadena como here doc. La variable \$a vale $a. Ahora vamos a finalizar la cadena: FINCAD Para concatenar cadenas se utiliza el operador . : $cad = A esta cadena ; $cad = $cad . le vamos a aadir ms texto.;
Se puede acceder a cada carcter de la cadena de forma independiente utilizando notacin de arrays indexados sobre la cadena: $cad2 = El tercer carcter de \$cad es $cad[2].; Por ltimo, sealar que aunque como ya hemos dicho en una cadena delimitada por dobles comillas se expanden las variables, con construcciones complejas (arrays multidimensionales, objetos...) la expansin NO siempre funciona bien. Para evitar problemas, podemos concatenar la cadena con el valor de la variable o encerrar la variable entre llaves: echo Esto no ir bien $a[1][3]; echo As no hay problemas {$a[1][3]}; echo Concatenar es otra alternativa . $cosa->valor;
2.7. Constantes
En PHP podemos definir constantes utilizando la funcin define(), cuya declaracin es: int define(string nombre, mixed valor [, int noMayusculas]) Donde nombre es el nombre que le queremos dar a la constante, valor su valor, y el campo opcional noMayusculas indica si est a 1 que podemos acceder a la variable independientemente con maysculas o minsculas, mientras que si est a 0 (valor por defecto) slo podremos acceder a ella de la misma forma como la hayamos definido. Las constantes en PHP se diferencian de las variables en que: no llevan el smbolo del dlar delante. puede accederse a ellas desde cualquier parte del cdigo donde han sido definidas, sin restricciones de mbito como en las variables. no pueden ser redefinidas o borradas una vez definidas. slo pueden contener valores escalares, no vectores. Un ejemplo de declaracin y uso de constantes en PHP sera: define(SALUDO, Hola, mundo!); echo La constante SALUDO vale . SALUDO;
En los nombres de funciones y palabras reservadas, las maysculas NO IMPORTAN. La funcin PRINT() hace referencia a print().
Para evitar errores y confusiones, siempre escribiremos los nombres de funciones del sistema en minscula, y las funciones propias siemp re tal y como se escribieran en la declaracin.
2.9. Operadores
Vamos a ver los distintos operadores disponibles en PHP, clasificados por tipos:
Por si alguien no est familiarizado con el funcionamiento de estos operadores, he aqu un ejemplo para clarificarlo: $a = 1; $b = $a++; $a = 1; $b = ++$a;
10
Resultado Se invierten los bits (se cambian 1 por 0 y viceversa.) Desplaza $b posiciones a la izquierda todos los bits de $a.
La razn de que haya dos operadores distintos para las operaciones Y y O lgicas es que tienen distinta precedencia (ver punto 2.8.9.)
Los programadores acostumbrados a ASP deben llevar mucho cuidado con esto, ya que puede llevar a errores de este tipo: $var1 = 1; $var2 = 2; if( $var1 = $var2 ) { echo iguales; } else { echo distintas; }
11
Esta condicin en ASP se evaluara a FALSO. En cambio, en PHP como = es el operador de ASIGNACIN y no el de IGUALDAD, lo que estamos haciendo es asignar el valor de $var2 a $var1. Tras esto $var1 vale 2, que como es distinto de 1 se evaluar a CIERTO.
2.9.6. Comparaciones
Devuelven cierto o falso segn el resultado de comparar los dos operandos. Operacin Nombre $a != $b No igual Resultado Cierto si el valor de $a no es igual al de $b. Cierto si $a no es igual a $b, o si no tienen el mismo tipo. Cierto si $a es estrictamente menor que $b. Cierto si $a es estrictamente mayor que $b. Cierto si $a es menor o igual que $b. Cierto si $a es mayor o igual que $b.
$a !== $b No idntico $a < $b $a > $b $a <= $b $a >= $b Menor que Mayor que Menor o igual que Mayor o igual que
La principal diferencia con ASP aqu es que para expresar la desigualdad, en PHP se utilizan != y !== mientras que en ASP se utiliza <>. Tambin se puede englobar aqu el operador condicional ?:, que funciona como en C y otros lenguajes: (expr1) ? (expr2) : (expr3); Esta expresin devuelve expr2 si expr1 se evala a cierto, o expr3 si expr1 se evala a falso. Por ejemplo: $cad = $a > $b ? a es mayor que b : a no es mayor que b;
12
+ - * / % & ^ . >> y << resultando en los nuevos signos de operacin-asignacin: += -= *= /= %= &= ^= .= >>= y <<= Ejemplos de uso: $var1 += 3; // $var1 = $var1 + 3; $var2 /= 2; // $var2 = $var2 / 2; $var3 >>= 1; // $var3 = $var3 >> 1;
y adems algunas otras estructuras ms tpicas de lenguajes interpretados como Perl o Bash. En todos los casos, las estructuras de control contienen una expresin cuya evaluacin a cierto o falso determinar el flujo a seguir dentro de la estructura. Estas expresiones pueden ser una variable, una funcin (el valor que devuelve), una constante, o cualquier combinacin de stas con los operadores vistos en el punto anterior.
14
comandos3 } ... elseif (expresionN) { comandosN } else { comandosElse } El flujo del cdigo comienza evaluando expresin1. Si es cierta, ejecuta comandos1. Si no, evala expresin2. Si es cierta, ejecuta expresin2. Si no, evala expresin3... y contina as hasta que alguna de las condiciones de un endif se verifique. Si no se verifica ninguna, se ejecuta comandosElse (este ltimo else es optativo.) En cualquier caso, despus se contina con el flujo normal del programa.
La estructura do .. while puede ser vista como una variante de while en la que la comprobacin de la condicin se realiza al final de cada iteracin del bucle en lugar de al principio. Con esto lo que se consigue es que al menos la iteracin se realice siempre una vez, aunque expresin se evale a falso. La estructura de do .. while es esta: do { comandos } while (expresin);
15
} $a++; } Despus del break podemos especificar un parmetro, el nmero de niveles de bucles anidados de los que queremos salir. Por defecto es uno (salir del bucle ms interno) : $a = 0; while ($a < 10) { $b = 0; while ($b < 5) { if ($b == 2) { break; // Equivale a break 1, sale del while b } } while ($b < 5) { if ($a == 3 && $b == 3) { break 2; // Saldra de los DOS bucles. } } } Por su parte, la sentencia continue lo que hace es saltarse el resto de la iteracin actual, y pasar directamente a la siguiente: $a = 0; while ($a < 5) { if ($a == 2) { continue; } echo \$a vale $a.; } En el ejemplo se saltara el echo de la iteracin $a = 2, y el resultado sera: $a $a $a $a vale vale vale vale 0 1 3 4
2.10.4. for
Los bucles for son los ms complejos de que dispone PHP, bastante ms que sus homnimos de ASP. Su estructura es la misma que en C: for (expresin1; expresin2; expresin3) { comandos } donde: expresin1 es la iniciacin del bucle. Generalmente da un valor inicial a una o varias variables (separadas por comas). Slo se ejecuta una vez, al principio, cuando el flujo del programa llega al bucle.
16
expresin2 es la condicin. Mientras que expresin2 se evale a cierto, el bucle estar iterando. Se evala al inicio de cada iteracin, y si no se verifica la condicin la siguiente iteracin ya no se realiza y finaliza el bucle, continuando la ejecucin del programa con el resto del cdigo de despus del for. expresin3 es el paso de iteracin. Se ejecuta despus de cada iteracin, y generalmente modifica el valor de alguna variable (separadas por comas si hay ms de una).
Cualquiera de las tres expresiones puede estar vaca, aunque en este caso tendremos que llevar cuidado de realizar su funcin en el cuerpo del bucle. Ejemplos: $factorial5 = 1; for ($i = 2; $i <= 5; $i++ ) { $factorial5 *= $i; } El bucle anterior calcula la factorial de 5 (5!). En expresin1 podemos inicializar varias variables separndolas con comas, con lo que el cdigo se podra rescribir as: for ($factorial5 = 1, $i = 2; $i <= 5; $i++ ) { $factorial5 *= $i; } Por ltimo, en expresin3 tambin podemos operar sobre varias variables separndolas con comas, con lo que podramos encerrar todo el cdigo del bucle en la lnea for de esta forma: for ($factorial5=1, $i=2; $i<=5; $factorial5*=$i, $i++); En general no se debe complicar tanto un bucle for porque como se ve se pierde bastante en la claridad del cdigo. Esto es un ejemplo tanto de la potencia de los bucles for, como de un mal uso (abuso) de ellos. Los cuatro ejemplos siguientes tienen el mismo resultado: muestran los nmeros del 0 al 10. /* ejemplo 1 */ for ($i = 1; $i <= 10; $i++) { print $i; } /* ejemplo 2 */ for ($i = 1;;$i++) { if ($i > 10) { break; } print $i; } /* ejemplo 3 */ $i = 1;
17
for (;;) { if ($i > 10) { break; } print $i; $i++; } /* ejemplo 4 */ for ($i = 1; $i <= 10; print $i, $i++) ; De nuevo, algunos d e estos ejemplos (en especial el ltimo) no lo son de buenas costumbres de programacin, pero s de la potencia y flexibilidad del bucle for. Como hemos visto, el bucle for de PHP es MUCHO ms potente que el de ASP, as que no debera haber problemas a la hora de pasar bucles de este tipo de ASP a PHP. Valga como ejemplo: ASP <%FOR i=1 TO 100%> <%=MiVar%> <%NEXT%> // PHP <?php for ($i = 1; $i <= 100; $i++) { echo $MiVar; } ?>
2.10.5. foreach
El bucle foreach es nuevo en PHP4, y representa una estructura de control tpica de lenguajes interpretados como Perl y Bash, en la que a una variable se le van asignando todos los valores de una lista. Su sintaxis es esta: foreach (array as $variable) { comandos } Es equivalente al FOR EACH .. NEXT de ASP. En cada iteracin del bucle, se coloca en $variable un elemento de array, comenzando por el primero y siguiendo un orden ascendente. Por ejemplo: $a = array (1, 2, 3, 17); foreach ($a as $v) { print "Valor actual de \$a: $v.\n"; } El resultado sera: Valor Valor Valor Valor actual actual actual actual de de de de $a: $a: $a: $a: 1 2 3 17
18
2.10.6. switch
La estructura switch de PHP es equivalente al SELECT CASE de ASP. Su sintaxis es: switch (variable) { case valor1: comandos1 case valor2: comandos2 ... case valorN: comandosN default: comandosDefault } El flujo procede linealmente de arriba a abajo, comparando con cada valor de los case, y ejecutando el cdigo asociado si se cumple la condicin. En caso de que no se cumpla ninguna, se ejecuta el cdigo asociado a la clusula default . El comportamiento sera similar a tener un if por cada case , uno detrs del otro. Hay que destacar como diferencia respecto a ASP que cuando se termina de ejecutar el cdigo de un case , si no se finaliza el switch explcitamente con un break, se contina ejecutando el cdigo del siguiente case aunque no se cumpla la condicin, hasta que se llegue al final del bloque switch o se finalice este con un break. Por ejemplo: switch ($i) { case 1: echo Cdigo del 1; case 2: echo Cdigo del 2; case 3: echo Cdigo del 3; break; case 4: echo Cdigo del 4; } Si $i vale 1, se imprimirn las tres primeras cadenas; Si v ale 2, la segunda y la tercera; Si vale 3, slo la tercera; Y si vale 4, slo la ltima. Otro ejemplo del funcionamiento del switch, ahora con una clusula default : switch ($i) { case 0: case 1: case 2: case 3: echo i es menor que 4, pero no negativa; break; case 4: echo i vale 4; break; default: 19
Para cadenas de texto, una cadena vaca equivale a FALSO, una cadena no vaca a CIERTO. $x = "hello"; if( $x ) $x = ""; if( $x ) // // // // asignamos una cadena a $x se evala a cierto cadena vaca evala a falso
NOTA: $x = 0 es la nica excepcin, ya que primero se convierte la cadena 0 al decimal 0, que como ya hemos visto se evala a FALSO. Para arrays: un array vaco se evala a FALSO, mientras que si tiene algn elemento lo hace a CIERTO. $x = array(); // $x es un array vaco if( $x ) // se evala como falso $x = array( "a", "b", "c" ); if( $x ) // se evala a cierto Para objetos, el resultado de la evaluacin es FALSO si son objetos vacos (su clase no define ningn mtodo ni variable), y CIERTO en otro caso. Class Yod {} // $x = new Yod(); if( $x ) // Class Yod { // var $x = 1; } $x = new Yod(); if( $x ) // clase vaca se evala a falso clase no vaca
PHP tiene definidas dos constantes para los valores CIERTO respectivamente TRUE y FALSE. Estn definidas de esta forma: TRUE es el valor entero decimal 1. FALSE es la cadena vaca.
20
Es indiferente si se escriben en maysculas o minsculas, es decir, true, True y tRuE hacen referencia a la misma constante TRUE. Para evitar confusiones, escribiremos estas constantes siempre en maysculas. Como regla general a utilizar al principio hasta que nos acostumbremos al funcionamiento de PHP, podemos tener en mente esta regla que funciona el 99% de las veces: el valor 0 y la cadena vaca se evalan a FALSO, cualquier otra cosa a CIERTO.
2.12. Funciones
Las funciones de PHP seran el equivalente a los procedimientos SUB y FUNCTION de ASP. Con una funcin podemos agrupar bajo un nombre una serie de comandos que se repiten a menudo a lo largo del cdigo, y en vez de repetir este cdigo varias veces lo sustituimos por una simple llamada a la funcin. La sintaxis de la declaracin de una funcin en PHP es: function nombre ($arg_1, $arg_2, ..., $arg_n) { comandos return $salida; } Los parmetros se pasan por valor, es decir, se crea en $arg_1 ... $arg_n copias locales de las variables, y se trabaja sobre estas copias locales, de forma que al salir de la funcin los valores originales no han sido modificados. El comando return es opcional, y sirve para que la funcin devuelva un valor de salida. Es el equivalente a asignar un valor al nombre de la funcin en ASP. Puede aparecer varias veces en el cdigo de la funcin, y siempre implica la final de la ejecucin de la funcin. En el cuerpo de la funcin puede haber cualquier combinacin de instrucciones vlidas en PHP, incluso otras definiciones de funciones y / o clases. Por ejemplo: function factorial ($valor) { if ($valor < 0) { return 1; // Error } if ($valor == 0 ) { return 1; } if ($valor == 1 || $valor == 2) { return $valor; } $ret = 1; for ($i = 2; $i <= $valor; $i++) { $ret *= $i; } return $ret; } $factorial5 = factorial(5); En PHP 3 era necesario definir las funciones antes de usarlas, como en el ejemplo de arriba. Esta restriccin se ha eliminado en PHP 4, donde ya se puede utilizar una funcin antes de su declaracin. 21
PHP no soporta sobrecarga de funciones (tener varias funciones con el mismo nombre y distintos argumentos), ni tampoco se puede eliminar o modificar una funcin previamente definida. Lo que si se puede hacer es dar valores por defecto a algunos de los parmetros que reciba la funcin (comenzando siempre por la derecha) y hacerlos as optativos: function enlace($url = www.php.net) { echo <a href= . $url . >Pulsa aqu</a>; }
22
cdigo en todos los ficheros que lo necesiten, se pone en un fichero que es incluido por el resto. Entontes, por qu tener dos funciones distintas para hacer lo mismo? Principalmente por dos motivos: Optimizacin de los accesos a disco: Imagnese un cdigo en el que dependiendo de una serie de condiciones, se deba incluir o no otros ficheros. Con require se cargaran TODOS los ficheros SIEMPRE. Con include, nicamente aquellos que se vayan a utilizar. Flexibilidad. Con include podemos acceder a ficheros cuyo nombre tenemos en una variable que podemos ir cambiando en tiempo de ejecucin, mientras que con require siempre se accede al mismo fichero.
Tambin existen las funciones include_once y require_once, que nos aseguran que un determinado fichero slo ser procesado una vez, en caso de que en sucesivos includes vuelva a aparecer.
23
3. Programando en PHP
En esta segunda parte del curso, una vez ya tenemos una idea general de cmo se programa en PHP, vamos a olvidarnos de ASP ya estudiar con ms detalle algunas de las funciones de PHP que probablemente tendremos que usar con mayor frecuencia.
3.1. Forms
Trabajar en PHP con forms es muy fcil, ya que el propio lenguaje se encarga de crear automticamente las variables necesarias para almacenar los datos del form en la pgina que los recibe. Vamos a ver algunos ejemplos:
24
Y podemos ver el resultado con este cdigo: <?php echo "Su eleccin:<br>"; foreach($menu as $plato) { echo "$plato<br>\n"; } ?>
3.2. Cookies
En PHP podemos almacenar datos en una cookie utilizando la funcin setcookie(): int setcookie (string nombre [, string valor [, int fin [, string camino [, string dominio [, int seguro]]]]]) Como las cookies forman parte de los headers, esta funcin DEBE ser llamada ANTES de realizar cualquier salida de texto, incluso antes de los tags <html> y <head>. El parmetro fin indica la fecha de expiracin de la cookie y se expresa en formato UNIX (como las funciones de PHP time() y mktime()). El parmetro seguro fuerza a que la cookie slo sea enviada a travs de una conexin segura (HTTPS). Los campos optativos de tipo string se pueden omitir poniendo , y los numricos con 0. Por ejemplo, para definir una cookie llamada PruebaCookie con el valor expirar dentro de una hora y que, en efecto, expire en una hora, tendramos que hacer: setcookie(PruebaCookie, expirar dentro de una hora, time() + 3600); La prxima vez que se cargue la pgina, PHP definir una variable global llamada PruebaCookie con el valor definido para sta. Para borrar la cookie del ejemplo anterior (hay que indicar los mismos parmetros que se usaron para definirla): setcookie(PruebaCookie, , time());
3.3. Sesiones
Para iniciar el seguimiento de una sesin, llamamos a la funcin session_start(): bool session_start(void); Si ya haba una sesin (almacenada en una cookie o pasada por GET), la contina. Si no, crea una nueva. Una vez que hemos iniciado el tratamiento de sesiones, podemos registrar variables en la sesin con session_register(): bool session_register (mixed name [, mixed ...]) Podemos registrar en una llamada a session_register() tantas variables como queramos.
25
Con estas funciones tenemos la misma restriccin que con las cookies: deben llamarse antes de realizar cualquier tipo de salida de texto. Por ejemplo, para implementar un contador del nmero de veces que un usuario visita una pgina, podramos hacer: session_start(); print($contador); $contador++; session_register("contador"); Para finalizar una sesin, llamamos a session_destroy(): bool session_destroy(void); Esta funcin finaliza la sesin actual, es decir, debe ser llamada siempre despus de session_start(). El identificador de la sesin se pasa por defecto mediante cookies. Si estas estn desactivadas en el cliente, tendremos que pasarlo como una variable GET. PHP define la constante SID con el Session ID actual, de forma que para pasarlo por GET podemos hacer: <A HREF="siguiente_pagina.php?<?=SID?>">Continuar</A> Para ms informacin sobre las funciones de manejo de sesiones disponibles en PHP, est la pgina del manual: http://www.php.net/manual/ref.session.php
26
3.5.1. Comparaciones
Para comparar cadenas ya hemos visto que podemos utilizar los operadores == y ===, aunque tambin disponemos de la funcin strcmp() con el mismo funcionamiento que en C: int strcmp (string str1, string str2) La funcin devuelve 0 si ambas cadenas son iguales, un nmero menor que cero si $a es menor que $b, y mayor que cero si $a es mayor que $b. Adems, siempre que la cadena contenga algn carcter binario deberemos utilizar esta funcin en lugar del operador ==. Por ejemplo: if (strcmp($a, $b) == 0) { echo iguales; } La funcin strcmp tiene en cuenta maysculas y minsculas. Si queremos comparar sin tenerlas en cuenta, usaremos strcasecmp : int strcasecmp (string str1, string str2)
3.5.2. Subcadenas
Otra operacin que podramos necesitar es obtener una subcadena de otra dada. Esto se consigue con: string substr (string cadena, int inicio [, int tamao]) Si inicio es positivo, devuelve la subcadena que empieza en esa posicin. Si es negativo, la subcadena que empieza en esa posicin contando desde el final. Si se indica el tamao, se devuelve una subcadena de hasta ese nmero de caracteres. Si el tamao es negativo, se elimina ese nmero de caracteres de la subcadena devuelta: $str $str $str $str = = = = substr('abcdef', substr('abcdef', substr('abcdef', substr('abcdef', 2, 3); -2); -2, 1); 1, -2); // // // // cde ef e bcd
En ocasiones puede que no sepamos la posicin exacta en la cadena de lo que andamos buscando, pero si una serie de caracteres de referencia que marcarn su inicio. Entonces podremos usar estas funciones: int strpos (string cadena, string referencia [, int inicio])
27
int strrpos (string cadena, char referencia) string strstr (string cadena, string referencia) La primera funcin devuelve el ndice de la primera ocurrencia de la cadena referencia en cadena a partir de la posicin inicio . La segunda funcin es similar pero aqu referencia es un carcter en lugar de una cadena (si se pasa una cadena slo se usar el primer carcter), y se busca desde el final de la cadena. Por ltimo, la tercera funcin devuelve la subcadena de cadena que comienza en la primera ocurrencia de referencia . $i = strpos('cadena de prueba', 'de'); // $i = 2 $i = strpos('cadena de prueba', 'de', 5); // $i = 7 $s = strrpos('cadena de prueba', 'de'); // $i = 7 $s = strstr('cadena de prueba', 'de'); // $s = dena de prueba
28
Ejemplos: printf(%02d/%02d/%04d, $dia, $mes, $ao); $pago1 = 68.75; $pago2 = 54.35; $pago = $pago1 + $pago2; // echo $pago mostrar "123.1" // Mostrar al menos un dgito entero y exactamente dos // decimales, rellenando con ceros printf ("%01.2f", $pago); Tambin podemos almacenar el resultado del formateo en una cadena en lugar de imprimirlo con la funcin sprintf(): string sprintf (string formato [, mixed args...]) El formato es el mismo que con printf: $fecha = sprintf(%02d/%02d/%04d, $dia, $mes, $ao); Estas dos funciones son muy tiles a la hora de dar un formato especfico a unos datos, pero se debe de huir de ellas cuando este formato no sea importante o simplemente no se est realizando ningn formateo, ya que es mucho ms rpido imprimir con echo o concatenar cadenas con el operador ..
29
detener Apache. Para evitar esto habra que aplicar esta funcin sobre los datos que recibamos del form: string escapeshellcmd (string comando) que se encarga de escapar con barras los caracteres que se podran usar en el shell de UNIX para ejecutar un programa sin nuestro permiso (en concreto, #&;'\"|*?~<>^()[]{}$\\\x0A\xFF). Adems de por razones de seguridad, tambin necesitaremos a veces cambiar unos caracteres por otros para formatear correctamente un texto en HTML. Esto lo hace la funcin htmlspecialchars(): $valor = a>b; echo <input type=hidden name=var value= . htmlspecialchars($valor) . >; // <input type=hidden name=var value=a>b> Podemos tambin convertir todos los caracteres de fin de lnea de una cadena a <br> con: string nl2br (string cadena)
30
Por ejemplo, para obtener los campos de una fecha donde el da, mes y ao puedan estar separados por espacios, barras, guiones o puntos, tendramos que utilizar split as: $fecha = "12/4 2000"; $campos = split ('[ /.-]', $fecha);
Este puntero al elemento actual del que estamos hablando tambin se utiliza en los bucles foreach y se actualiza en cada iteracin.
31
Esta funcin elimina espacios del principio y final de la cadena. Tambin se puede usar ltrim y rtrim , que los eliminan slo del inicio y slo del final, respectivamente. Podemos convertir una cadena a maysculas con: string strtoupper (string cadena) Y a minsculas con: string strtolower (string cadena) Tambin puede ser til convertir a maysculas t an slo el primer carcter de la cadena, por ejemplo si estamos construyendo frases. Esto se consigue con: string ucfirst (string cadena)
3.5.7. Ms informacin
Para ms informacin sobre todas las funciones de strings y arrays disponibles en PHP, ver las pginas de manual: Funciones de strings http://www.php.net/manual/ref.strings.php Funciones de arrays http://www.php.net/manual/ref.array.php
32
'a+' Modo lectura/escritura. Se coloca el puntero al final del fichero. Si no existe se crea.
Si el ltimo parmetro se pone a 1, se buscar los ficheros adems de en el directorio actual en el indicado en la opcin de configuracin include_path en php.ini. La funcin devuelve un identificador para usar con el resto de funciones, o FALSE si ha habido un error. Para cerrar el fichero, se usa fclose() con el identificador devuelto por fopen(): int fclose (int identificador)
33
int rename (string origen, string destino) o borrarlo con: int unlink (string fichero)
3.6.4. Directorios
Para movernos a otro directorio, tenemos la funcin chdir(): int chdir (string directorio) Para crear un directorio llamaremos a mkdir(): int mkdir (string nombre, int modo) donde modo indica los permisos (en formato UNIX). Y para borrar directorios: int rmdir (string nombre) Si queremos saber qu ficheros hay dentro de un directorio (como hacer un dir en DOS o un ls en UNIX), tenemos que usar las funciones opendir() para abrirlo, readdir() para ir viendo los contenidos y closedir() para cerrarlo. Estos son los formatos de estas funciones: int opendir (string nombre) string readdir (int identificador) void closedir (int identificador) Por ejemplo, para mostrar la lista de ficheros en el directorio actual, tendramos que hacer algo as: $direcotrio = opendir('.'); while (($fichero = readdir($directorio)) !== FALSE) { echo "$fichero\n"; } closedir($directorio);
$fichero: El fichero temporal donde se ha almacenado el fichero. $fichero_name: El nombre original que tena el fichero en el sistema del cliente. $fichero_size: Tamao del fichero. $fichero_type: El tipo mime del fichero, si el navegador del cliente dio la informacin.
En el script que recibe el fichero se deber implementar toda la lgica necesaria para ver qu se hace con el fichero, ya que al finalizar su ejecucin el fichero temporal se borra del sistema. Por ejemplo, podramos decidir simplemente almacenar el fichero en el directorio actual, para lo que podramos utilizar este cdigo: echo Recibido el fichero: " . $fichero_name . "<br>; echo Tamao del fichero: . $fichero_size . <br>; echo Tipo mime: . $fichero_type . <br>; rename($fichero, $fichero_name);
35
Una de las carencias de las clases de PHP es que no se puede restringir el acceso a las variables y mtodos. En los LOO puros, hay una serie de palabras reservadas (p.ej., public , private y protected en C++) para indicar si a una variable o mtodo es pblico y se puede acceder desde fuera, o si es privado y slo se puede acceder de forma interna desde otros mtodos de la propia clase o sus derivadas (protegido). Para acceder a las variables y mtodos de un objeto, tanto desde fuera como desde un mtodo del propio objeto, hay que utilizar el operador ->, sobre el nombre de la variable que almacena el objeto si accedemos desde fuera ($miCasa->telefono), o sobre la referencia al propio objeto $this si es desde dentro ($this->telefono.) Existe una clase especial de mtodos, llamados constructores , que se llaman igual que la clase y se invocan de forma automtica al crear un objeto. Estos constructores se encargan de inicializar los valores de las variables internas, reservar memoria, crear estructuras de datos que se vayan a utilizar despus... Los constructores pueden tener o no tener parmetros, que habr que pasar en la creacin del objeto. Como ejemplo, vamos a definir una clase coche : class Coche { var $velocidad; // Velocidad actual // Constructor por defecto. El coche est parado. function Coche() { $this->velocidad = 0; } // Constructor que indica la velocidad inicial. function Coche($vel) { $this->velocidad = $vel; } // Mtodo acelerar. El coche va ms rpido. function acelerar() { $this->velocidad++; } // Mtodo frenar. El coche va ms lento hasta frenar. function frenar() { if ($this->velocidad > 0) { $this->velocidad--; } } }
3.7.2. Herencia
Otra de las caractersticas ms importantes de la POO junto con la encapsulacin es la herencia, por la que se pueden definir clases derivadas de otras ya existentes. Estas clases derivadas (subclases) heredan todas las caractersticas (variables) y funcionalidad (mtodos) de sus clases madres (superclases). Es una forma de ir especializando el tipo de cada clase, partiendo de una clase muy genrica hasta las herederas ms especficas.
36
Para definir una clase en funcin de otra, se usa la palabra reservada extends en la definicin de la subclase. De esta forma, la clase heredera parte ya con todas las variables y mtodos de su superclase, y adems podr aadir tantas variables y mtodos como quiera e incluso redefinir algn mtodo en el proceso de especializacin de las clases. Vamos a definir una subclase de coche llamada cocheFantastico, que ser capaz de hablar, saltar, poner el turbo y que adems en lugar de frenar poco a poco frenar de golpe: class CocheFantastico extends coche() { // Frenado instantneo function frena() { $this->velocidad = 0; } // El coche habla! function habla() { echo Hola, Michael.; } // Salta! function salta() { echo Boing!!; } // Turbo propulsin function turbo() { $this->velocidad = 200; } } IMPORTANTE: si se redefinen los constructores, el de la superclase NO SE LLAMA AUTOMTICAMENTE al llamar al de la subclase.
37
38
$link = mysql_connect ("www.mmlabx.ua.es", "nobody", ""); if (!$link) { die ("No se pudo conectar"); } print ("Conexin realizada"); mysql_close ($link); Con algunas BD tambin se pueden usar enlaces persistentes que no se cerrarn automticamente al acabar la ejecucin del fichero, si no que permanecern abiertos y se podrn utilizar desde los siguientes ficheros .php que se ejecuten. Estos enlaces se abren y cierran con mysql_pconnect y mysql_pclose. Su definicin es idntica a la de connect y close: int mysql_pconnect ([string servidor [:puerto][:/camino/al/socket] [, string usuario [, string contrasea]]]) int mysql_pclose ([int identificador])
3.8.3. Interrogar a la BD
Para hacer querys a una BD se utiliza mysql_query: int mysql_query (string query [, int identificador]) En query va la sentencia en SQL que queremos ejecutar. Al igual que con mysql_select_db, si se omite el identificador se usa el ltimo o se trata de crear. Esta funcin devuelve FALSE si ha habido un error, o un valor no negativo (TRUE) que identifica el resultado y que ms tarde deber ser tratado para extraer la informacin necesaria. Para obtener la informacin de las asignaturas en la BD de ejemplo: $query = "SELECT codigo, nombre, descripcion, creditos, tipo FROM asignatura"; $asignaturas = mysql_query($query, $link); if (!$asignaturas) {
39
die (Error en el query); } Tambin podemos utilizar esta otra funcin, en la que adems del query indicamos la BD a la que queremos interrogar: int mysql_db_query (string nombre_bd, string query [, int identificador]) Cuando hayamos acabado con el resultado, podemos liberar memoria con: int mysql_free_result (int result) aunque realmente no es necesario ya que el recolector de basura de PHP se encargar de liberarla al acabar la ejecucin del fichero actual.
40
Otra funcin que podemos utilizar para obtener los resultados de un query es mysq_fetch_object: object mysql_fetch_object (int result) que en lugar de almacenar el resultado en un array, lo almacena en un objeto cuyas propiedades (variables) coinciden con los nombres de las columnas: while ($fila = mysql_fetch_object($asignaturas)) { echo $fila->codigo . . $fila->nombre . \n; } Si queremos saber el tamao de los campos de la ltima fila devuelta por mysql_fetch_array, object o row, tenemos: array mysql_fetch_lengths (int resultado) Esta funcin devuelve un array con tantos campos como columnas el ltimo resultado, con los tamaos de estas columnas. Por ltimo, podemos saltar directamente a una fila del resultado, o rebobinar una vez hemos llegado al final, con la funcin mysql_data_seek. Las filas comienzan en el 0. int mysql_data_seek (int resultado, int numero_fila)
<?php /* * Clase base para definir una conexin genrica a una BD desde PHP. * Se debern definir clases que hereden de esta redefiniendo sus mtodos * para cada BD a la que queramos acceder. * * * 7/9/2000 */ /** * CLASE ConexionGenerica *
41
* Esta clase es una plantilla para definir la estructura bsica (variables * y mtodos) de todas las clases para conectar a distintas BBDD que ms * tarde heredarn de esta, redefiniendo los mtodos. */ class ConexionGenerica { /** El enlace con la BD */ var $link; /** * Constructor. No hace nada. Creo que se podra quitar ... */ function ConexionGenerica() {} /** * FUNCIN connect( servidor, usuario, clave ) * Conecta con el servidor, identificndose como usuario y clave. * No hace nada, debe ser redefinida por las clases que hereden de esta. */ function connect($servidor, $usuario, $clave) { echo "<h1>El método <i>connect</i> no está " . "implementado en la clase <i>" . get_class($this) . "</i></h1>"; return FALSE; } /** * FUNCIN close() * Finaliza la conexion con el servidor. * No hace nada, debe ser redefinida por las clases que hereden de esta. */ function close() { echo "<h1>El método <i>close</i> no está " . "implementado en la clase <i>" . get_class($this) . "</i></h1>"; return FALSE; } /** * FUNCIN select_db( base_datos ) * Elige la base de datos con la que trabajar. * No hace nada, debe ser redefinida por las clases que hereden de esta. */ function select_db($base_datos) { echo "<h1>El método <i>select_db</i> no está " . "implementado en la clase <i>" . get_class($this) . "</i></h1>"; return FALSE; } /** * FUNCIN query( query ) * Realiza una consulta o actualizacin en la BD. * No hace nada, debe ser redefinida por las clases que hereden de esta. */ function query($query) { echo "<h1>El método <i>query</i> no está " . "implementado en la clase <i>" . get_class($this) . "</i></h1>"; return FALSE; } /** * FUNCIN fetch_array( resultado ) * Realiza una consulta o actualizacin en la BD. * No hace nada, debe ser redefinida por las clases que hereden de esta. */ function fetch_array($resultado) { echo "<h1>El método <i>query</i> no está " . "implementado en la clase <i>" . get_class($this) . "</i></h1>"; return FALSE; } /** * FUNCIN free_result( resultado ) * Libera la memoria ocupada por un resultado. * No hace nada, debe ser redefinida por las clases que hereden de esta. */ function free_result($resultado) { echo "<h1>El método <i>free_result</i> no está " . "implementado en la clase <i>" . get_class($this) . "</i></h1>";
42
43
* Libera la memoria ocupada por un resultado. */ function free_result($resultado) { return mysql_free_result($resultado); } } ?>
Adems de estas dos clases, tenemos otro fichero CreaConexion.inc que es el encargado de crear el objeto de la clase que vayamos a usar:
<?php /** * CreaConexion * Crea una conexion (variable $conexion) con una base de datos. * * * * 7/9/2000 */ /* * Habra que cambiar estas dos lmneas segzn la BD a la que se quiera * acceder y la clase que se quiera utilizar para ello. */ require ("ConexionMySQL.inc"); $conexion = new ConexionMySQL(); ?>
Para acceder a una base de datos, tan slo tendremos que incluir este ltimo fichero y acceder a las funciones de las BD a travs de l, de esta forma:
<?php require ("CreaConexion.inc"); $conexion->connect("localhost", "nobody"); $conexion->select_db("prueba", $link); $asignaturas = $conexion->query("SELECT codigo, nombre, descripcion, creditos, tipo FROM asignatura"); ?>
44
45
http://www.php.net/manual/ref.mail.php Acceso a servidores de correo IMAP, POP3 y NNTP http://www.php.net/manual/ref.imap.php Acceso a servidores ICAP http://www.php.net/manual/ref.icap.php Acceso a servidores LDAP http://www.php.net/manual/ref.ldap.php Manejo de traducciones a diversos idiomas con GNU gettext http://www.php.net/manual/ref.gettext.php Generacin online de documentos PDF http://www.php.net/manual/ref.pdf.php Generacin de documentos Shockwave Flash http://www.php.net/manual/ref.swf.php Pago con tarjetas de crdito http://www.php.net/manual/ref.cybercash.php http://www.php.net/manual/ref.pfpro.php Correccin ortogrfica http://www.php.net/manual/ref.aspell.php http://www.php.net/manual/ref.pspell.php
La direccin de Zend en Internet es: http://www.zend.com Adems de informacin sobre sus productos, tiene bastantes tutoriales y artculos sobre PHP. 46