Incluso después de trabajar con PHP desde hace muchos años, a veces
nos encontramos con funciones y funcionalidades o características de las
que no eramos conscientes. Algunas pueden ser útiles pero no se usan
mucho, ya sea por el tipo de proyecto o el nivel de tecnología que
tengamos. En este artículo comentaré unas cuantas funciones y
características de PHP que quizá no sabías.
Funciones en PHP con número arbitrario de argumentos
Seguro
que ya sabes que PHP permite definir funciones con argumentos
opcionales. Pero existe un método para permitir un numero arbitrario de
argumentos en las funciones.
Ejemplo de función con argumentos opcionales:
2 | function foo( $arg1 = '' , $arg2 = '' ) { |
Ahora, vamos a construir una función que acepte cualquier número de argumentos. Esta vez vamos a utilizar
func_get_args():
5 | $args = func_get_args(); |
7 | foreach ( $args as $k => $v ) { |
8 | echo "arg" .( $k +1). ": $vn" ; |
21 | foo( 'hello' , 'world' , 'again' ); |
Buscar y encontrar ficheros en PHP con GLob()
Muchas funciones en PHP tienen nombres largos y descriptivos, sin embargo es difícil saber que hace una función llamada
glob(), a no ser que lo busques en la documentación o ya la hayas usado previamente.
Es una función mucho más potente que
scandir() ya que también permite búsqueda de ficheros usando patrones.
También se pueden extraer múltiples tipos de ficheros de la siguiente manera:
2 | $files = glob ( '*.{php,txt}' , GLOB_BRACE); |
NOTA: Los archivos se pueden devolver con su ruta, dependiendo de la búsqueda que se haga
1 | $files = glob ( '../images/a*.jpg' ); |
Si quieres obtener la ruta completa de cada archivo, tendrías que llamar a la función realpath() en los valores retornados.
1 | $files = glob ( '../images/a*.jpg' ); |
4 | $files = array_map ( 'realpath' , $files ); |
Procesar con PHP información de la memoria usada
Monitorizando
la memoria usada de tus scripts serás capaz de optimizar tu código
mucho mejor. La monitorización ya sea en los servidores, base de datos
o en nuestro código siempre es un práctica muy aconsejable de realizar y
con la que tendremos una información valiosa de la calidad de nuestro software, con esta información se pueden hacer muchas “cosas” pero eso da para otro artículo.
PHP
tiene un complejo administrador de memoria, La cantidad total de
memoria que esta siendo usada por un script puede subir y bajar durante
la ejecución del mismo. Para obtener la memoria usada en un determinado
momento se tiene que usar la función
memory_get_usage(), para conseguir la cantidad más alta de memoria usada a lo largo de la ejecución del script usar la función
memory_get_peak_usage()
Pongamos a prueba el uso de la memoria con el siguiente ejemplo.
1 | echo "Bytes iniciales: " .memory_get_usage(). "n" ; |
7 | for ( $i = 0; $i < 100000; $i ++) { |
12 | for ( $i = 0; $i < 100000; $i ++) { |
16 | echo "Final: " .memory_get_usage(). " bytes n" ; |
21 | echo "Peak: " .memory_get_peak_usage(). " bytes n" ; |
NOTA:
Es muy posible que no os van a dar los mismo resultados que a mi,
porque el equipo donde ejecutáis vuestro código es diferente al mío, o
incluso si fuera idéntico tampoco tendría porque salir lo mismo. Todo
depende de la memoria que vaya a asignar vuestro sistema operativo y la
configuración que tengáis en el servidor Apache y PHP.
Información del uso de CPU
Para obtener la información del uso de la CPU en PHP usaremos la función
getrusage(). Por el momento no esta disponible en plataformas con Windows.
Explicación de cada valor:
- ru_oublock: block output operations
- ru_inblock: block input operations
- ru_msgsnd: messages sent
- ru_msgrcv: messages received
- ru_maxrss: maximum resident set size
- ru_ixrss: integral shared memory size
- ru_idrss: integral unshared data size
- ru_minflt: page reclaims
- ru_majflt: page faults
- ru_nsignals: signals received
- ru_nvcsw: voluntary context switches
- ru_nivcsw: involuntary context switches
- ru_nswap: swaps
- ru_utime.tv_usec: user time used (microseconds)
- ru_utime.tv_sec: user time used (seconds)
- ru_stime.tv_usec: system time used (microseconds)
- ru_stime.tv_sec: system time used (seconds)
Para
determinar cuanta energía ha consumido la CPU, habría que mirar a los
valores de ‘user time’ y ‘system time’. Los segundos y las porciones de
milisegundos son entregadas separadas por defecto. Se podría dividir el
valor de milisegundos por 1 millón, y añadir el resultado a los
segundos, para obtener el total de segundos como un número decimal.
Ver siguiente ejemplo:
6 | ( $data [ 'ru_utime.tv_sec' ] + |
7 | $data [ 'ru_utime.tv_usec' ] / 1000000); |
9 | ( $data [ 'ru_stime.tv_sec' ] + |
10 | $data [ 'ru_stime.tv_usec' ] / 1000000); |
A
pesar de que el script duró 3 segundos para ejecutarse, el uso de la
CPU es muy muy bajo. Durante la ejecución del sleep() el script no esta
consumiendo recursos de CPU. Hay otras muchas tareas que se ejecutan en
tiempo real pero que no consumen tiempo de CPU, como por ejemplo esperar
para operaciones de disco. Por lo que, como se puede ver, el uso de la
CPU y el tiempo de ejecución de un scipt no siempre coinciden.
Otro ejemplo:
2 | for ( $i =0; $i <10000000; $i ++) { |
8 | ( $data [ 'ru_utime.tv_sec' ] + |
9 | $data [ 'ru_utime.tv_usec' ] / 1000000); |
11 | ( $data [ 'ru_stime.tv_sec' ] + |
12 | $data [ 'ru_stime.tv_usec' ] / 1000000); |
Esta
operación ha llevado 1.4 segundos de tiempo de CPU, casi todas por
parte de tiempo de usuario ya que no existían otras llamadas al sistema.
El
tiempo del sistema (System time) es el total de tiempo de CPU gasta en
ejecutar llamadas por el kernel en el nombre del programa. Veamos un
ejemplo:
1 | $start = microtime(true); |
3 | while (microtime(true) - $start < 3) { |
9 | ( $data [ 'ru_utime.tv_sec' ] + |
10 | $data [ 'ru_utime.tv_usec' ] / 1000000); |
12 | ( $data [ 'ru_stime.tv_sec' ] + |
13 | $data [ 'ru_stime.tv_usec' ] / 1000000); |
Ahora
tenemos más uso del tiempo del sistema. Esto es porque el script llama a
la función microtime() varias veces, que ejecuta una petición a través
del sistema operativo para recoger la fecha.
Magic Constants
PHP provee de una herramienta super útil las:
magic constants al español constantes mágicas (que suena un poco peor,no?).
Para obtener la linea actual donde estamos(__LINE__), la ruta del
fichero (__FILE__), la ruta del directorio (__DIR__), el nombre de la
función (__FUNCTION__), el nombre de la clase (__CLASS__), el nombre del
método (__METHOD__) y namespace (__NAMESPACE__).
Este tipo de constantes son usada en desarrollo Open Source, como CakePHP, WordPress
y otros códigos donde cada desarrollador los instala en diferentes
rutas y el código debe ser capaz de determinar las rutas y cualquier
otra información para poder funcionar correctamente
3 | require_once ( 'config/database.php' ); |
7 | require_once (dirname( __FILE__ ) . '/config/database.php' ); |
Usar
__LINE__ hace que el debuging o la localización de errores sea mucho
más fácil. Puedes obtener el número de linea que esta fallando.
3 | my_debug( "some debug message" , __LINE__ ); |
10 | my_debug( "another debug message" , __LINE__ ); |
15 | function my_debug( $msg , $line ) { |
16 | echo "Line $line: $msgn" ; |
También
se podría hablar mucho sobre las constantes: __FUNCTION__, __CLASS__ y
__METHOD__ las cuales pueden ayudar muchísimo al trabajo con objetos y
con la creación y definición de patrones de diseño en el código, pero el
uso de éstas constantes para trabajar con objetos podría ser motivo de
un artículo tan sólo para esto. En la documentación de php
http://php.net/manual/en/language.constants.predefined.php hay otros consejos y ejemplos.
Generar IDs únicos
There
may be situations where you need to generate a unique string. I have
seen many people use the md5() function for this, even though it’s not
exactly meant for this purpose:
En muchas situaciones vamos a
necesitar generar identificadores o cadenas únicas. Confieso que yo
suelo hacer esto: md5(time()) para generar string únicos, aunque puede
que no sea 100% optimo. PHP propone la siguiente función específica para
llevar a cabo esta tarea,
uniqid().
El
inicio de la cadena suele ser similar entre los diferentes
identificadores que vamos generando, ya que el string generado está
relacionando con la fecha del servidor, es decir con la función time().
Esto tiene una ventaja ya que todos los ids generados van en orden
alfabético y se podrían ordenar.
Puedes enviar como primer
parámetro en la función un prefijo y puede poner a true el segundo valor
para aumentar la entropía, (usando el generador de congruencia lineal
combinado) al final del valor de retorno, lo que aumenta la probabilidad
de que el resultado será único. Por defecto devuelve una cadena de 13
caracteres, si se activa la entropía devuelve una cadena de 23
caracteres.
14 | echo uniqid( 'bar_' ,true); |
Esta función genera una cadena más corta que md5(), con lo que nos ayudará a ahorrar algo de espacio.
Serialización en PHP
La
serialización básicamente es el formateo de arrays u objetos para
convertirlos en un string. PHP ya tiene funciones que hacen esta tarea.
Hay 2 métodos para serializar variables, serialize() y unserialize():
10 | $string = serialize( $myvar ); |
18 | $newvar = unserialize( $string ); |
This
was the native PHP serialization method. However, since JSON has become
so popular in recent years, they decided to add support for it in PHP
5.2. Now you can use the json_encode() and json_decode() functions as
well:
Estos son los métodos nativos de PHP para serializar. Sin
embargo desde que JSON se volvió más popular, PHP sacó las funciones de
json_encode() y json_decode en la versión 5.2.
Si tienes una
versión de PHP inferior a 5.2 y llamas a las funciones de json_decode() o
json_encode(), te aparecerá un error similar a este PHP Fatal error:
Call to undefined function: json_encode(). Como he dicho, esta mejora
aparece en la versión 5.2, para más información leer el siguiente
artículo donde ya lo comentaba hace unos años
http://www.pedroventura.com/php/php-fatal-error-call-to-undefined-function-json_encode/
10 | $string = json_encode( $myvar ); |
18 | $newvar = json_decode( $string ); |
Comprimir cadenas en PHP
Cuando
hablamos de compresión, casi siempre nos referimos a ficheros, tales
como los archivos ZIP. Pero es posible comprimir largas cadenas en PHP
sin involucrar la creación de ningún archivo.
Para esta tarea usaremos las funciones gzcompress() y gzuncompress()
2 | "Lorem ipsum dolor sit amet, consectetur |
3 | adipiscing elit. Nunc ut elit id mi ultricies |
4 | adipiscing. Nulla facilisi. Praesent pulvinar, |
5 | sapien vel feugiat vestibulum, nulla dui pretium orci, |
6 | non ultricies elit lacus quis ante. Lorem ipsum dolor |
7 | sit amet, consectetur adipiscing elit. Aliquam |
8 | pretium ullamcorper urna quis iaculis. Etiam ac massa |
9 | sed turpis tempor luctus. Curabitur sed nibh eu elit |
10 | mollis congue. Praesent ipsum diam, consectetur vitae |
11 | ornare a, aliquam a nunc. In id magna pellentesque |
12 | tellus posuere adipiscing. Sed non mi metus, at lacinia |
13 | augue. Sed magna nisi, ornare in mollis in, mollis |
14 | sed nunc. Etiam at justo in leo congue mollis. |
15 | Nullam in neque eget metus hendrerit scelerisque |
16 | eu non enim. Ut malesuada lacus eu nulla bibendum |
17 | id euismod urna sodales. "; |
19 | $compressed = gzcompress( $string ); |
21 | echo "Original size: " . strlen ( $string ). "n" ; |
28 | echo "Compressed size: " . strlen ( $compressed ). "n" ; |
34 | $original = gzuncompress( $compressed ); |
Con esta técnica somos capaces de reducir al 50% el tamaño. También están las funciones
gzencode() y
gzdecode() que obtienen resultados similares pero con diferentes algoritmos de compresión
Lecturas recomendadas sobre compresión de archivos:
Registrar función de apagado (shutdown)
Hay una función llamada
register_shutdown_function() que te permite ejecutar código justo después de que termine la ejecución del script.
Imagina
que quieres capturas datos para estadísticas al final de la ejecución
de un script, como por ejemplo cuanto tiempo tardó en ejecutarse.
2 | $start_time = microtime(true); |
8 | echo "execution took: " . |
9 | (microtime(true) - $start_time ). |
En
este ejemplo parece un poco simple y sin mucho sentido, es un código al
inicio y otro al final y no parece que esta función se pueda estar
ejecutando al final del script, ya que está al final. Pero hay que tener
en cuenta, de que si se añade un exit(), el código devuelve un
fatal error
o incluso si el usuario detiene la ejecución del script con el botón de
parar del navegador esta función siempre se va seguir ejecutando a
pesar de todo.
Conclusión
Que te ha parecido? has
aprendido algunas funciones nuevas? Yo por lo menos he aprendido unas
cuantas y he refrescado otras que hacía mucho tiempo no había utilizado.
De
todas maneras si conoces de otras funciones que sean desconocidas pero
útiles no dudes en comentarlas, con tus comentarios aportas tu
experiencia y opinión al resto de lectores
Fuente:
http://net.tutsplus.com/tutorials/php/9-useful-php-functions-and-features-you-need-to-know/