Anda di halaman 1dari 21

Tema 7 PHP: Server-Side Scripting

El Preprocesador de HiPertexto PHP tom su nombre inicialmente de una herramienta de paginas web personales (Personal Home Page) que a finales de 1994 usaba un miembro del Apache Group: Rasmus Lerdorf1. La usaba para sus propias pginas personales y a mediados de 1995, esta herramienta fue reescrita y nombrada PHP/FI versin 2. FI viene de otro programa que Rasmus haba escrito y que procesaba los datos de formularios. Aadi soporte para mSQL y creci a gran velocidad con la contribucin de otra gente. Cuando se estim que ya existan unas 50.000 pginas PHP repartidas por el mundo, dej de ser un proyecto personal de Rasmus y se convirti en un proyecto de grupo. Esto suceda a mediados de 1997. El analizador sintctico se reescribi desde el principio por Zeev Suraski y Andi Gutmans2 y este nuevo analizador estableci las bases para PHP versin 3. Gran cantidad de cdigo de PHP/FI fue portado a PHP3 y otra gran cantidad fue escrito completamente de nuevo. PHP3 pas a ser el Server-Side Script preferido por los usuarios de software gratuito ya que varias distribuciones de Linux y/o servidores web lo incluan o lo soportaban. A finales de 1999 ms de 1.000.000 de servidores del mundo usaban PHP. En la primavera del 2000, el PHP Group sac la esperada versin 4 con la nueva mquina de scripting Zend2 y muchos y variados mdulos que, por ejemplo, dan acceso a prcticamente todas las bases de datos y a muchos protocolos como IMAP o POP3.

7.1.

Qu es PHP?

PHP es un lenguaje de script que se ejecuta en el servidor, esto quiere decir que la peticin (pgina HTML) es procesada e interpretada por el servidor antes de ser enviada al cliente. Las ventajas de un script interpretado por el servidor estn: En el control que se pueda tener sobre el contenido en el propio sitio donde ste reside (independizndolo del navegador que lo vea). La posibilidad de gestionar foros, boletines, Webmail, o aplicaciones propias para intranet o extranet (Contabilidad, Personal, etc.) Gestin de base de datos. Etc.

Quizs entre las desventajas deberamos resaltar la imposibilidad de acceder a caractersticas propias del navegador que pudieran mejorar la interfaz de usuario, como por ejemplo, la validacin de campos en formularios. Pero nada nos impide que combinemos ambas estrategias, aprovechando lo mejor de cada una. En concreto, en el caso PHP es tambin ventajoso por ser gratis, adems de software abierto, popular, fcil de programar y muy extendido.

En la actualidad, Rasmus trabaja para IBM como Ingeniero senior de software.

Zeey y Andi crearon la compaa Zend Technologies que ahora se dedica a mantener la mquina de scripting de PHP (ver http://www.zend.com).

Tema 7. PHP: Server-Side Scripting

Una web ejemplar


Uno de los mejores ejemplos de uso de PHP lo encontramos en propia web del PHP Group:
http://www.php.net

En esta web podemos encontrar todo lo relacionado con PHP: Las pginas de descarga de las ltimas versiones. Documentacin en lnea o para descargar (la documentacin en castellano se encuentra en http://www.php.net/manual/es/manual.php). Bibliografa sobre el tema (http://www.php.net/books.php). Recomendable el libro de referencia de bolsillo escrito por el propio padre del PHP Ramus Lerdorf. Todos los enlaces de sitios con recursos y libreras PHP, sitios oficiales como el de Zend o relacionados con el tema como Apache, MySQL o PostgreSQL. Estadsticas sobre utilizacin (http://www.php.net/usage.php). Y lo mejor de todo, la posibilidad de ver el cdigo PHP de todas sus pginas (que es lo que literalmente la convierte en una web ejemplar).

7.2.

Empezando con PHP

El primer paso que debemos dar es el de descargarnos la ltima versin de PHP que tendramos que compilar adecuadamente para el sistema operativo con el que trabajamos. Para Win32 existe la posibilidad de descargar dos paquetes que incluyen directamente los binarios (ya compilados), uno de ellos incluye un instalador para configurar automticamente los servidores de Microsoft IIS y PWS. En nuestro caso, usando Apache, el ms conveniente es el que proporciona los binarios de Win32 sin instalador.

Instalacin
En la documentacin de PHP se da como propuesta para descomprimir el paquete el directorio C:/PHP, aunque por organizacin nosotros lo vamos a instalar en C:\Archivos de programa\PHP Group\PHP. Una vez descomprimido podremos probarlo directamente con:
C:\>"C:\Archivos de programa\PHP Group\PHP\php.exe" <? echo "hola" ?> ^Z

y procura no tardar ms de 30 segundos en escribir las dos ltimas lneas, porque sino, en vez de obtener la salida
Content-type: text/html hola

obtendrs esta otra:


Content-type: text/html <br> <b>Fatal error</b>: Maximum execution time of 30 seconds exceeded in <b>-</b> on line <b>n</b><br>

PHP puede instalarse como CGI o como mdulo, pero en el caso de la combinacin Win32 y Apache, hoy por hoy solo puede instalarse como CGI. Curiosamente para los servidores IIS y PWS de Microsoft s se puede utilizar directamente la DLL php4ts.dll como un mdulo.

Tema 7. PHP: Server-Side Scripting

Para instalarlo como CGI solo hay que aadir al fichero de configuracin del Apache (httpd.conf) las siguientes lneas:
AddType application/x-httpd-php .php AddType application/x-httpd-php .phtml ScriptAlias /php/ "C:/Archivos de programa/PHP Group/PHP/" Action application/x-httpd-php "/php/php.exe"

Un buen sitio para poner estas lneas es donde encontremos estas otras:
#AddType application/x-httpd-php3 .phtml #AddType application/x-httpd-php3-source .phps

Ahora ya podemos probar un primer fichero PHP: Listado 7.1. C:\Archivos de programa\Apache Group\Apache\htdocs\tema7\hola.phtml Saluda al mundo.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE>Hola</TITLE> </HEAD> <BODY> <H1> <CENTER> <?php print "Hola, mundo."?> </CENTER> </H1> </BODY> </HTML>

Recuerda arrancar Apache y solicita la URL siguiente en tu navegador:


http://localhost/tema7/hola.phtml

Lo que ha sucedido es que el programa php.exe invocado como un CGI ha interpretado el script print hola, mundo.. El resultado devuelto por el servidor es el mismo que obtendramos con la siguiente secuencia de comandos:
C:\>cd "\Archivos de programa" C:\>"PHP Group\PHP\php.exe" "Apache Group\Apache\htdocs\tema7\hola.phtml" | more

Invocando a php.exe con el flag q o f y el fichero .phtml podremos obtener directamente el HTML equivalente (sin cabeceras HTTP). Esto es una ventaja de usar php.exe como CGI en vez de cmo mdulo: el poder invocarlo directamente para poder depurar los ficheros PHP. Pero se corre un riesgo a nivel seguridad. Si todava mantienes los ejemplos del Tema 3 prueba las dos siguientes URL:
http://localhost/php/php.exe/tema7/hola.phtml http://localhost/php/php.exe/cgi-bin/tema3/args.bat

La primera URL no nos preocupa pues reacciona igual que su equivalente probada ms arriba. Pero la segunda deja al descubierto el cdigo del programa args.bat que nunca sera accesible de no ser ejecutado por el interprete php.exe en vez de por el command.com. Se trata simplemente de un riesgo, pues si la instalacin como CGI estuviera bien configurada, evitaramos estos casos. PHP usa un fichero de configuracin, php.ini, que en el caso de windows busca por defecto en el directorio de instalacin de Windows. Con las distribuciones se suele proporcionar uno o dos ficheros con una configuracin que en la mayora de los casos nos encajarn bastante bien, son los ficheros php.ini-dist y php.ini-optimized. En nuestro caso y para evitar el problema de seguridad, copiaremos php.ini-dist al directorio de donde est instalado Windows (por defecto C:\WINDOWS) con el nombre

Tema 7. PHP: Server-Side Scripting

php.ini. Una vez copiado al directorio correspondiente, lo editamos, buscamos una lnea con el siguiente texto:
doc_root =

y lo sustituimos por el siguiente:


doc_root = "C:\Archivos de programa\Apache Group\Apache\htdocs"

Ahora solo los documentos que se encuentre por debajo de ese path pueden ser interpretados por php.exe. Puedes comprobarlo probando de nuevo:
http://localhost/php/php.exe/cgi-bin/tema3/args.bat

En nuestro caso esta es una solucin valida, pero puede que en la realidad estemos dejando visibles subdirectorios que debieran estar protegidos. Para ms detalles ver la las recomendaciones en la documentacin (http://www.php.net/manual/security.php) sobre seguridad con el modo CGI. Una forma de comprobar la configuracin por defecto que PHP est usando es mediante el siguiente comando:
C:\>"C:\Archivos de programa\PHP Group\PHP\php.exe" -i

Pero el resultado es una respuesta CGI que mejor sera que la interpretase un servidor web. Podemos definir una accin en el servidor del estilo a las que veamos en el Tema 4 para ver el estado o los mdulos del Apache; o simplemente, hacer uso del siguiente fichero PHP: Listado 7.2. C:\Archivos de programa\Apache Group\Apache\htdocs\tema7\info.phtml Informa de la configuracin del interprete PHP.
<SCRIPT language="php"> phpinfo() </SCRIPT>

Para invocarlo accederemos a la siguiente URL*:


http://localhost/tema7/info.phtml

Como ejercicio compara el fichero php.ini con el resultado obtenido.

Cdigo PHP en HTML


En los ejemplos vistos hasta ahora hemos podido detectar hasta tres formas distintas de incrustar cdigo PHP entre el HTML. En el primer ejemplo escribamos:
<? echo "hola" ?>

sta es la forma corta o estilo-SGML que resulta incompatible con el XML (que usa esa notacin para sus propios fines), por eso se puede desactivar en la configuracin (php.ini) y forzar a cumplir el estndar XML.

Si eres coleccionista de huevos de pascua, prueba tambin la URL:


http://localhost/tema7/info.phtml?=PHPE9568F36-D428-11d2-A769-00AA001ACF42

Como ejercicio, razona un poco donde estaba escondido el huevo de pascua, y en que condiciones aparece. Te puede ayudar el ver el cdigo HTML generado por la funcin PHP phpinfo().

Tema 7. PHP: Server-Side Scripting

El estilo corto compatible con XML sera el del siguiente ejemplo que hemos visto:
<?php print "Hola, mundo."?>

La tercera forma vista es mediante la etiqueta SCRIPT de HTML:


<SCRIPT language="php"> phpinfo() </SCRIPT>

Para los que estn acostumbrados al estilo ASP (<% %>), es posible configurar PHP (no viene as por defecto) para que se pueda usar tambin ese estilo:
<% for($i=0; $i<10; $i++) { %> <BR> <% } %>

Observad que la intencin del cdigo anterior es la de repetir 10 veces la etiqueta HTML <BR> que al encontrarse entre {} la considera una instruccin cualquiera.

7.3.

Sintaxis Bsica

La sintaxis bsica de PHP es una mezcla entre C, C++, Java y otros lenguajes de script como Perl y Shell-Script (ksh, bsh o bash). Esto se puede apreciar en los ejemplos anteriores, donde a priori, igual da usar echo que print, con o sin parntesis (consultar la documentacin para determinar sus diferencias, que las hay). Igualmente, los comentarios pueden ser al estilo C, C++ o Shell.

Variables
Las variables no se declaran, se distingue entre maysculas y minsculas, no tienen tipo y empiezan por $. Esto supone una sintaxis del tipo Shell para las variables, pero ms ponente, pues permite variables dinmicas, esto quiere decir, que dos $ supondra interpretar el nombre de la variable como el contenido de la misma con un solo $, solo que para resolver posibles ambigedades se fuerza en este caso a usar exclusivamente el estilo Shell de llaves: $$var[$i] se debe expresar como ${$var[$i]} o ${$var}[$i]. Para acceder a una variable global desde una funcin hay que indicarlo explcitamente, o hacerlo a travs del array $GLOBALS[], pues el mbito no es heredado por las funciones llamadas. Si una variable se usa antes de ser asignada no da error sino un valor por defecto que depende del valor esperado en ese contexto (este comportamiento puede ser modificado con la funcin error_reporting()para que de error). La funcin isset() nos indica si una variable ya est asignada y la funcin unset() la deja como si nunca hubiera sido asignada. Algunas de estas caractersticas se ilustran en un ejemplo, que adems trata de separar el cdigo ejecutable del HTML (como recomendbamos para los CGI en el Tema 3) mediante el mecanismo de inclusin de ficheros.

Inclusin de ficheros
Para la inclusin de ficheros es conveniente que estos estn en directorios distintos para que no puedan ser invocados directamente a travs de una URL. En nuestro caso hemos elegido el directorio para CGIs (cgi-bin) configurado en el Apache, por paralelismo entre los scripts ejecutables por s solos y los de PHP. En este ejemplo no resulta peligroso (ya comprobamos

Tema 7. PHP: Server-Side Scripting

antes que no se pueden ejecutar php.exe nada ms que con ficheros que estn a partir del directorio doc_root), pero en otro caso en el que no tuviramos claro que permisos hemos dado al directorio, podra resultar peligroso. Lo ideal es escoger un directorio que no est relacionado con el servidor web. Debemos indicarle al interprete PHP cuales son los directorios donde buscar los ficheros incluidos. Para ello sustituiremos en el fichero php.ini el texto
include_path =

por el siguiente:
include_path = "C:\Archivos de programa\Apache Group\Apache\cgi-bin"

Este sera el fichero que incluye a otro: Listado 7.3. C:\Archivos de programa\Apache Group\Apache\htdocs\tema7\saludo.phtml Mejora el PHP de saludo hola.phtml.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <?php include "tema7/saludo.php"?> <HTML> <HEAD> <TITLE> <?php titulo()?> </TITLE> </HEAD> <BODY> <H1 style="font-weight:bold; font-size:200%; color:blue"> <CENTER> <?php saludo()?> </CENTER> </H1> </BODY> </HTML>

Y ste el que es incluido: Listado 7.4. C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\saludo.php Funciones necesarias para el PHP saludo.phml.
<SCRIPT language="php"> ############################### # Funciones para saludo.phtml # ############################### $titulo="Hola"; /* Variable global */ function titulo() { global $titulo; // Referencia a la global print("$titulo\n"); } function saludo() { global $titulo; // Referencia a la global $Hola = "mundo"; /* Variable local */ print("$titulo, ${$titulo}.\n"); // ${$titulo} eq. ${"Hola"} eq. $Hola } </SCRIPT>

Ahora ya podemos probarlo en la URL:


http://localhost/tema7/saludo.phtml

Existen variantes de include() require_once() o virtual().

como

son

require(),

include_once(),

Tema 7. PHP: Server-Side Scripting

Tipos de datos
Los enteros PHP equivalen a los enteros largos en C y se pueden expresar en decimal, octal (si empiezan por el dgito 0) y en hexadecimal (empiezan por 0x). Los negativos se expresan empezando por -. Los reales equivalen a los dobles en C, y como en C, pueden ser expresados en notacin cientfica (y con signo a la mantisa o al exponente). En la versin 4 aparecen dos constantes de tipo puramente booleanas (TRUE y FALSE). Mediante conversin implcita de tipos, se mantiene la compatibilidad con las versiones anteriores que trabajaban los valores lgicos asocindolos a otros tipos (falso es 0, "0", "", etc.). Las cadenas pueden ser expresadas entre comillas o dobles comillas. Como en otros lenguajes de script, las expresadas con dobles comillas son interpretadas para sustituir secuencias de escape (\n \r \t \$ \ y \\) y/o variables. Las expresadas con comillas simples son literales, con excepcin de dos secuencias de escape (\ y \\). Las cadenas pueden considerarse arrays que empiezan en la componente 0. Los arrays pueden indexarse por nmeros o cadenas y crecen dinmicamente conforme se van asignando componentes. Una forma de hacerlos crecer automticamente es asignando valor a un componente sin ndice, que significa asignar el nuevo valor a la siguiente componente a la mayor de todas que ya est asignada. Todo esto se puede verificar en el siguiente ejemplo: Listado 7.5. C:\Archivos de programa\Apache Group\Apache\htdocs\tema7\arrays.phtml Muestra el cdigo y el resultado del manejo de arrays.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <?php include "tema7/arrays.php"?> <HTML> <HEAD> <TITLE> Arrays </TITLE> </HEAD> <BODY> <CENTER> <H1 style="font-weight:bold; font-size:200%; color:blue"> Arrays </H1> <TABLE width="80%" border="1" rules="all"> <TR align="center"> <TD> <B>C&oacute;digo</B><BR> </TD> <TD> <B>Resultado</B><BR> </TD> </TR> <TR> <TD> <?php show_source("tema7/arrays.php")?> </TD> <TD> <?php arrays()?> </TD> </TR> </TABLE> </CENTER> </BODY> </HTML>

Aqu slo se puede ver que el cdigo de verdad esta en otro fichero (arrays.php) que es mostrado por la funcin show_source() y que debe tener una funcin principal arrays() que implementa al ejemplo. El cdigo de arrays.php se muestra a continuacin:

Tema 7. PHP: Server-Side Scripting

Listado 7.6. C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\arrays.php Cdigo del manejo de arrays.


<SCRIPT language="php"> function arrays() { print("<B>Antes:</B><BR>\n"); print("\$Array='$Array'<BR>\n"); print("\$Array[0]='$Array[0]'<BR>\n"); print("\$Array[3]='$Array[3]'<BR>\n"); $Array[3]="Componente 3"; $Array[]="Componente 4"; $Array["Cadena"]="Componente ?"; $Array[]="Fin"; print("<BR><BR><B>Despu&eacute;s:</B><BR>\n"); print("\$Array='$Array'<BR>\n"); print("\$Array[0]='$Array[0]'<BR>\n"); while(list($componente,$valor)=each($Array)) { print("\$Array[$componente]='$valor'<BR>\n"); } } </SCRIPT>

Para visualizar el ejemplo accede a la URL:


http://localhost/tema7/arrays.phtml

La implementacin que PHP hace de los objetos soporta definicin de clases, funciones miembro y herencia. La definicin de clases se hace mediante la palabra clave class que permite agrupar en un bloque de programa ({}) una serie de variables y una serie de funciones que las usan. Los objetos se crean con el operador new y hacen referencia a ellos mismos mediante la variable $this. Funciones como gettype(), is_integer() (y sus alias is_int() e is_long()), is_real() (y sus alias is_float() e is_double()), is_boolean(), is_string(), is_array() e is_object(), permiten obtener y verificar los tipos. La conversin de tipos puede ser implcita, cubriendo casi todas las combinaciones entre tipos, o explcita mediante cast al estilo C ((int), (double), (string), etc.) o mediante funciones de conversin (ceil(), floor(), round(), chr(), odr(), implode() y explode()).

Operadores y expresiones
A continuacin se muestra una tabla de operadores ordenados de mayor a menor prioridad: new [] ! ~ ++ -- @ () */% +-. << >> < <= > >= == != === !== & ^ | && || ? : Nuevo objeto. Componente de un array. Negacin lgica y de bits, incrementar, decrementar, control de error y cast. Producto, divisin y mdulo. Suma, resta y concatenacin. Desplazamiento izquierda y derecha de bits. Relacionales menor, menor o igual, mayor y mayor o igual. Relacionales igual y distinto, para valor y para valor y tipo. Conjuncin de bits. Disyuncin exclusiva de bits. Disyuncin de bits. Conjuncin lgica(con prioridad alta). Disyuncin lgica (con prioridad alta). Operador ternario condicional (como el de C).

Se refiere al operador cast para conversin de tipos: (int), (double), etc.

Tema 7. PHP: Server-Side Scripting

= += -= *= /= Asignacin y asignaciones acumulativas (para la suma, resta, .= %= &= |= ^= multiplicacin, divisin, concatenacin, mdulo, conjuncin de bits, ~= <<= >>= disyuncin de bits, disyuncin exclusiva de bits, negacin de bits y desplazamiento a la izquierda y a la derecha de bits). print Funcin print como operador. and Conjuncin lgica (con prioridad baja). xor Disyuncin exclusiva lgica. or Disyuncin lgica (con prioridad baja). , Separador de parmetros y expresiones.

En PHP la unidad mnima para un bloque de instrucciones ({...}) es la expresin. As pues, operaciones como 3+5 o simplemente valores como FALSE, sin asignarse a ninguna variable o sin pasar como parmetros a ninguna funcin, pueden ser expresiones consideradas como una instruccin (intil, desde luego, pues su valor se pierde si no conlleva ningn efecto colateral) sin provocar ningn error de sintaxis.

Instrucciones de control
Las instrucciones de control if-elseif-else, switch-case-break-default, while, do-while y for son literalmente una copia de C, a nivel estructura de control y sintaxis, incluso contemplan en los bucles los controles break y continue. Como aadido, permite para todas las instrucciones de control, menos para do-while, una sintaxis alternativa en la que poder determinar los bloques de instrucciones mediante dos puntos y una etiqueta de fin de instruccin (:endxxx) en vez entre llaves ({}), es decir: switch (expr) { if (expr) { case expr: instrucciones instrucciones } break; elseif (expr) { default: instrucciones instrucciones } break; else { instrucciones } } switch (expr): if (expr): case expr: instrucciones instrucciones elseif (expr): break; instrucciones default: else: instrucciones instrucciones break; endif; endswitch; while (expr) { for (expr;expr;expr){ instrucciones instrucciones } }

while (expr): for (expr;expr;expr): instrucciones instrucciones endwhile; endfor;

Las funciones exit() y die() interrumpen el control y salen del interprete, die() lo hace despus de imprimir en la salida estndar la cadena pasada como parmetro. Para evitar que el control se meta en bucles infinitos, en PHP se puede definir un tiempo de respuesta que sobrepasado provoca la interrupcin del programa. Por defecto viene configurado con 30 segundos.

7.4.

Posibilidades del lenguaje PHP

Como PHP ha nacido especficamente para programar aplicaciones en Web, no es necesario incluir ningn tipo de librera para acceder directamente a cualquier variable de un formulario. PHP crea variables globales de todas los datos que lleguen en una peticin HTTP.

Tema 7. PHP: Server-Side Scripting

Igualmente estn disponibles todas las variables de entorno que proporcione el servidor HTTP al puro estilo CGI, ms otras cuantas que proporciona el propio PHP. Todo aquello que se describa como variables en el informe de la configuracin (<? phpinfo() ?>) son realmente variables globales a nuestra disposicin. El resto de caractersticas que aparecen en ese informe tambin estn a nuestra disposicin de una u otra forma, por ejemplo, de lo que se describe como directivas se puede obtener su valor con la funcin get_cfg_var(). Siguiendo la sintaxis tpica de un Shell-Script se puede usar el resultado de cualquier comando del sistema operativo, o grupo de estos, como una cadena. Prubalo directamente sobre el interprete como demostracin:
C:\>"C:\Archivos de programa\PHP Group\PHP\php.exe" <? print(`DIR /B`)?> ^Z

Funciones
Existen mltiples funciones predefinidas, algunas las aportan los mdulos. La documentacin PHP proporciona una sintaxis de estas mostrndonos un prototipado en el que se puede ver el tipo del valor de retorno y el de los parmetros, as como si estos parmetros son opcionales o no. En esta sintaxis de prototipado las palabras clave void y mixed, las debemos interpretar como ningn tipo o cualquier tipo respectivamente. Algunas funciones predefinidas no son tales, sino constructores, lo que implica unas ciertas diferencias, por ejemplo el que puede que no se necesiten parntesis para determinar sus parmetros, etc. Ya hemos visto en los ejemplos como definir nuestras propias funciones. Como en otros lenguajes, la instruccin return nos permite devolver el control de la llamada con un valor de retorno. En los nombres de las funciones no se distinguen maysculas y minsculas y las variables son propias en cada llama, de forma que el uso de variables globales se debe especificar explcitamente, como ya indicamos con anterioridad. Sin embargo, las variables locales pueden ser permanentes desde la primera invocacin a la funcin y no destruirse, indicndolas como estticas (static), pero esto no las hace accesibles desde fuera de la funcin. Una funcin que ya exista no se puede volver a definir y hay que tener en cuenta que el mbito en el que quedan declaradas es el global, aunque se haga una definicin de funcin dentro de otra funcin. Por el contrario, en PHP4 (no as en PHP3) es posible llamar a las funciones antes de definirlas. El mecanismo que PHP4 usa para ello es realizar dos pasadas sobre el cdigo, la primera para definir funciones y la segunda para interpretar el cdigo. Sin embargo, este truco no nos permite invocar a una funcin antes de tenerla definida si es declarada de forma anidada en otra funcin. Una funcin puede ser llamada recursivamente de forma directa o indirecta sin ninguna pega. Dependiendo del control de errores que llevemos, una funcin podr ser llamada con ms o menos de los parmetros con los que fue definida. Por defecto, llamarla con ms parmetros no provoca error alguno, y con menos provoca un mensaje de advertencia y no para la ejecucin. En el primer caso los parmetros sobrantes son ignorados y en el segundo toma el valor por defecto segn contexto (como cuando se usa una variable sin asignarle nada todava).

10

Tema 7. PHP: Server-Side Scripting

Es posible, adems, realizar una gestin de parmetros variables con las funciones func_num_args(), func_get_arg() y func_get_args(). Pude ser interesante combinar esta gestin con la posibilidad de proporcionar valores por defecto a los parmetros. En el siguiente ejemplo se ilustran algunas de las cuestiones anteriores: Listado 7.7. C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\funciones.php Cdigo de definicin y manejo de funciones.
<SCRIPT language="php"> F0(); // Llama a f0 sin parametros antes de definirse function funciones() { @f2(1); // El operador @ evita el mensaje de advertencia f1(1,2); // En f2 falta un parametro y en f1 sobra otro for ($i=0;$i<9;$i++) print("<BR>\n"); // Cuestin de estetica } function f0($P1 = TRUE) { // $P1 es por defecto verdadero if ($P1) { function f1($P1) { // Se define al ejecutarse F0(TRUE) print("f1: \$P1='$P1'<BR>\n"); } } } function F2($P1,$P2) { // Da igual F2 que f2 print("f2: \$P1='$P1' \$P2='$P2'<BR>\n"); } </SCRIPT>

Como en el caso de arrays.php, este fichero slo lleva cdigo PHP y no HTML (la etiqueta SCRIPT es el nico vestigio HTML). El cdigo HTML debera estar, como en el ejemplo de arrays, en una plantilla (fichero HTML) que incluyera a su vez a ste (el fichero PHP). Como el aspecto que proporcionaba la plantilla arrays.phtml puede ser valido tambin para este ejemplo de funciones, copiaremos el fichero arrays.phtml a funciones.phtml y lo editaremos para sustituir todas las referencias hechas a la palabra arrays por la palabra funciones. Ahora ya podemos probar el cdigo de funciones.php solicitando a la URL:
http://localhost/tema7/funciones.phtml

NOTA

A lo largo de este tema, usaremos el convenio de que los ficheros .php contengan la lgica del programa (cdigo PHP mayoritariamente) y los .phtml contengan el diseo de la interfaz de usuario (cdigo HTML con inclusiones y llamadas a funciones PHP puntuales). Este acuerdo es particular y no universal: la comunidad que usa PHP crea indistintamente ficheros .php o .phtml, as como .php3, simplemente por razones como la costumbre o porque as lo hacan las fuentes de donde aprendieron.

El paso de parmetros en las funciones se puede hacer por valor o por referencia. Por defecto es por valor. Para que sea por referencia, o se indica en la definicin de la funcin o se indica en la llamada. Se puede hacer en la llamada a una funcin porque en realidad de puede manejar la referencia de cualquier variable, incluso para trabajar nicamente con variables y no slo con funciones. Analiza el siguiente ejemplo: Listado 7.8. C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\referencias.php Cdigo de manejo de referencias a variables.
<SCRIPT language="php"> function referencias() { $variable1="Valor1 inicial"; $variable2="Valor2 inicial"; $copia1=$variable1; $copia2=&$variable2; $copia1="Valor1 cambiado"; // No altera a $variable1

11

Tema 7. PHP: Server-Side Scripting

$copia2="Valor2 cambiado"; // Altera a $variable2 print("$variable1<BR>\n"); print("$variable2<BR>\n"); print("<BR><BR><BR>\n"); f1($variable1); // f1 altera a $varible1 f2(&$variable2); // f2 altera a $varible2 print("$variable1<BR>\n"); print("$variable2<BR>\n"); } function f1(&$referencia) { $referencia="Valor1 cambiado en f1"; } function f2($valor) { $valor="Valor2 cambiado en f2"; } </SCRIPT>

El Ejemplo de los Ejemplos


Para probar el ltimo ejemplo nos tocara hacer tambin una plantilla nueva equivalente a arrays.phtml o funciones.phtml, pero esta vez, en vista de que el formato de la plantilla puede venir bien a varios ejemplo, y como ejercicio, vamos a intentar hacerla genrica: Listado 7.9. C:\Archivos de programa\Apache Group\Apache\htdocs\tema7\generico.phtml Muestra el cdigo y el resultado de un ejemplo en general.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <?php include "tema7/generico.php"?> <HTML> <HEAD> <TITLE> <?php titulo()?> </TITLE> </HEAD> <BODY> <CENTER> <H1 style="font-weight:bold; font-size:200%; color:blue"> <?php titulo()?> </H1> <TABLE width="80%" border="1" rules="all"> <TR align="center "> <TD> <B>C&oacute;digo</B><BR> </TD> <TD> <B>Resultado</B><BR> </TD> </TR> <TR> <TD> <?php codigo()?> </TD> <TD> <?php resultado()?> </TD> </TR> </TABLE> </CENTER> </BODY> </HTML>

El cdigo para el fichero generico.php debe ser tal que dependiendo de una variable pasada por CGI, proporcione las funciones titulo(), codigo() y resultado() apropiadas para cada caso. La funcin titulo() consistir prcticamente en imprimir el valor de la variable pasada por CGI. La funcin codigo(), provocar una llamada a la funcin show_source() tomando como parmetro un nombre de fichero relacionado la variable. El problema es resultado() que debe implicar una llamada a una funcin que en cada caso ser distinta. Utilizaremos una nueva caracterstica de PH: los nombres de funcin como variables.

12

Tema 7. PHP: Server-Side Scripting

El nombre de una funcin es un smbolo relacionado con ella como sucede en otros interpretes de procesamiento simblico como Lisp. Es posible, tambin como en Lisp, tener incluso funciones sin nombre (funciones lamda). Volviendo a nuestro ejemplo generico.php, faltan por destacar algunos detalles: Si no se indica que ejemplo mostrar se mostrar a s mismo. Se usa una funcin para incluir cdigo que proporciona un mecanismo con el que evitar que se incluya ms de una vez el mismo. Esto evita que se bucle al ponerse como ejemplo su propio cdigo. Otra funcin evita redefinir la funcin titulo() si el cdigo a mostrar ya la implementa. Por ltimo, solo se define la funcin resultado() si al menos se ha podido acceder al fichero donde se supone que est el cdigo a mostrar. En caso contrario muestra el nombre del supuesto fichero entre interrogantes. Una funcin vaca hace que cuando se muestra as mismo no d ningn resultado.

Observa el cdigo detalladamente: Listado 7.10. C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\generico.php Cdigo genrico para probar ejemplos.
<SCRIPT language="php"> if (!isset($Ejemplo)) $Ejemplo="Generico"; // A si mismo por defecto $Fichero=strToLower("tema7/$Ejemplo.php"); @include_once($Fichero); // Incluye una sola vez if (!function_exists("titulo")) { function titulo() { // Solo si no existia global $Ejemplo; print($Ejemplo); } } function codigo() { global $Ejemplo; global $Fichero; if (@show_source($Fichero)) { function resultado() { // Si se accedio al fuente global $Ejemplo; $Ejemplo(); // Nombre de funcin en una variable } } else print("$Ejemplo.php?"); } function generico() { } // Si se muestra a si mismo no dara ningun resultado </SCRIPT>

Prueba ahora las siguientes URL y analiza detenidamente lo que est pasando:
http://localhost/tema7/generico.phtml?Ejemplo=Referencias http://localhost/tema7/generico.phtml?Ejemplo=Funciones http://localhost/tema7/generico.phtml?Ejemplo=Error http://localhost/tema7/generico.phtml http://localhost/tema7/generico.phtml?Ejemplo=Saludo

Ya podemos llamar a cualquier ejemplo .php compatible con nuestra plantilla generico.phtml que tengamos en nuestro directorio tema7 con solo poner la query Ejemplo=XXXXX. Ahora con otro PHP podremos seleccionar cualquier ejemplo del tema7: Listado 7.11. C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\ejemplos.php Nos permite seleccinar uno de los ejemplos.
<SCRIPT language="php"> function ejemplos() { global $REQUEST_URI;

13

Tema 7. PHP: Server-Side Scripting

print <<<FIN <FORM action="$REQUEST_URI" method="POST"> <CENTER> <LABEL> <B>Ejemplos:</B><BR><BR> <SELECT name="Ejemplo"> FIN; $Directorio=openDir(get_cfg_var("include_path")."/tema7/"); while ($Fichero=readDir($Directorio)) { $Fichero=ucFirst(strToLower($Fichero)); list($Ejem,$Ext)=explode(".",$Fichero); if ($Ejem AND !strCaseCmp($Ext,"php")) print("<OPTION>$Ejem</OPTION>\n"); } closeDir($Directorio); print <<<FIN </SELECT> </LABEL><BR><BR><BR><BR> <INPUT type="submit" value="Mostrar"> </CENTER> </FORM> FIN; } </SCRIPT>

La URL que debes invocar para probarlo es:


http://localhost/tema7/generico.phtml?Ejemplo=Ejemplos

Como ejercicio, editar ahora el fichero generico.php y cambia el valor que toma por defecto para la variable $Ejemplo, "Generico", por la cadena "Ejemplos", de forma que se pueda invocar a generico.phtml sin ningn parmetro y que salga directamente el selector de ejemplos.

7.5.

Usando a fondo PHP

Son muchas las funcionalidades de PHP, y prueba de ello es la extensa documentacin sobre sus funciones predefinidas, ya sean por su propio ncleo o por mdulos. En la documentacin se encuentran agrupadas por temas: las relacionadas con la ejecucin de programas, con la hora y la fecha, etc. Sera interesante tener una clasificacin alfabtica de las funciones, pero lamentablemente, hoy por hoy, sta no aparece en la documentacin. Aqu vamos a ver algunas funciones (todas sera imposible), aprovechando que aparecen en algn ejemplo, y de paso nos servir para advertir de la existencia de un tipo de funciones relacionadas con algn tema. Evitaremos todas los temas relacionados con el manejo y gestin de base de datos genricas o concretas que nos reservamos para ver en le prximo tema. Aprovecharemos tambin los ejemplos para ilustrar alguna caracterstica o cuestin sintctica que todava no hallamos visto. En el ltimo ejemplo descubrimos una nueva forma de pasarle cadenas a la funcin print, al ms puro Per o Shell-script. Tambin hacemos uso de funciones que no habamos visto hasta ahora como openDir(), readDir() y closeDir() para manejo de directorios (existe todo un grupo de funciones dedicado a esta cuestin). Las funciones explode(), ucFirst() y strToLower() (esta ltima ya la usbamos en otro ejemplo) pertenecen al numeroso grupo de las funciones de manejo de cadenas, la primera trocea una cadena en varias, la segunda pone la primera letra de cada palabra de una cadena en maysculas y la ltima pasa toda una cadena a minsculas. list() es en realidad un constructor que sirve para asignar elementos de un array a variables sueltas de una sola vez.

14

Tema 7. PHP: Server-Side Scripting

Expresiones regulares
PHP es muy potente trabajando expresiones regulares para bsqueda y/o sustitucin. Podemos usarlo para crear fcilmente un parser. Algunos parser ya vienen implementados implcita o explcitamente como por ejemplo, una serie de funciones especificas que tiene para el tratamiento de ficheros XML. Estas propiedades combinadas con la posibilidad de tratar cualquier URL como un fichero ordinario, nos posibilita crear un ejemplo con el que poder analizar una pagina web e indicar cuantas referencias se hacen a sitios web distintos al propio y cuales son estos sitios: Listado 7.12. C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\enlaces.php Busca saltos a otros sitios en una pgina web.
<SCRIPT language="php"> function enlaces() { global $REQUEST_URI, $URL; </SCRIPT> <FORM action="<?php echo $REQUEST_URI?>" method="POST"> <CENTER> <INPUT type="Hidden" name="Ejemplo" value="Enlaces"> <LABEL> <B>URL:</B><BR> <INPUT type="text" name="URL" value="<?php echo $URL?>"> </LABEL><BR><BR> <INPUT type="submit" value="Buscar"> </CENTER> </FORM> <SCRIPT language="php"> if (!isset($URL)) return; if (!$Contenido=@file($URL)) return mensaje("URL no encontrada"); $R1="/<A\s[^>]*HREF\s*=\s*([^>]*)\s*[^>]*>/i"; $R2="/^([\"]?)(http:|)\/\/.*\\1$/i"; $R3="/\/\/([^\/\"]*)/"; preg_match($R3,$URL,$Host); $HTML=implode("",$Contenido); preg_match_all($R1,$HTML,$HREF); foreach (preg_grep($R2,$HREF[1]) as $Enlace) { preg_match($R3,$Enlace,$Sitio); if (strCaseCmp($Sitio[1],$Host[1])) $Contador[strToLower($Sitio[1])]++; } if (!$Contador) return mensaje("Sin direcciones"); mensaje("Enlaces:"); foreach ($Contador as $Sitio => $Enlaces) { print("$Enlaces a $Sitio<BR>\n"); } } function mensaje($Texto) { </SCRIPT> <CENTER> <B><?php echo $Texto?></B><BR> </CENTER> <SCRIPT language="php"> } </SCRIPT>

Lo primero que hay que destacar de este ejemplo es algo que ya dejamos ver sin mucho detalle en el punto Cdigo PHP en HTML. PHP trata el cdigo HTML como instrucciones, de forma que cuando estn dentro de un bloque {} estas aparecern en el documento HTML resultante si ese bloque se ejecuta, tantas veces como se ejecute y en el lugar donde se ejecute. El resultado es que cuando se interrumpe el script PHP a mitad de una funcin, es como si se le indicara a la funcin que se pretende imprimir literalmente el texto HTML contenido entre el ltimo fin de script (</SCRIPT>) y el prximo principio de script (<SCRIPT

15

Tema 7. PHP: Server-Side Scripting

language=php>) como si de una nica instruccin print se tratase. Compara este estilo tipo HTML con el estilo de Shell-Script/Perl usado en el ejemplo anterior. Adems, este cdigo HTML embebido en PHP puede llevar a su vez cdigo PHP embebido. En el ejemplo se puede comprobar con la inclusin de algunas etiquetas de la forma:
<?php echo ?>

La funcin file() nos devuelve una cadena con todo el contenido el fichero (URL en esta ocasin), ahorrandonos la apertura, bucle de lecturas y cierre del fichero. Las variables $R1, $R2 y $R3 contienen tres expresiones regulares (tipo Perl) preparadas para: R1) Selecciona las subcadenas que estn envueltas entre <A HREF= y >. R2) Determina que URL llevan protocolo http: y/o host (//). R3) Selecciona las subcadenas envueltas entre // y /, es decir, el host. Hay varias jergas para definir expresiones regulares. PHP permite trabajar con las POSIX (las extendidas) y con casi la totalidad de las e-Perl que a su vez son un supraconjunto de las Shell. La definicin de expresiones regulares no es trivial y su uso casi queda relegado a gurus y administradores de sistemas, pero resultan una herramienta muy potente. Con la funcin preg_match() se consigue seleccionar una subcadena de otra. La funcin preg_match_all() selecciona todas las posibles. La funcin preg_grep() busca entre varias cadenas y se queda con las que coinciden con la expresin regular. Una nueva instruccin de control que no vimos en el punto Instrucciones de control se usa en este ejemplo. Es equivalente a un for, pero itera sobre las componentes de un array. Su sintaxis es la siguiente: foreach (array as [$clave =>] $valor) instruccin Recuerda que los arrays en PHP no tiene verdaderamente ndices, sino claves que pueden ser numricas o cadenas. Hay muchas formas de iterar sobre los arrays, pues estos pueden ser considerados como pilas, colas o listas. Se recomienda ver la documentacin de las funciones para manejo de arrays. Una funcin ms de las clasificadas como funciones de manejo de cadenas aparece en este ejemplo: strCaseCmp() compara dos cadenas sin distinguir entre maysculas o minsculas. Para poder probar el ejemplo, utiliza como en los casos anteriores el fichero genrico.phtml. Ahora puedes indagar a que empresas apuntan otras empresas en la red. No necesitas que te sugiera ninguna URL en concreto verdad?

Manejo de sesiones
PHP puede establecer sus propios mecanismos para establecer sesiones. Por defecto utiliza un mecanismo de cookies pero es configurable, y se puede establecer sesiones sin cookies. En el ejemplo se ha escogido el comportamiento por defecto. PHP proporciona funciones para el manejo directamente de cookies (sera recomendable que las vieras), pero en nuestro caso no nos van a ser necesarias. Tampoco tendremos que gestionar directamente los ficheros de datos con la gestin de la sesin como ocurra en el ejemplo de la tienda virtual del tema 3. Como una pequea demostracin de lo potente que puede ser PHP con temas relacionados con la multimedia (posee por ejemplo libreras para manejo de ficheros PFD y FDF de Acrobat

16

Tema 7. PHP: Server-Side Scripting

o para crear ficheros Shockwave Flash), este ejemplo se ha acompaado de tratamiento de imgenes grficas: Un fichero PHP (en concreto diana.phtml) responde con el grfico de una diana. Si se le pasan dos parmetros, x e y, la diana es devuelta con un disparo en dicha posicin, as como todos los disparos acumulados en la sesin, adems de que el nuevo disparo queda almacenado para la siguiente invocacin. Si la solicitud del grfico se realiza sin disparo, y no se proporcionan ningn x e y, se inicializa de nuevo la sesin. Listado 7.13. C:\Archivos de programa\Apache Group\Apache\htdocs\tema7\diana.phtml Debe responder un fichero PNG con la imagen de una diana.
<?php include "tema7/diana.php"?>

La verdad es que el cdigo del fichero diana.phtml resulta decepcionante, pues slo es una referencia al verdadero fichero que contiene el programa. Sin embargo hay que destacar que no incluya ninguna otra etiqueta (ni siquiera <!DOCTYPE >), pues esto har que cuando empiece a ejecutarse el cdigo de diana.php, el interprete PHP no haya enviado todava ninguna cabecera y el programa pueda establecer por su cuenta el tipo de cabecera que desea. En concreto, en este caso, es importante porque se debe de indicar que el Content-Type es image/png (fichero de imagen del tipo PNG) para que el navegador lo interprete como tal y no como un texto HTML. Otra razn para la que usar la cabecera del mensaje de respuesta antes que nada es la de tener que incluir una cookie, pues ya hemos indicado que la sesin se controlar mediante este sistema. Precisamente, como PHP la enva automticamente para establecer la sesin, no hay posibilidad de enviarla de forma alternativa mediante etiquetas <META http-eqiv >. Esta distincin entre si se ha enviado ya la cabecera o no (si ya se a procesado cdigo HTML o no) es lo primero que hace el ejemplo mediante la funcin headers_sent(): Listado 7.14. C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\diana.php Implementa el juego de la diana.
<SCRIPT language="php"> if (!headers_sent()) imagen(); // Crea y envia la imagen function diana() { global $REQUEST_URI; global $Ejemplo, $x, $y; if (isset($x) AND isset($y)) $URL_Imagen="/tema7/diana.phtml?x=$x&y=$y"; else $URL_Imagen="/tema7/diana.phtml"; </SCRIPT> <FORM action="<?=$REQUEST_URI?>" method="POST"> <CENTER> <INPUT type="Hidden" name="Ejemplo" value="Diana"> <INPUT type="image" alt="Apunta y dispara" src="<?=$URL_Imagen?>" border="0"> <BR><BR> <INPUT type="submit" value="Limpiar"> <CENTER> </FORM> <SCRIPT language="php"> for ($i=0;$i<9;$i++) print("<BR><BR>\n"); // Cuestin de estetica } function imagen() { dl("extensions/php_gd.dll"); // Carga libreria header("Content-type: image/png"); session_save_path("../../cgi-bin/tema7/datos"); session_register("Disparos"); global $Disparos, $x, $y; if (isset($x) AND isset($y)) $Disparos[]=array($x,$y);

17

Tema 7. PHP: Server-Side Scripting

else $Disparos=array(); $Imagen=imageCreate(100,100); $Blanco=imageColorAllocate($Imagen,255,255,255); $Rojo=imageColorAllocate($Imagen,255,0,0); $Negro=imageColorAllocate($Imagen,0,0,0); imageFill($Imagen,50,50,$Blanco); for ($i=100;$i>0;$i-=20) { // Dibuja la diana imageArc($Imagen,50,50,$i,$i,0,360,$Negro); imageFill($Imagen,50,50,$Negro); imageArc($Imagen,50,50,$i-10,$i-10,0,360,$Rojo); imageFill($Imagen,50,50,$Rojo); } // Dibuja los disparos: while (list(,list($X,$Y))=each($Disparos)) { imageArc($Imagen,$X,$Y,7,7,0,360,$Negro); imageArc($Imagen,$X,$Y,6,6,0,360,$Negro); imageArc($Imagen,$X,$Y,5,5,0,360,$Blanco); imageFillToBorder($Imagen,$X,$Y,$Blanco,$Blanco); } imagePng($Imagen); // Envia imagen } </SCRIPT>

La funcin diana() monta un formulario con la URL de la imagen con o sin parmetros x e y dependiendo si se quiere representar limpia o con los disparos efectuados. En el cdigo HTML del formulario descubrimos una nueva forma de verter de forma embebida el contenido de una variable PHP: <?=?> equivale a <?php echo ?> y se puede usar para constantes variables o funciones PHP. La funcin imagen() se encarga de crear y verter la imagen de la diana. Para poder trabajar con imgenes necesitamos la librera php_gd que en este caso, al no estar incluida en compilacin debemos cargar dinamicamente. La funcin que se encarga de cargarla es dl() el path de la librera dinmica. Como en el cdigo solo indicamos el nombre (php_gd.dll) debermos haber configurado PHP para que busque en el directorio apropiado. De forma similar a como hicimos cuando indiacmos donde buscar los ficharos a incluir (punto Inclusin de ficheros), sustituiremos en el fichero php.ini el texto
extension_dir =

por el siguiente:
extension_dir = "C:\Archivos de programa\PHP Group\PHP\extensions"

La funcin header() nos permite introducir la cabecera Content-type: image/png al mensaje de respuesta. La funcin session_save_path() establece cual va a ser el directorio donde se guarda la informacin de las sesiones. Por semejanza con el ejemplo de la tienda virtual del tema 3 se usa "C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\datos" como directorio aunque en el cdigo aparece como "../../cgi-bin/tema7/datos" (path relativo). La funcin session_register() inicializa la sesin si no lo est ya (equivale a session_start()) y sincroniza o establece sincronizacin con la variable global cuyo nombre se indique en la cadena que se le pasa como parmetro (sin el smbolo $), en nuestro caso "Disparos". Se pueden registrar todas las variables que se desee. En nuestro caso no necesitamos ms, pero son muchos la s funciones relacionadas y los parmetros para ajustar y configurar sesiones. Con las funciones imageCreate() y imageColorAllocate() creamos una imagen y loa colores que vamos a usar con ella. Con imageFill(), imageArc() e imageFillToBorder() dibujamos la diana u los disparos. La funcin imagePng() nos permite volcar en binario la imagen con el formato PNG.

18

Tema 7. PHP: Server-Side Scripting

La funcin each() es un iterador para arrays que devuelve el indice (clave) y valor del elemento actual y pasa a apuntar al siguiente. Como en este caso no nos interesa el indice, el constructor list() no tiene primer elemento y el segundo es otro constructor list() ya que el valor de los disparos es a su vez otro array con dos enteros (x e y). Podemos probar ahora a jugar invocndolo a travs de generico.html como en los casos anteriores. En cuanto lo uses, comprueba en el directorio que hemos establecido para guardar la informacin de la sesin (\cgi-bin\tema7\datos) que aparece un fichero sess_* por cada instancia de navegador que acceda a nuestro programa. Si inspeccionas el contenido de estos ficheros te dars cuenta que lo nico que hacen es codificar la variable $Disparos almacenando su contenido a lo largo de una sesin. Analizando un poco puedes describir exactamente las coordenas de tus disparos (la diana perfecta esta en x=50 e y=50).

Utilidades de red
PHP tiene tambin muchas funciones que lo convierten un una potente herramienta para programar en red, como son funciones para DNS, NIS, SNMP, IMAP, POP3, NNTP, etc. Como prueba de ello, en un ltimo ejemplo, vamos a reproducir el ejemplo del Cliente HTTP del tema 1: Listado 7.15. C:\Archivos de programa\Apache Group\Apache\cgi-bin\tema7\cliente.php Envia una cabecera NPH.
<SCRIPT language="php"> function cliente() { global $REQUEST_URI; </SCRIPT> <FORM action="<?=$REQUEST_URI?>" method="POST"> <CENTER> <INPUT type="Hidden" name="Ejemplo" value="Cliente"> <LABEL> <B>Host:</B> <INPUT type="text" name="Host" value="localhost"> </LABEL><BR> <LABEL> <B>Puerto:</B> <INPUT type="text" name="Puerto" value="80" size="4"> </LABEL><BR> <LABEL> <B>Peticion:</B><BR> <TEXTAREA name="Peticion" rows="3" colls="20"> GET / HTTP/1.1 Host: localhost </TEXTAREA> </LABEL><BR> <INPUT type="submit" name="Conectar" value="Conectar"> <INPUT type="reset" value="Sugerir"> </CENTER> </FORM> <SCRIPT language="php"> for ($i=0;$i<15;$i++) print("<BR><BR><BR>\n"); // Cuestin de estetica } function peticion() { global $Socket, $Host, $Puerto, $Peticion; mensaje("Peticin a $Host por puerto $Puerto"); $Socket=fsockopen($Host,$Puerto,&$errno,&$errstr,30); if (!$Socket) mensaje("$errstr ($errno)"); else { print("<PRE>\n$Peticion\n</PRE>\n"); fputs($Socket,rtrim($Peticion)."\r\n\r\n"); }

19

Tema 7. PHP: Server-Side Scripting

} function respuesta() { global $Socket, $Host, $Puerto; mensaje("Respuesta de $Host por puerto $Puerto"); if ($Socket) { while (!feof($Socket)) { $Respuesta.=fgets($Socket,128); } fclose($Socket); $Respuesta=explode("\r\n\r\n",$Respuesta); print("<PRE>\n$Respuesta[0]\r\n\r\n</PRE>\n"); unset($Respuesta[0]); print(implode("\r\n\r\n",$Respuesta)); } } function titulo() { global $Conectar; static $TituloYaImprimido; print("Cliente\n"); if (isset($Conectar) AND $TituloYaImprimido) { </SCRIPT> </H1> <TABLE width="80%" border="1" rules="all"> <TR><TD> <?php peticion()?> </TD></TR> <TR><TD> <?php respuesta()?> </TD></TR> </TABLE> </CENTER> </BODY> </HTML> <SCRIPT language="php"> exit(); } $TituloYaImprimido=TRUE; } function mensaje($Texto) { </SCRIPT> <CENTER> <B><?=htmlEntities($Texto)?></B><BR> </CENTER> <SCRIPT language="php"> } </SCRIPT>

La funcin cliente() proporciona un formulario que nos sirve de interfaz para determinar host, puerto y mensaje de la peticin. La funcin peticion() abre un socket con el host y en el puerto indicado mediante la funcin fsockopen() que devuelve algo equivalente a un manejador de fichero pero vinculado al socket. Si la conexsin (apertura de socket) no tiene existo se indica el error, sino se muestra el mensaje de peticin y se enva (escribiendo en el socket con la funcin fputs()). La funcin respuesta(), si el socket est abierto, recoge la respuesta, cierra la conexin y muestra por separado cabecera y contenido de la respuesta. Las funciones utilizadas son las mismas que para manejar un fichero cualquiera (feof(), fgets() y fclose()). La funcin implode() es la inversa a explode(). En el caso de responder al formulario mostrando la peticin y respuesta HTTP, nuestra habitual plantilla generica en la que se muestra el cdigo a la izquierda y el resultado a la derecha, ya no nos vale, no hay espacio suficiente el lado del resultado. Se ha pensado que es ms interesante una nueva plantilla que muestre en la parte superior el mensaje enviado y en la inferior la respuesta. Cmo cambiar de plantilla sin utilizar otro fichero distinto a generico.phtml? Aprovechamos la plantilla genrica hasta la segunda vez que imprimimos el ttulo (ver el listado

20

Tema 7. PHP: Server-Side Scripting

7.9. en el punto El Ejemplo de los Ejemplos), y a partir de ah mediante la invocacin a la funcin titulo() tomamos el control e introducimos la nueva plantilla alternativa. Observa detenidamente la funcin titulo(): si determina que est contestando al formulario (variable $Conectar) y es la segunda vez que imprime el titulo (variable $TituloYaImprimido), entonces, introduce el cdigo HTML de la nueva plantilla, y para asegurarse que la antigua no se va a imprimir, termina la ejecucin con la funcin exit(). A pesar de ello, las funciones peticion() y respuesta() si se ejecutan a tiempo, porque son parte de la nueva plantilla introducida (son invocadas conforme se imprime el cdigo HTML en el que estn embebidas). Por ltimo, la funcin mensaje() que ya se usaba en el ejemplo enlaces.php es mejorada mediante el uso de la funcin htmlEntities() que traduce, entre otros caracteres, los acentos a las correspondientes entidades HTML. Prueba este ejemplo a travs de la plantilla generico.phtml y luego ya puedes probar con cualquier host e intentar reconocer por las cabecearas que responden, que servidor HTTP tiene instalado. Puede ser muy interesante que solicites como respuesta HTTP la imagen de la diana del ejemplo anterior, te permitir ver la cabecera correspondiente a la cookie (son cookies que el navegador no necesita escribir en disco, por lo que se quedan en memoria y sta es la nica forma de ver el contenido de una). Otro experimento interesante sera solicitar con este ejemplo al propio ejemplo, y el reto estara en solicitarlo mediante mtodo POST Te atreves?.

7.6.

Apndice A. Software recomendado.

Como editor, volvemos a recomendar para PHP el 1st Page 2000 de Evrsoft. Aparece como el mejor en una web especializada en editores PHP:
http://www.itworks.demon.co.uk/phpeditors.htm

Resulta muy cmodo editar con colores sensibles al contexto, al estilo de cmo se visualizan en el navegador los ejemplo que hemos visto en este tema. Por defecto no trae configurada ninguna de las extensiones del PHP (.phtml .php .php3 .php4) para que seleccione automticamente los dicheros de un directorio, pero se puede configurar.

21

Anda mungkin juga menyukai