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/