Programación web con PHP
Módulo 2.5: Algunas funciones de librería y otros elementos avanzados
Etiquetas PHP cortas
Además de encapsular el código PHP entre las marcas <?php y ?>, tenemos dos alternativas adicionales
1) Short open tags
Utilizar <?
y ?>
, si la directriz:
short_open_tag = on
está abilitada en php.ini
. No es muy recomendable, ya que en algunos hospedajes están obligatoriamente desconectadas.
2) Short echo tags
Utilizar <?=$variable ?>
, equivalente a <? echo $variable ?>
.
A partir de PHP 5.4, el uso de estas etiquetas están siempre habilitado, independientemente de que la directríz short_open_tag
no lo esté.
Cookies & Session
Podemos leer información de las cookies del navegador mediante el array global $_COOKIE
, y establecer valores en las cookies mediante setcookie()
.
http://php.net/manual/es/features.cookies.php
http://php.net/manual/es/function.setcookie.php
También podemos leer y establecer valores en el array global $_SESSION
, con las siguientes diferencias.
Los valores almacenados con setcookie()
se almacenan directamente en una cookie del navegador del usuario. Éste puede ver su contenido y manipularla en cualquier momento.
Los valores almacenados en $_SESSION
se guardan por defecto en unos ficheros con datos de sesión, pero se establece una cookie en el navegador del usuario con una clave autogenerada que identifica a ese usuario frente a los datos almacenados en $_SESSION
Los valores almacenados con setcookie()
se mantienen indefinidamente en el navegador o hasta que expiren según la fecha especificada, mientras que los datos y la cookie de $_SESSION
desaparece cuando se cierra la ventana del navegador.
Para escribir en una cookie, necesitamos una función específica setcookie(), mientras que para escribir en la sesión se puede hacer directamente estableciendo un valor de array en $_SESSION.
http://php.net/manual/es/reserved.variables.session.php
http://php.net/manual/es/reserved.variables.session.php
//Ejemplo setcookie
setcookie("TestCookie", $value, time()+3600); /* expira en una hora */
Header
La instrucción header() permite enviar cabeceras HTTP al navegador antes de que se comience a enviar el documento HTTP, que controlan cosas como una redirección a otra página, o si el documento debe ser almacenado en cache.
header('location: http://www.google.com');
Pero para que funcionen, es importante cuando se ejecute que no se haya comenzado a enviar el documento HTML al navegador. Es por esto que si el código que estamos utilizando en algún momento utiliza la instrucción header(), debemos asegurarnos que el fichero PHP empieza por <?php y no contiene ningún espacio antes, o que contenga un byte de BOM de UTF-8 que esté siendo mal interpretado por el servidor. Si estamos incluyendo varios ficheros, también es importante que estos no contengan ningún caracter o espacio adicional al cierre de la etiqueta final ?> (es recomendable incluso no cerrar dicha etiqueta, ya que no es necesario).
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
Declaración de funciones avanzada
Hay algunos conceptos avanzados de declaración de funciones que no hemos explicado hasta ahora:
-
Parámetros predeterminados: Si tras el nombre de los parámetros especificamos con = un valor opcional, podemos omitir utilizar ese parámetro al llamar a la función, y tomará ese valor por defecto especificado.
-
Declaraciones de tipo: Podemos especificar si una variable debe ser un objeto de una clase o interfaz en concreto anteponiéndolo antes del parámetro en la definición de la función (los tipos básicos solo se pueden especificar a partir de PHP 7).
-
Paso de parámetros por referencia: Si anteponemos & en la declaración de un parámetro de una función, será pasado por referencia. Esto quiere decir que las modificaciones que se realicen al parámetro serán hechas directamente sobre la variable original.
Desde PHP 5, los objetos siempre son pasados por referencia (lo que supone un gran ahorro de memoria en programas fuertemente orientados a objetos) por lo que el operador & de paso de parámetros no debería ser utilizado en condiciones normales, ya que se considera una mala práctica el modificar el valor de los parámetros pasados.
http://php.net/manual/es/functions.arguments.php
function miFuncion(&$paramObligatorioPorRef, MiClase $paramOpciona=null) {
//...
}
Programación funcional
Desde PHP 5.3, las funciones pueden utilizarse como parámetros, almacenadas en variables, o utilizadas como “expresiones lambda” (funciones anónimas) y Closures (funciones anónimas que son utilizadas inmediatamente).
Este paradigma de programación es enormemente utilizado en JavaScript, sobre todo en frameworks como jQuery.
echo preg_replace_callback('~-([a-z])~', function ($coincidencia) {
return strtoupper($coincidencia[1]);
}, 'hola-mundo');
// imprime holaMundo
$saludo = function($nombre) {
printf("Hola %s\r\n", $nombre);
};
$saludo('Mundo');
https://secure.php.net/manual/es/functions.anonymous.php
Conversión y comparación de tipos y objetos
Cuando tenemos variables que contienen datos de diferentes tipos, y realizamos operaciones con ellos, PHP intenta realizar una conversión entre ellos de la manera más conveniente posible. De esta manera, enteros son convertidos directamente a cadenas al realizar concatenación, etc.
En ocasiones esta conversión automática no es adecuada, y podemos querer forzarla nosotros por nuestra cuenta. Podemos hacerlo anteponiendo a la utilización de la función el tipo entre paréntesis que queremos forzar que sea el resultado.
http://php.net/manual/es/language.types.type-juggling.php
$foo = 10; // $foo es un integer
$str = "$foo"; // $str es un string
$fst = (string) $foo; // $fst es tambien un string
Dado que PHP convierte automáticamente los tipos siempre que es posible, esto hace que algunas comparaciones puedan dar como resultado que dos variables son iguales, cuando en realidad los datos que contienen son de tipos diferentes.
if (10=="10") echo "Parecen iguales";
Para esto existen los operadores === y !==, que no solo verificarán que los contenidos de las variables o expresiones comparadas sean equivalente, sino que además sean del mismo tipo.
if (10==="10") echo "Solo verdadero si son del mismo tipo";
else echo "No tiene el mismo valor y tipo";
Respecto a los objetos, con ==
se comparan de forma superficial los atributos de dos objetos, y que son de la misma clase, para considerarlos equivalentes. Con ===
el resultado es verdadero únicamente cuando ambas variables hacen referencia a la misma instancia de objeto de la misma clase.
http://php.net/manual/es/language.oop5.object-comparison.php
Fechas y horas
El procesamiento de fechas y horas es uno de los retos más interesantes y de uso más habitual en la programación, y en PHP tenemos a nuestra disposición unas potentísimas funciones para ayudarnos a trabajar con ellas.
Como suele pasar con PHP, tenemos varias alternativas que se utilizan de diferentes formas. A continuación vamos a enumerar algunos ejemplos de uso útiles.
Podemos utilizar la funcion date
para mostrar la representación de la fecha actual.
echo date("Y-m-d H:m:i");
http://php.net/manual/es/function.date.php
También podemos establecer una fecha concreta con mktime
para representarla luego con date
:
// Imprime: July 1, 2000 is on a Saturday
echo "July 1, 2000 is on a " . date("l", mktime(0, 0, 0, 7, 1, 2000));
http://php.net/manual/es/function.mktime.php
La función strtotime
nos permite especificar con expresiones sencillas de cadenas fechas para ser representadas por date:
echo date('Y-m-d', strtotime('-1 day')); //Fecha de ayer
http://php.net/manual/es/function.strtotime.php
Es probable que queramos expresar una fecha indicando el nombre del mes o del día de la semana, pero date
nos lo devuelve en principio en inglés. Una forma de conseguirlo en español es mediante la instrucción strftime
. Es preciso declarar antes la configuración de idioma del sistema mediante la función setlocale
.
setlocale(LC_ALL, 'es_ES');
echo strftime('%A',strtotime('+1 day')); //Día de la semana mañana
Hay que tener en cuenta que estos formatos son diferentes a los utilizados por date.
http://php.net/manual/es/function.strftime.php
http://php.net/manual/es/function.setlocale.php
date_diff
es una función que calcula la diferencia entre dos fechas. En realidad es un alias que devuelve un objeto responsable de su representación.
$datetime1 = date_create($date_1);
$datetime2 = date_create($date_2);
$interval = date_diff($datetime1, $datetime2);
return $interval->format('%a'); //Días de diferencia
El formato utilizado es diferente a los utilizados por date, más info en la referencia:
http://php.net/manual/es/function.date-diff.php
Todas estas funciones pueden ser utilizadas en su lugar según una semántica de orientación a objetos, partiendo de la clase DateTime. Esta sintaxis es más homogenea y generalizada, por lo que puede ser más conveniente.
$date = new DateTime('2000-01-01');
echo $date->format('Y-m-d H:i:s');
http://php.net/manual/es/book.datetime.php
printf, sprintf
Para enviar al navegador una representación en cadena del contenido de una variable, indicando un formato concreto, podemos utilizar la instrucción printf
.
printf("%'.09d\n", 123); //Resultado: 000000123
Más interesante es el uso de sprintf
, que en lugar de enviar directamente el contenido de una variable al navegador, la devuelve como cadena que puede ser luego almacenada en otra variable.
$formato = 'El %2$s contiene %1$04d monos';
$num = 5; $ubicacion = 'arbol';
echo sprintf($formato, $num, $ubicacion);
Consulte las referencias para conocer los diferentes formatos que pueden ser aplicados
http://php.net/manual/es/function.sprintf.php
http://php.net/manual/es/function.printf.php
Manejo de archivos
En PHP suele haber multitud de funciones que pueden ser utilizadas con el mismo propósito de manera ligeramente diferente. En este caso igualmente hay muchas alternativas para el manejo de ficheros.
Puedes consultar una lista completa de todas las funciones relacionadas con el manejo de ficheros en: http://php.net/manual/es/ref.filesystem.php
Además, estas funciones en muchos casos pueden utilizarse para leer contenidos desde URL, la salida procedente de procesos, utilizando una sintaxis similar.
Nosotros utilizaremos a continuación algunas de estas funciones para realizar diferentes operaciones sobre los ficheros.
Escritura y lectura
Muchas de estas funciones requieren que se realice una operación de apertura sobre el fichero, almacenando en una varible un manejador del fichero abierto, que es de tipo resource (recurso).
Al abrirlo, debemos especificar cuál es el propósito de trabajo con el fichero, si solo es para lectura, lectura+escritura, o solo escritura, con una serie de combinaciones especiales. Cuanto más específicos seamos, mejor funcionará nuestro código en cooperación con otros ejecutables que también estén trabajando sobre el fichero.
Alguno de los modos más comunes son:
- r: Solo lectura. Empezamos al principio del fichero.
- r+: Lectura y escritura. Empezamos al principio del fichero.
- w: Solo escritura, reinicia el fichero a vacio, si no existe lo crea.
- a: Solo escritura, si no existe el fichero lo crea. Empezamos al final del fichero.
Puedes consultar todos los modos de apertura en: http://php.net/manual/es/function.fopen.php
Una vez abierto, sobre dicho manejador se pueden invocar operaciones de lectura secuencial de lineas del fichero, realizando alguna operación con cada una de ellas, avanzar o retroceder en la posición considerada actual, o movernos al final del mismo para escribir información nueva.
Ejemplo de escritura
$myFile = "mi_log.txt";
//Abrimos el fichero en modo 'a', escritura al final del mismo
$fh = fopen($myFile, 'a') or die("No se pudo abrir el fichero");
$stringData = "Linea ejemplo 1\n";
fwrite($fh, $stringData);
$stringData = "Linea ejemplo 2\n";
fwrite($fh, $stringData);
fclose($fh);
Ejemplo lectura linea a linea
//Abrimos el fichero en modo 'r', lectura desde el principio
$handle = fopen("inputfile.txt", "r");
if ( ! $handle ) {
echo "Error abriendo el fichero";
return;
}
while ( ( $line = fgets($handle) ) !== false) {
echo $line.'<br>';
}
fclose($handle);
Lectura completa, Directorios
Otras funciones interesantes son las siguientes.
Leer un archivo de texto completo y guardar su contenido en una variable
$contenido_leeme_completo = file_get_contents('readme.txt');
Comprobar si un archivos existe
if ( file_exists($ruta_fichero) ) echo 'Fichero encontrado';
Listar todos los archivos de una carpeta
if( is_dir($carpeta) ) {
if( $dir = opendir($carpeta) ) {
while( ( $archivo = readdir($dir) ) !== false ) {
if ( $archivo != '.' && $archivo != '..'
&& $archivo != '.htaccess') {
echo '$carpeta.'/'.$archivo.'<br>';
}
}
closedir($dir);
}
}