PHP-TUT-11 Manejo de datos (I)

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

A la hora de realizar una gestión de información para ofrecerle al usuario unos resultados acordes con su petición, a menudo no es suficiente con disponer de datos “en bruto”, sino que se hace necesario elaborarlos de algún modo. Por ejemplo, puede ser que su sistema almacene fechas en formato aaaa-mm-dd y usted quiera ofrecerlas en formato dd/mm/aaaa, si sus usuarios son europeos, o mm-dd-aaaa, si son anglosajones. O puede ser que, dado un texto determinado, usted sólo quiera mostrar una pequeña parte del mismo como enlace a una página donde se mostrará completo. En este artñiculo vamos a conocer las principales funciones que proporciona PHP para el manejo de cadenas alfanuméricas. En el próximo hablaremos de valores aritméticos y fechas. Estos dos artículos son, desde mi punto de vista, un poco áridos. Mi consejo es que los leas por encima para tener una visión de conjunto de las posibilidades que le ofrece PHP para el manejo de datos, y lo uses como guía de consulta para utilizar cada función concreta cuando necesites llevar a cabo tal o cual acción. No intentes aprenderte de memoria todas las funciones y sus sintaxis.

Algunas de las funciones que vamos a ver en estos artículos ya las hemos conocido y/o usado en algunos puntos de otros anteriores, pero esto nos sirve de recopilación y ampliación de uso.

MANEJO BÁSICO DE CADENAS

Una de las operaciones más habituales consiste en extraer un fragmento de una cadena de texto. Esto lo podemos llevar a cabo con la función substr(), que recibe tres argumentos separados por comas. El primero es la cadena de la que queremos extraer un fragmento. El segundo es el carácter a partir del cual queremos el fragmento. Hay que tener en cuenta que los caracteres empiezan a numerarse desde 0 por la izquierda, así que si, por ejemplo, ponemos un 3, nos estaremos refiriendo al cuarto carácter de la cadena, en el sentido normal de lectura. Estos dos argumentos son preceptivos. El tercer argumento es opcional y se refiere a la longitud del fragmento, expresado en número de caracteres. Si no establecemos este argumento, el fragmento se obtendrá desde el carácter indicado en el segundo argumento hasta el final de la cadena original. En el script subcadena.php vemos un ejemplo de funcionamiento de substr(). El código es el que aparece a continuación:

Al cargar este script en el navegador observará el resultado que ves a continuación:

Extracción de una subcadena

Extracción de una subcadena

Observa que tomamos la cadena original y extraemos un fragmento a partir del carácter 8, es decir, el noveno carácter de la cadena. A este efecto recuerda que cada espacio en blanco, signo de puntuación, número, letra, etc., cuenta como un carácter y se empiezan a contar desde 0 por la izquierda, tal como hemos mencionado. El carácter 8 corresponde a la “u” de “una”. El segundo argumento le indica a la función que queremos un fragmento de 3 caracteres. He acotado la cadena y el fragmento entre comillas simples para que se aprecie mejor el principio y el final.

Otra operación muy habitual con cadenas es eliminar los espacios en blanco que quedan al principio y/o al final de una cadena. Para eliminar los espacios al principio de la cadena, usamos la función ltrim (). Para eliminar los que pudiera haber al final, usamos la función chop () y para eliminar tanto los del principio como los del final, usamos la función trim (). Estas funciones reciben un único argumento: la cadena a la que hay que eliminarle los espacios. Por espacios, a efectos de estas tres funciones, entendemos los espacios en blanco, las tabulaciones y los saltos de línea. Vemos un ejemplo en el script recortes.php:

El resultado lo ves claramente a continuación.

Recortes de espacios en blanco

Recortes de espacios en blanco

A menudo es necesario obtener el código ASCII de un carácter, o bien obtener el carácter que corresponde a un determinado código ASCII. Para ello empleamos las funciones ord () y chr (), respectivamente. La primera recibe como argumento un carácter y devuelve su código ASCII. La segunda recibe un valor numérico comprendido entre 1 y 255 y devuelve el carácter correspondiente. En el script ascii.php vemos un ejemplo de uso de estas funciones.

En ocasiones tenemos que conocer el número de caracteres que forman una cadena. Para ello, empleamos la función strlen(), que recibe como argumento la cadena y nos devuelve su longitud, es decir, la cantidad de caracteres que la forman, incluyendo los espacios, signos de puntuación, etc. Podemos ver un ejemplo de su uso en el script longitud.php:

Carga este script en el navegador para ver su funcionamiento.

A la hora de mostrar resultados o valores en la página, existen varias funciones que debemos tener en cuenta. En algunos textos, y también en scripts ya escritos, puedes encontrar print(), en lugar de echo. El uso es el mismo. Utilizar uno u otro método para mostrar un valor es una cuestión de criterio personal. Sin embargo, hay una función muy interesante a la hora de mostrar ciertos resultados en la página: se trata de printf (). Ésta recibe dos argumentos, separados por una coma. El primero es una cadena de formato, y el segundo es la cadena que queremos mostrar, de forma que nos la devuelve con el formato especificado en el primer argumento. Veamos un ejemplo de uso en el script imprimirFormato.php:

Cadena con formato

Cadena con formato

El resultado aparece a continaución: Con esto podemos medio intuir cómo trabaja esta función. No obstante, deberíamos entrar más en detalle acerca de los formatos. Cómo ves, el formato se expresa, a su vez, cómo una cadena (entrecomillado).

Las cadenas de formato empiezan con el signo % para indicar que se trata, precisamente de un formato.

A continuación fíjate en la letra f (minúscula). Le estamos diciendo que representaremos el dato de la variable $altura cómo un número flotante. La secuencia 2.2 que precede a la f indica que se representará con 2 cifras enteras, el punto decimal, y 2 cifras fraccionarias. También podemos añadir a la cadena de formato una secuencia arbitraria que se mostrará tal cual, cosa que hemos hecho agregando un espacio separador y la palabra  metros.

Aparte de la f hay otros posibles formatos:

CLAVE FORMATO
b El argumento es tratado como un integer y presentado como un número binario.
c El argumento es tratado como un integer y presentado como el caracter con ese valor ASCII.
d El argumento es tratado como un integer y presentado como un número decimal (con signo).
e El argumento es tratado como notación científica (e.g. 1.2e+2). El especificador de precisión indica el número de dígitos después del punto decimal.
E Como %e pero utiliza la letra mayúscula (e.g. 1.2E+2).
u El argumento es tratado como un integer y presentado como un número decimal sin signo.
f El argumento es tratado como un float y presentado como un número de punto flotante (depende de la configuración regional).
F El argumento es tratado como un float y presentado como un número de punto flotante (no depende de la configuración regional).
 o

El argumento es tratado como un integer y presentado como un número octal.

 s El argumento es tratado y presentado como un string.
 x El argumento es tratado como un integer y presentado como un número hexadecimal (con las letras en minúsculas).
 X El argumento es tratado como un integer y presentado como un número hexadecimal (con las letras en mayúsculas).

La función sprintf() actúa como la anterior pero sin poder mostrar su resultado en la página, por lo que éste debe ser almacenado en otra variable. Tienes un ejemplo de su uso en el script valorFormateado.php:

Uso de sprintf

Uso de sprintf

El resultado de la ejecución aparece a continuación:

Observa, en la línea resaltada en el código, que esta vez, a pesar de indicar que es un número flotante, no hemos establecido la cantidad de posiciones enteras (entre % y .). Esto hace que se usen tantas posiciones enteras cómo sean necesarias, de forma automática.

Esto nos será muy útil más adelante, así que quédate con la copla.

 

Veamos un ejemplo de uso de printf () que aclarará un poco más la operativa de los formatos. Vamos a suponer el caso de que quisieras mostrar en una tabla el consumo de combustible de un motor a lo largo de quince días, teniendo en cuenta que gasta, digamos, diecisiete litros diarios. Observa el script tablaFormateada.php:

El resultado de la ejecución de este script lo ves a continaución.

Tabla formateada

Tabla formateada

Como ves, los datos de consumo del motor aparecen alineados de modo que queda un resultado legible a primera vista. Veamos cómo hemos obtenido esta colocación de los datos. En primer lugar fíjate en el uso de printf ():

printf($formato, 17, $dia, $dia*17);

Como ves, esta función puede recibir más de dos argumentos. Los argumentos segundo y siguientes serán tenidos en cuenta como datos a mostrar adaptándose al formato especificado en el primer argumento. Respecto a este formato encontramos varios usos. Empecemos por %'_7d. Cuando en una definición de formato aparece el signo del porcentaje, seguido de la comilla simple, estamos indicando que el siguiente carácter deberá ser usado como de relleno para conseguir una alineación de datos. En este caso es el guión bajo. A continuación vemos el número 7. Esto quiere decir que el dato que se muestre deberá ocupar siete posiciones, completando las que falten con el carácter de relleno. Como el dato que se muestra aquí (el número 17) tiene dos caracteres, se añaden 5 caracteres de relleno. Por último, la letra d especifica que el valor que se va a mostrar debe aparecer como un número en base 10 (el sistema habitual de numeración).

A continuación, siguiendo con la cadena de formato, encontramos un asterisco. Como éste no es un carácter específico de formato, PHP lo determina como directamente imprimible.

Además, un carácter imprimible determina que el siguiente formato se aplicará al tercer argumento de la función que, en este caso, es la variable $dia. En general, los formatos se estructuran de la siguiente manera:

  • Carácter de relleno. Conviene especificar uno diferente del espacio en blanco dado que, cuando hay varios espacios consecutivos, HTML los ignora.
  • Alineamiento. Por defecto, la función alinea por la derecha, poniendo los caracteres de relleno a la izquierda. Si queremos cambiar esto, añadiremos el signo menos (-).
  • Valor numérico. Determina el mínimo número de caracteres que se deben mostrar, incluyendo los del valor a mostrar y los de relleno.
  • Número de decimales. Se precede por un punto (.) y especifica cuántos decimales se le deben conceder al valor a mostrar, tal como veíamos en valorFormateado.php.
  • Tipo de datos. Se determinan según la tabla que hay más arriba a este respecto.

De todos modos, y esto es una opinión personal, cuando necesites formatear datos para su presentación considera el uso de tablas, capas u otros contenedores (bootstrap, por ejemplo, aporta buenas soluciones a este respecto, pero eso es otra historia). Sin embargo, para un formateado rápido de cadenas cuentas también con la función str_pad(), que permite establecer caracteres de relleno a una cadena de un modo más fácil que printf(). Esta función recibe cuatro argumentos:

  • El primero es la cadena que tenemos que completar con caracteres de relleno.
  • El segundo es la longitud total que deberá tener la cadena, incluyendo dichos caracteres.
  • El tercero es el carácter que se usará como relleno, para completar la longitud especificada. Este argumento es opcional y por defecto, si no se especifica otra cosa, es el espacio en blanco.
  • El cuarto parámetro también es opcional y corresponde a la alineación que se establecerá para el relleno. Por defecto, los caracteres de relleno se colocan a la derecha de la cadena. Los tres posibles valores para este parámetro son los que aparecen a continuación:
    • STR_PAD_LEFT, si queremos que el relleno se sitúe a la izquierda de la cadena.
    • STR_PAD_RIGHT o ninguno, si queremos que el relleno se sitúe a la derecha de la cadena.
    • STR_PAD_BOTH, si queremos que los caracteres de relleno se distribuyan a ambos lados de la cadena.

Para ver un ejemplo de funcionamiento observa el listado del script rellenaCadena.php, donde hemos omitido, a propósito, el argumento relativo a la alineación del relleno.

El resultado será que la cadena se mostrará tal como aparece a continuación:

Esto es una cadena+++++++

También contamos con una función específica para repetir una cadena. Se trata de str_repeat(). Esta función recibe dos argumentos. El primero es la cadena en cuestión y el segundo, el número de veces que se debe repetir dicha cadena. Veamos un ejemplo en el script repiteCadena.php:

En la página aparecerá lo siguiente:

*CADENA**CADENA**CADENA**CADENA*

Normalmente, por la naturaleza del uso de esta función, la cadena que constituye el primer argumento suele estar formada por un solo carácter, para crear una línea, un relleno, cosas así.

Con mucha frecuencia es necesario poner todas las letras en mayúsculas o en minúsculas en una cadena antes de mostrarla. Para ello, contamos con las funciones strtoupper() y strtolower(). Estas funciones reciben como argumento la cadena que queremos modificar. Tienes un ejemplo de funcionamiento en mayusMinus.php:

Carga el script en el navegador para ver su funcionamiento.

Existen otras dos funciones que podríamos considerar complementarias de las anteriores: se trata de ucfirst() y ucwords(). Ambas reciben como argumento una cadena o el nombre de una variable que contiene una cadena. La primera función convierte a mayúscula el primer carácter de la cadena (si es una letra, claro). La segunda convierte a mayúscula la primera letra de cada palabra.

Es importante puntualizar que estas funciones no convierten ninguna letra en minúscula, es decir, si la cadena ya está en mayúsculas, no resulta modificada. Por esta razón es conveniente aplicarle a la cadena la función strtolower() previamente al uso de alguna de estas dos últimas. Mira un ejemplo de uso en el script capitaliza.php:

En la página aparecerá lo siguiente:

La cadena original es esto es una cadena.
El efecto de ucfirst es Esto es una cadena.
El efecto de ucwords es Esto Es Una Cadena.

PHP nos proporciona la posibilidad de cambiar determinados caracteres por otros dentro de una cadena. Para ello, podemos usar la función str_replace(), que sustituye un fragmento de una cadena por otro, dejando inalterado el resto de la cadena original. Esta función recibe tres argumentos, separados por comas. El primero es el fragmento que deseamos sustituir; el segundo, el fragmento que deseamos que quede en la cadena y el tercero es la propia cadena sobre la que vamos a trabajar. Partimos de la sintaxis genérica de esta función:

str_replace ($frag1, $frag2, $original)

Esto hará que la función busque, en $original, todas las apariciones de $frag1 y las sustituya por $frag2. Como ya es habitual, veamos un ejemplo de funcionamiento, en el script cambiaTexto.php:

Cuando cargues este script verás el siguiente resultado:

Mi mesa es blanca y tu mesa es negra.
Mi silla es blanca y tu silla es negra.

Pon especial cuidado en la sintaxis de esta función. En versiones anteriores de PHP, el orden de los dos primeros argumentos estaba cambiado. Como estás utilizando PHP 7 no tienes ningún problema.

Esta función admite un cuarto parámetro opcional. Se trata de un valor numérico que indica cuantos cambios queremos hacer cómo máximo. Si hay más ocurrencias del fragmento a reemplazar que las que indicamos, las sobrantes no se sustituirán.

Ten en cuenta que esta función es sensible a mayúsculas y minúsculas, de modo que, si no escribes correctamente el fragmento que debe ser remplazado, PHP no podrá localizarlo y no efectuará las sustituciones previstas.

Otra función de sustitución con la que contamos en PHP es strtr(). Ésta se utiliza para sustituir todas las apariciones de fragmentos o caracteres de una cadena por otros. Dicho así suena muy parecido a lo que acabamos de ver con str_replace(), pero hay una diferencia. La function strtr() establece correspondencia entre los caracteres originales y los de sustitución, uno a uno. Supongamos que tiene que hacer un trabajo que implique la presentación de un texto sin acentos, y el texto original incluye letras acentuadas. En este caso escribiríamos algo así:

$nuevaCadena = strtr ($cadena, "ÁÉÍÓÚáéíóú", "AEIOUaeiou");

En este ejemplo, la variable $cadena contiene el texto original, con algunas letras acentuadas. En la variable $nuevaCadena se almacenará una copia del texto en la que las “Á” habrán sido sustituidas por “A”, las “É” se habrán remplazado con “E”, y, así, sucesivamente. Es decir, cada aparición de un carácter del segundo argumento, será sustituido por el correspondiente del tercero. Veamos un ejemplo en el script cambiaCaracter.php:

El resultado es el siguiente:

INÉS SÁNCHEZ es Técnica en Electrónica.
INES SANCHEZ es Tecnica en Electronica.

Observa que para una situación como ésta difícilmente podríamos usar str_replace(), ya que tendríamos que incluir esta función diez veces en el script para contemplar todos los posibles casos de vocales acentuadas, y eso solamente con el español. Imagina ahora si el texto está en francés, alemán o polaco, que tienen más variedad de tildes que nuestro idioma.

A menudo es necesario determinar si una cadena contiene una determinada subcadena. Para esto contamos con la función strstr(), que recibe dos argumentos separados por una coma. El primero es la cadena en la que hay que buscar. El segundo es la subcadena que deseamos encontrar. Vea el listado del script compruebaSubcadena.php:

Al ejecutar este script la función strstr() determina que la subcadena está dentro de la cadena. Sin embargo, no nos dice en qué posición. Y esto es algo que, a menudo, vamos a necesitar saber. Para ello contamos con la función strpos(). Con la misma sintaxis que la anterior, nos devuelve el punto donde la subcadena se encuentra en la cadena. A este efecto recuerda que los caracteres de una cadena se empiezan a contar por la izquierda y por 0, de modo que el primer carácter es el 0, el segundo el 1, y así sucesivamente. Observa el script posicion.php:

Observa en la primera línea resaltada la sintaxis de la función. En la segunda línea resaltada fíjate en la forma en que hemos usado el condicional. Esto es así porque si la subcadena existe dentro de la cadena, strpos() nos devuelve su posición, pero si no existe nos devuelve un valor lógico false. Para comprender la operativa de este condicional ejecuta primero el script, tal como está. Deberás obtener:

La subcadena se inicia dentro de la cadena en la posición: 8

A continuación, edita el código para cambiar la línea que define la variable $subcadena, de modo que quede, por ejemplo, así:

$subcadena = "XXXX";

Ejecuta de nuevo el script. El resultado esta vez te indicará que no se ha localizado la subcadena. Esto es la forma habitual de trabajar del intérprete de PHP. Las funciones, cuando no pueden obtener un resultado coherente con su objetivo, devuelven un valor lógico false. Esto resulta muy útil para poder determinar mediante condicionales, como hemos hecho aquí, si se ha obtenido o no un resultado. En muchos códigos verás cómo empleamos este recurso con cierta asiduidad.

ATENCIÓN. Esto es importante. Dado que PHP es un lenguaje muy débilmente tipado, es decir, que es muy flexible con los tipos de datos, en general se asume que un valor 0, o una cadena vacía ("") es equivalente a un false booleano, y cualquier otro valor numérico, o una cadena con cualquier contenido puede ser considerada por el intérprete cómo un true booleano.

Esto representa un problema en el uso de la función strpos(), así cómo en otras. En efecto. Si el fragmento que buscamos está al principio de la cadena, se encuentra en la posición 0. La función devuelve el valor 0. Si usamos un condicional del tipo if (!$posicion) { // Lo que sea el 0 será interpretado cómo false, y el condicional nos dirá que no ha encontrado lo que estábamos buscando. Por eso hay que recurrir al operador de no identidad, para que lo que se compruebe sea, realmente, el valor false, y no se interprete el 0 como false. Recuerda que el operador de identidad (o de no identidad, en este caso) comprueba estrictamente no sólo el valor de un dato, sino también su tipo.

Verifica en el código cómo el valor true o false devuelto por la función puede usarse en condicionales que, de este modo, se hallan supeditados a la ejecución de una función.

Después de hacer esta comprobación, vuelve a editar el script para dejarlo como estaba al principio.

LA CODIFICACIÓN URL

Cuando hablábamos del envío de formularios en un artículo anterior dijimos que, al enviar un formulario al servidor mediante el método get, los campos y los valores introducidos por el usuario se transmiten a través de la URL en un formato específico que se conoce como codificación URL. Considera las dos cadenas de texto siguientes:

Esta es una cadena de texto que será codificada como URL. ¿Cómo se mostrará? ¡¡VEÁMOSLO!!

y

Esta%20es%20una%20cadena%20de%20texto%20que%20ser%E1%20codificada%20como%20URL.%20%BFC%F3mo%20se%20mostrar%E1%3F%20%A1%A1VE%C1MOSLO%21%21

La primera cadena es una frase normal, completamente legible. La segunda cadena es, a priori, ilegible. Si la examinamos someramente por encima podemos intuir que, en realidad, es la misma que la primera, codificada de algún modo. El tipo de cifrado corresponde a las estipulaciones de los RFC 1630 y 1738. Pulsa en los enlaces para leerlos (ojo, esta documentación siempre la vas a encontrar en inglés).

Los RFC (Request For Comments) son documentos, universalmente aceptados, que regulan el funcionamiento y modo de uso de todos los protocolos de comunicaciones en Internet, métodos de cifrado y transmisión de datos, formatos de cabeceras de páginas, etc. Constituyen una riquísima fuente de información y documentación para programadores que se enfrenten a trabajos con redes de ordenadores y, en general, para cualquier persona que sienta curiosidad por estos temas. Para saber más acerca de los RFC accede a este enlace.

Básicamente se trata de lo siguiente. Existen determinados caracteres conocidos como “inseguros”. Esto se refiere al hecho de que la transmisión de dichos caracteres en una URL “abre” lo que se conoce como “agujeros de seguridad” o “bugs”. Son “puertas traseras” que puede utilizar un atacante para acceder a zonas de los servidores que normalmente son reservadas, o para abrir ficheros para los que hace falta algún tipo de autorización especial. Por razones de seguridad, estos caracteres no deben ser transmitidos en una URL. Y, sin embargo, son necesarios, así que hay que transmitirlos. Lo que se hace es codificarlos antes de la transmisión y decodificarlos en la recepción, siguiendo un patrón muy eficiente: se toma el código ASCII del carácter que queremos cifrar, se expresa con dos dígitos en hexadecimal y se le antepone el símbolo %. Así pues consideremos, por ejemplo, el más obvio de los caracteres inseguros: el espacio en blanco. Su código ASCII es el 32. En hexadecimal se expresa como 20. Por lo tanto, el espacio en blanco, cifrado según la codificación URL, queda como %20. Los caracteres inseguros son el espacio en blanco, las letras acentuadas (tanto mayúsculas como minúsculas), los signos de puntuación, excepto el punto y el guión (-), y los saltos de línea. Dicho de otro modo, los caracteres no sujetos a codificación son los dígitos del 0 al 9, las letras del alfabeto inglés, el punto y el guión.

PHP permite cifrar textos según la codificación URL. Para ello recurrimos a la función rawurlencode(), que recibe un texto “normal” y lo devuelve cifrado. Como es lógico, también existe una función que permite recuperar el texto original. Se trata de rawurldecode(). Observa el listado codificarUrl.htm:

Como ves es una página que contiene un formulario. En dicho formulario hay una caja de texto multilínea y los botones típicos de tipo submit y reset. Escribe un texto con caracteres diversos en la caja de texto. Al enviar el formulario se manda el contenido de la caja de texto al script codificarUrl.php, cuyo código aparece a continuación:

Carga en el navegador la página codificarUrl.htm, escribe en la caja de texto un contenido y pulsa el botón ENVIAR. Al cargarse el script codificarUrl.php verás el resultado de estas funciones.

En las líneas resaltadas en el código se ve cómo usamos las dos funciones, para cifrar el texto y para descifrarlo. Estas funciones tienen muchísima utilidad en varias situaciones. Una de las más corrientes es cuando el texto que el usuario escribe está destinado a almacenarse en una base de datos o en un archivo de disco. También es importante realizar esta codificación cuando el texto va a ser posteriormente mostrado formando parte de una página. Lógicamente, cuando llegue el momento de mostrarlo, será necesario descifrarlo previamente con la función rawurldecode(). De lo contrario, se mostraría al usuario un contenido codificado e ilegible.

Quiero hacer un pequeño inciso para llamar tu atención sobre un detalle en el script. Fíjate en la forma de introducir el texto, que está en variables de PHP, dentro de tablas HTML. Por ejemplo, así:

<td bgcolor="#C0C0C0">
   <?php echo $textoRecuperado; ?>
</td>

Este modo de integrar código PHP con la salida en HTML es perfectamente válido y muy práctico en infinidad de ocasiones. Fíjate en que, dentro de la celda de una tabla se inicia PHP, se muestra el contenido de una variable y se finaliza PHP para volver a HTML. Dentro de tus páginas podrás iniciar y detener el intérprete de PHP tantas veces como lo necesites. Más adelante aprenderemos también a incluir código del intérprete PHP dentro de JavaScript.

Llegados a este punto estarás pensando: “Bueno, sí. Pero el texto se transmite tal como el usuario lo ha tecleado. Cuando el formulario manda su contenido al script de PHP todavía no se ha hecho ningún cifrado sobre el texto, sino que éste se hace en el servidor, una vez que ya se ha iniciado el script PHP”. Pues sí, tienes razón. Pero yo sólo quería mostrarte estas funciones, para empezar. Ahora vamos a ver cómo se puede llevar a cabo “algo” para que el texto se envíe ya codificado.

Para eso tenemos que recurrir a un pequeño truco, muy usado en ciertos entornos, que consiste en contar con la ayuda de nuestro viejo amigo JavaScript. Observa el script urlConJs.htm:

Observa que el textarea no tiene atributo name. Eso es porque, cuando mandemos el formulario, no queremos que el contenido del textarea se envíe tal cómo lo hemos escrito. En lugar de eso le pedimos a JavaScript que use su función escape() y copie el contenido procesado en un campo oculto. El campo oculto sí que tiene atributo name, así que será este el par nombre-valor que realmente sea enviado al servidor. No vamos a entrar aquí en detalles acerca del comportamiento de JavaScript o sus funciones, porque queda fuera del propósito de este artículo. En su momento publicaremos otros al respecto.

Ejecuta este script. Verás que el usuario no percibe ninguna diferencia con respecto al anterior. No se ve que haya dos campos, ni se aprecia nada inusual. Cuando el usuario escribe algo en la caja de texto y pulsa el botón de envío, se ejecuta la función de JavaScript que, en este ejemplo, hemos llamado comprobarFormulario ().

Al pulsar el botón ENVIAR se carga el script urlConJs.php, cuyo código es el siguiente:

Observa el resultado en tu navegador. Como ves, hemos logrado enviar y recibir el texto ya cifrado.

Hay una cosa que tienes que tener en cuenta al emplear este recurso. Si tecleas tu texto en dos o más líneas (pulsando la tecla INTRO mientras escribes), verás que el texto se recupera cómo una sóla línea.0 Esto sucede porque el carácter de salto de línea que maneja PHP no corresponde con la etiqueta <br /> de XHTML, así que este último se ve incapaz de mostrarlo en la página. Lo que tenemos que hacer es buscar la secuencia del texto codificado que corresponde a un salto de línea y sustituirla por una etiqueta <br /> antes de hacer la decodificación. Y, para esto, nos va a ayudar la función str_replace() que hemos conocido en este mismo artículo. Mira la siguiente línea de ejemplo:

$textoRecuperado = rawurldecode(str_replace("%0D%0A", "<br />",$_POST["ocultoTexto"]));

Lo que hemos hecho ha sido identificar la secuencia que corresponde al salto de línea (%0D%0A), y sustituirla por <br /> antes de decodificar. Cuando dos o más funciones de PHP están anidadas una dentro de otra, como en este caso, el intérprete las resuelve desde dentro hacia fuera, de forma, que primero se resuelve la más interior, y la siguiente hacia fuera opera con el resultado de la anterior. En este caso, primero se ejecuta str_replace(), y rawurldecode() opera con el resultado obtenido.

De este modo, ya sabes cómo codificar texto para su envío por La Red, y su posterior almacenamiento en ficheros o bases de datos en el lado del servidor (el tema del almacenamiento será tratado en posteriores artículos). También sabes cómo recuperar los textos y mostrarlos en la página igual que los tecleó el usuario.

Para cifrar y descifrar textos puedes usar también las funciones urlencode() y urldecode(). Son similares a las que ya conoces. La diferencia más evidente que vas a apreciar es que los espacios en blanco son sustituidos por un signo + en lugar de por la secuencia %20. Esto se emplea cuando el cifrado debe adaptarse a un formato MIME estándar. Si en alguna ocasión se te presenta el caso, usa estas dos funciones. Si no, puedes usar el juego que quieras. Yo, personalmente, suelo inclinarme por las dos que hemos conocido en primer lugar.

En encodeDecode.php tienes un ejemplo de uso de estas dos últimas funciones. Ejecútalo en el navegador y ves el resultado. Como puedes comprobar, los espacios en blanco son sustituidos por signos +. Puedes hacer algunas pruebas cambiando el contenido de la variable $cadena, introduciendo distintos caracteres, para ver el comportamiento del script.

TRATAMIENTO DE CADENAS PARA HTML

En este apartado vamos a conocer algunas funciones que PHP incluye para el tratamiento de cadenas específico para su integración con HTML, así como para gestionar algunos aspectos del entorno web, aunque más adelante conoceremos detalles más avanzados.

Es muy común que el contenido de una variable alfanumérica deba ser mostrado en la página. Y también lo es que contenga determinados caracteres que no correspondan al alfabeto internacional. Como sabes, en XHTML se contempla que determinados caracteres deben ser sustituidos por las entidades. Por ejemplo, la letra ñ se escribe en una página como &ntilde; para que todos los navegadores del mundo puedan mostrarla sin problemas. Sin embargo, PHP no traduce estos caracteres directamente. Supongamos un documento como el siguiente:

Si cargas este código en tu navegador y tratas de ver el código fuente de la página te encontrarás con algo parecido a esto:

<html>
  <body>
    España
  </body>
</html>

Fíjate en la tercera línea. En realidad, para obtener una correcta programación en HTML, esta línea debería ser Espa&ntilde;a. PHP cuenta con una solución para estos casos. Se trata de la función htmlentities(). Ésta recibe como argumento una cadena y sustituye todos los caracteres no pertenecientes al alfabeto internacional por las entidades HTML oportunas, devolviendo la cadena lista para su presentación en la página. Observa el script entidades.php:

Cuando quieras ver el código fuente de la página en tu navegador, obtendrás lo siguiente:

<html>
  <body>
    Espa&ntilde;a  </body>
</html>

Como ves, la letra ñ ha sido convertida a su correspondiente entidad.

Otra función que también genera las entidades HTML de una cadena es htmlspecialchars(). Sin embargo, ésta es más antigua y no contempla todas las posibles entidades.

En PHP contamos con la función get_html_translation_table(), que genera una matriz con todas las entidades que contempla XHTML. Esta es una matriz asociativa, en la que la clave de cada elemento es el carácter y el valor es la entidad XHTML. Observa el script listaEntidades.php:

El resultado es la tabla que ves en tu navegador. Como ves, se genera una tabla con todas las entidades XHTML de caracteres no reconocidos en el alfabeto internacional. Observa en el listado del script cómo hemos empleado la función get_html_translation_table(). Como argumento le hemos pasado HTML_ENTITIES, una constante de PHP que hace referencia a la lista de entidades. La alternativa sería haberle pasado HTML_SPECIALCHARS. Sin embargo, el resultado es mucho más pobre.

ATENCIÓN. Lo de las entidades XHTML y las funciones PHP que las manejan, está bien para páginas estáticas, cuyo contenido varía poco o menos en el tiempo, y ademas son pequeñas y poco aspiracionales, pero es un sistema que se ha quedado obsoleto. PHP nos ofrece una solución mejor. Incluye al principio de cada una de tus páginas la siguiente línea:

header('Content-Type: text/html; charset=UTF-8');

La función header() sirve para enviar ciertas cabeceras al navegador. La veremos en detalle más adelante. De momento, basta saber que con la línea indicada estamos forzando que se use la codificación UTF-8, que es más completa y universal que la codificación por defecto que puede ser un latin o similar. Esto hará que las letras acentuadas, letras distintas del alfabeto inglés, y otros caracteres se muestren correctamente en el navegador sin tener que usar entidades.

Otra función bastante útil en ocasiones es parse_url(). Ésta recibe como argumento la dirección de un documento en Internet o en una Intranet, y devuelve una matriz con todos los elementos que forman dicha dirección. Observe el script datosUrl.php:

Realmente ésta es una dirección muy simple. Esta función puede sacar más datos, tal como se ve en la siguiente tabla:

DATO CONTENIDO
scheme El protocolo de comunicación. Normalmente suele ser http. Sin embargo, puede ser ftp, file, etc. dependiendo de la comunicación establecida con el recurso.
host La dirección IP o el nombre del servidor.
port El número de puerto en el que se espera que el servidor escuche.
user El login del usuario que accede al recurso.
password La clave de acceso del usuario especificado.
path La ruta, dentro del host, donde está el recurso al que se pretende acceder.
query Los datos que se le pasen al recurso, como es el caso de campos de un formulario enviados mediante get.

En la mayoría de los casos, una URL no tiene especificados todos los posibles valores, como es el ejemplo que hemos visto en el script datosUrl.php.

LAS CADENAS COMO MATRICES

PHP (así cómo algunos otros lenguajes) contempla la posibilidad de convertir una cadena alfanumérica en una matriz, y viceversa: tomar una matriz y colocar todos sus elementos, uno a continuación de otro, formando una cadena que, lógicamente, puede ser almacenada en una variable.

Para convertir una cadena en una matriz de datos debemos seguir dos pasos. En primer lugar, contaremos con la función chunk_split(). Ésta recibe como parámetro obligatorio la cadena que hay que dividir (o la variable que la contiene) y genera otra cadena en la que, cada 76 caracteres, introduce una secuencia “\r\n” (retorno de carro y nueva línea). Como parámetros opcionales podemos incluir el número de caracteres que se contarán en cada parte de la cadena resultante, en lugar de 76, así como la secuencia que actúa como separador, en lugar de “\r\n”. Por ejemplo, supongamos que quieres introducir una secuencia “*-*” cada 10 caracteres. La sintaxis a emplear sería la siguiente:

$cadenaNueva = chunk_split($cadenaOriginal,10,”*-*”);

Es importante que comprendas que chunk_split() NO modifica la cadena que recibe como argumento, sino que genera otra variable con la cadena modificada, así que la original permanece inalterada.

Una vez que tenemos la cadena modificada en otra variable llega el momento de usar la función explode(), que ya conocemos de un artículo anterior, para convertir dicha cadena en una matriz. Esta función recibe dos parámetros obligatorios. El primero es la secuencia que debe buscar como separador y que es la que establecimos en chunk_split(). El segundo es el nombre de la cadena modificada, generada por chunk_split(). La función explode() devuelve una matriz en la que creará un nuevo elemento cada vez que encuentre el separador. Así pues, la matriz tendrá tantos elementos como separadores haya, más uno. Para aclarar conceptos, veamos el uso combinado de estas dos funciones en el listado del script cadena2matriz.php:

Observa en las líneas resaltadas el uso de las dos funciones que acabamos de conocer. Además de lo que ya sabemos, recuerda que la función explode() admite un tercer parámetro numérico opcional, que hace referencia al número máximo de elementos que deberá tener la matriz. Si establecemos un número de elementos inferior a lo que la matriz necesitaría de por sí, el último elemento contendrá el final de la cadena, incluyendo los separadores como si fueran parte del elemento. De todos modos es muy raro que llegues a necesitar de este tercer parámetro.

En tu navegador puedes comprobar cómo la función chunk_split() añade a la cadena los caracteres especificados como separador (“*.*”) cada diez caracteres, tal como hemos indicado, y cómo la función explode() genera la matriz.

En PHP contamos también con la función join() que es un alias de implode(), que ya conocemos. Puedes usar la que desees.

El convertir una cadena a una matriz y viceversa puede parecer una operación fútil, pero viene muy bien para localizar y, en su caso, sustituir determinados fragmentos por otros y, si bien las funciones que hemos conocido en este apartado no son el único modo de hacer localizaciones y/o sustituciones, no está de más su conocimiento, ya que las encontrarás en varios scripts.

ENCRIPTACIÓN DE CADENAS

En ocasiones te encontrarás con una situación muy típica. Tienes que enviar un valor de una página a otra. En un artículo anterior vimos que puedes hacerlo mediante el uso de campos ocultos en un formulario. Sin embargo, los campos ocultos no están, realmente, demasiado ocultos. Evidentemente el usuario convencional no los ve. Fueron diseñados con el fin de pasar datos sin que resulten una molestia innecesaria a los ojos de quien usa nuestra página. Pero no han sido concebidos como un modo efectivo de esconder datos. Cualquiera puede abrir el código fuente de una página desde el navegador y ver los campos que constituyen el formulario y los valores que almacenan. En determinadas ocasiones no es conveniente que el usuario pueda ver estos datos. También nos encontraremos con casos en que determinada información deba almacenarse encriptada en archivos de disco o campos de una base de datos, a fin de que no esté al alcance de cualquiera que sienta una insana curiosidad.

PHP nos proporciona la función base64_encode() para encriptar una cadena. Esta función recibe como argumento una cadena y la devuelve encriptada. Si queremos mayor seguridad, podemos usarla combinada con strrev(), que invierte la posición de todos los caracteres de la cadena que recibe como argumento y genera una cadena inversa. Para recuperar una cadena encriptada con base64_encode() contamos con la función base64_decode(), que recibe como argumento la cadena encriptada y devuelve la cadena original, para poder seguir trabajando con ella. El uso de estas tres funciones está ilustrado en el script encripta64.php:

Observa la sintaxis de estas funciones. En cada paso hemos ido mostrando los resultados en el navegador. En el próximo artículo hablaremos de funciones numéricas y de fecha.

     

3 comentarios:

  1. Pingback: PHP-TUT-12 Manejo de datos (y II) » eldesvandejose.com

  2. Pingback: PHP-TUT-13 Expresiones regulares » eldesvandejose.com

  3. Pingback: PHP-TUT-16 Permisos para directorios y archivos » Recursos para programadores

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *