1. Code
  2. PHP

9 Funciones y Características Útiles en PHP que Usted Necesita Saber

Dos veces por mes, volvemos a visitar algunas de las publicaciones favoritas de nuestros lectores a lo largo de toda la historia de Nettuts+.
Scroll to top
11 min read

Spanish (Español) translation by Jorge Montoya (you can also view the original English article)

Dos veces por mes, volvemos a visitar algunas de las publicaciones favoritas de nuestros lectores a lo largo de toda la historia de Nettuts+. 

Incluso después de utilizar PHP por años, nos tropezamos con funciones y características que no conocíamos. Algunas de estas pueden ser muy útiles, sin embargo subutilizadas. Con eso en mente, he compilado una lista de nueve funciones y características increíbles de PHP con las que usted debería familiarizarse.  


1. Funciones con un Número Arbitrario de Argumentos

Ya puede que ya sepa que PHP le permite definir funciones con argumentos opcionales. Pero también existe un método para permitir un número completamente arbitrario de argumentos de función.

En primer lugar, aquí hay un ejemplo solo con argumentos opcionales:

1
2
// function with 2 optional arguments

3
function foo($arg1 = '', $arg2 = '') {
4
5
  echo "arg1: $arg1\n";
6
	echo "arg2: $arg2\n";
7
8
}
9
10
11
foo('hello','world');
12
/* prints:

13
arg1: hello

14
arg2: world

15
*/
16
17
foo();
18
/* prints:

19
arg1:

20
arg2:

21
*/

Ahora, veamos cómo podemos construir una función que acepte cualquier número de argumentos. Esta vez vamos a utilizar func_get_args():

1
2
// yes, the argument list can be empty

3
function foo() {
4
5
	// returns an array of all passed arguments

6
	$args = func_get_args();
7
8
	foreach ($args as $k => $v) {
9
		echo "arg".($k+1).": $v\n";
10
	}
11
12
}
13
14
foo();
15
/* prints nothing */
16
17
foo('hello');
18
/* prints

19
arg1: hello

20
*/
21
22
foo('hello', 'world', 'again');
23
/* prints

24
arg1: hello

25
arg2: world

26
arg3: again

27
*/

2. Uso de Glob() para Encontrar Archivos

Muchas funciones de PHP tienen nombres largos y descriptivos. Sin embargo, puede ser difícil saber qué hace una función llamada glob() a menos que ya esté familiarizado con ese término de otra parte.

Piense en ello como una versión más capaz de la función scandir(). Puede permitirte buscar archivos usando patrones.

1
2
// get all php files

3
$files = glob('*.php');
4
5
print_r($files);
6
/* output looks like:

7
Array

8
(

9
    [0] => phptest.php

10
    [1] => pi.php

11
    [2] => post_output.php

12
    [3] => test.php

13
)

14
*/

Puede obtener varios tipos de archivo como este:

1
2
// get all php files AND txt files

3
$files = glob('*.{php,txt}', GLOB_BRACE);
4
5
print_r($files);
6
/* output looks like:

7
Array

8
(

9
    [0] => phptest.php

10
    [1] => pi.php

11
    [2] => post_output.php

12
    [3] => test.php

13
    [4] => log.txt

14
    [5] => test.txt

15
)

16
*/

Tenga en cuenta que los archivos pueden ser devueltos con una ruta, dependiendo de su consulta:

1
2
$files = glob('../images/a*.jpg');
3
4
print_r($files);
5
/* output looks like:

6
Array

7
(

8
    [0] => ../images/apple.jpg

9
    [1] => ../images/art.jpg

10
)

11
*/

Si desea obtener la ruta completa a cada archivo, sólo puede llamar a la función realpath() en los valores devueltos:

1
2
$files = glob('../images/a*.jpg');
3
4
// applies the function to each array element

5
$files = array_map('realpath',$files);
6
7
print_r($files);
8
/* output looks like:

9
Array

10
(

11
    [0] => C:\wamp\www\images\apple.jpg

12
    [1] => C:\wamp\www\images\art.jpg

13
)

14
*/

3. Información Sobre el Uso de la Memoria

Observando el uso de la memoria de sus scripts, puede optimizar mejor su código.

PHP tiene un recolector de basura y un administrador de memoria bastante complejo. La cantidad de memoria utilizada por el script. puede subir y bajar durante la ejecución de un script. Para obtener el uso actual de la memoria, podemos usar la función memory_get_usage(), y para obtener la mayor cantidad de memoria utilizada en cualquier punto, podemos usar la función memory_get_peak_usage().

1
2
echo "Initial: ".memory_get_usage()." bytes \n";
3
/* prints

4
Initial: 361400 bytes

5
*/
6
7
// let's use up some memory

8
for ($i = 0; $i < 100000; $i++) {
9
	$array []= md5($i);
10
}
11
12
// let's remove half of the array

13
for ($i = 0; $i < 100000; $i++) {
14
	unset($array[$i]);
15
}
16
17
echo "Final: ".memory_get_usage()." bytes \n";
18
/* prints

19
Final: 885912 bytes

20
*/
21
22
echo "Peak: ".memory_get_peak_usage()." bytes \n";
23
/* prints

24
Peak: 13687072 bytes

25
*/

4. Información de Uso de la CPU

Para ello, vamos a utilizar la función getrusage(). Tenga en cuenta que esto no está disponible en plataformas Windows.

1
2
print_r(getrusage());
3
/* prints

4
Array

5
(

6
    [ru_oublock] => 0

7
    [ru_inblock] => 0

8
    [ru_msgsnd] => 2

9
    [ru_msgrcv] => 3

10
    [ru_maxrss] => 12692

11
    [ru_ixrss] => 764

12
    [ru_idrss] => 3864

13
    [ru_minflt] => 94

14
    [ru_majflt] => 0

15
    [ru_nsignals] => 1

16
    [ru_nvcsw] => 67

17
    [ru_nivcsw] => 4

18
    [ru_nswap] => 0

19
    [ru_utime.tv_usec] => 0

20
    [ru_utime.tv_sec] => 0

21
    [ru_stime.tv_usec] => 6269

22
    [ru_stime.tv_sec] => 0

23
)

24


25
*/

Eso puede parecer un poco críptico a menos que ya tenga un conocimientos de administración de sistema. Aquí está la explicación de cada valor (no es necesario memorizarlos):

  • ru_oublock: bloquear operaciones de salida
  • ru_inblock: bloquear operaciones de entrada
  • ru_msgsnd: mensajes enviados
  • ru_msgrcv: mensajes recibidos
  • ru_maxrss: tamaño máximo del conjunto de residentes
  • ru_ixrss: tamaño de memoria compartida integral
  • ru_idrss: tamaño de datos sin compartir
  • ru_minflt: reclamaciones de página
  • ru_majflt: fallos de página
  • ru_nsignals: señales recibidas
  • ru_nvcsw: cambios de contexto voluntarios
  • ru_nivcsw: cambios involuntarios de contexto
  • ru_nswap: intercambios
  • ru_utime.tv_usec: tiempo de usuario utilizado (microsegundos)
  • ru_utime.tv_sec: tiempo de uso del usuario (segundos)
  • ru_stime.tv_usec: tiempo del sistema utilizado (microsegundos)
  • ru_stime.tv_sec: tiempo del sistema utilizado (segundos)

Para ver cuánta potencia de CPU consumió el script, debemos mirar los valores de 'tiempo de usuario' y 'tiempo de sistema'. Las porciones de segundos y microsegundos se proporcionan por separado por defecto. Puede dividir el valor de microsegundos en 1 millón y agregarlo al valor de segundos, para obtener el total de segundos como un número decimal.

Veamos un ejemplo:

1
2
// sleep for 3 seconds (non-busy)

3
sleep(3);
4
5
$data = getrusage();
6
echo "User time: ".
7
	($data['ru_utime.tv_sec'] +
8
	$data['ru_utime.tv_usec'] / 1000000);
9
echo "System time: ".
10
	($data['ru_stime.tv_sec'] +
11
	$data['ru_stime.tv_usec'] / 1000000);
12
13
/* prints

14
User time: 0.011552

15
System time: 0

16
*/

A pesar de que el script tomó unos 3 segundos para ejecutarse, el uso de la CPU fue muy, muy bajo. Porque durante la operación de suspensión, el script realmente no consume recursos de CPU. Hay muchas otras tareas que pueden tomar tiempo real, pero no puede utilizar el tiempo de CPU, como esperar operaciones de disco. Por lo tanto, como puede ver, el uso de la CPU y la duración real del tiempo de ejecución no siempre son los mismos.

Aquí hay otro ejemplo:

1
2
// loop 10 million times (busy)

3
for($i=0;$i<10000000;$i++) {
4
5
}
6
7
$data = getrusage();
8
echo "User time: ".
9
	($data['ru_utime.tv_sec'] +
10
	$data['ru_utime.tv_usec'] / 1000000);
11
echo "System time: ".
12
	($data['ru_stime.tv_sec'] +
13
	$data['ru_stime.tv_usec'] / 1000000);
14
15
/* prints

16
User time: 1.424592

17
System time: 0.004204

18
*/

Eso llevó alrededor de 1,4 segundos de tiempo de la CPU, casi todo el tiempo del usuario, ya que no había llamadas del sistema.

El Tiempo del Sistema es la cantidad de tiempo que la CPU pasa realizando llamadas del sistema para el kernel en nombre del programa. Aquí hay un ejemplo de eso:

1
2
$start = microtime(true);
3
// keep calling microtime for about 3 seconds

4
while(microtime(true) - $start < 3) {
5
6
}
7
8
$data = getrusage();
9
echo "User time: ".
10
	($data['ru_utime.tv_sec'] +
11
	$data['ru_utime.tv_usec'] / 1000000);
12
echo "System time: ".
13
	($data['ru_stime.tv_sec'] +
14
	$data['ru_stime.tv_usec'] / 1000000);
15
16
/* prints

17
User time: 1.088171

18
System time: 1.675315

19
*/

Ahora tenemos un bastante tiempo de uso del sistema. Esto se debe a que el script llama a la función microtime() muchas veces, lo que realiza una solicitud a través del sistema operativo para obtener la hora.

También puede notar que los números no suman hasta 3 segundos. Esto es porque probablemente hay otros procesos en el servidor, así, y el script no estaba usando 100% de la CPU durante toda la duración de los 3 segundos.


5. Constantes Mágicas

PHP proporciona constantes mágicas útiles para buscar el número de línea actual (__LINE__), la ruta del archivo (__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 el espacio de nombre (__NAMESPACE__).

No vamos a cubrir cada uno de estos en este artículo, pero voy a mostrar algunos casos de uso.

Al incluir otros scripts, es una buena idea utilizar la constante __FILE__ (o también __DIR__, a partir de PHP 5.3):

1
2
// this is relative to the loaded script's path

3
// it may cause problems when running scripts from different directories

4
require_once('config/database.php');
5
6
// this is always relative to this file's path

7
// no matter where it was included from

8
require_once(dirname(__FILE__) . '/config/database.php');

El uso de __LINE__ facilita la depuración. Puede rastrear los números de línea:

1
2
// some code

3
// ...

4
my_debug("some debug message", __LINE__);
5
/* prints

6
Line 4: some debug message

7
*/
8
9
// some more code

10
// ...

11
my_debug("another debug message", __LINE__);
12
/* prints

13
Line 11: another debug message

14
*/
15
16
function my_debug($msg, $line) {
17
	echo "Line $line: $msg\n";
18
}

6. Generación de IDs Únicos

Puede haber situaciones en las que necesite generar una cadena única. He visto a muchas personas usar la función md5() para esto, aunque no es exactamente para este propósito:

1
2
// generate unique string

3
echo md5(time() . mt_rand(1,1000000));

En realidad, existe una función PHP llamada uniqid() que está destinada a ser utilizada para esto.

1
2
// generate unique string

3
echo uniqid();
4
/* prints

5
4bd67c947233e

6
*/
7
8
// generate another unique string

9
echo uniqid();
10
/* prints

11
4bd67c9472340

12
*/

Puede notar que aunque las cadenas son únicas, parecen similares por los primeros caracteres. Esto se debe a que la cadena generada está relacionada con la hora del servidor. Esto realmente tiene un buen efecto secundario, ya que cada nuevo ID generado viene más tarde en orden alfabético, por lo que se pueden ordenar.

Para reducir las posibilidades de obtener un duplicado, puede pasar un prefijo o el segundo parámetro para aumentar la entropía:

1
2
// with prefix

3
echo uniqid('foo_');
4
/* prints

5
foo_4bd67d6cd8b8f

6
*/
7
8
// with more entropy

9
echo uniqid('',true);
10
/* prints

11
4bd67d6cd8b926.12135106

12
*/
13
14
// both

15
echo uniqid('bar_',true);
16
/* prints

17
bar_4bd67da367b650.43684647

18
*/

Esta función generará cadenas más cortas que md5(), lo que también le ahorrará algo de espacio.


7. Serialización

¿Alguna vez ha necesitado almacenar una variable compleja en una base de datos o un archivo de texto? No tiene que encontrar una solución elegante para convertir sus arrays u objetos en cadenas formateadas, ya que PHP ya tiene funciones para este propósito.

Hay dos métodos populares de serialización de variables. He aquí un ejemplo que utiliza serialize() y unserialize():

1
2
// a complex array

3
$myvar = array(
4
	'hello',
5
	42,
6
	array(1,'two'),
7
	'apple'
8
);
9
10
// convert to a string

11
$string = serialize($myvar);
12
13
echo $string;
14
/* prints

15
a:4:{i:0;s:5:"hello";i:1;i:42;i:2;a:2:{i:0;i:1;i:1;s:3:"two";}i:3;s:5:"apple";}

16
*/
17
18
// you can reproduce the original variable

19
$newvar = unserialize($string);
20
21
print_r($newvar);
22
/* prints

23
Array

24
(

25
    [0] => hello

26
    [1] => 42

27
    [2] => Array

28
        (

29
            [0] => 1

30
            [1] => two

31
        )

32


33
    [3] => apple

34
)

35
*/

Este fue el método de serialización PHP nativo. Sin embargo, desde que JSON se ha vuelto tan popular en los últimos años, decidieron añadir compatibilidad con PHP 5.2. Ahora también puede usar las funciones json_encode() y json_decode():

1
2
// a complex array

3
$myvar = array(
4
	'hello',
5
	42,
6
	array(1,'two'),
7
	'apple'
8
);
9
10
// convert to a string

11
$string = json_encode($myvar);
12
13
echo $string;
14
/* prints

15
["hello",42,[1,"two"],"apple"]

16
*/
17
18
// you can reproduce the original variable

19
$newvar = json_decode($string);
20
21
print_r($newvar);
22
/* prints

23
Array

24
(

25
    [0] => hello

26
    [1] => 42

27
    [2] => Array

28
        (

29
            [0] => 1

30
            [1] => two

31
        )

32


33
    [3] => apple

34
)

35
*/

Es más compacto, y lo mejor de todo, compatible con javascript y muchos otros lenguajes. Sin embargo, para objetos complejos, se puede perder alguna información.


8. Compresión de Cadenas de Texto

Al hablar de compresión, por lo general pensamos en archivos, como archivos ZIP. Es posible comprimir cadenas largas en PHP, sin involucrar archivos comprimidos.

En el siguiente ejemplo vamos a utilizar las funciones gzcompress() y gzuncompress():

1
2
$string =
3
"Lorem ipsum dolor sit amet, consectetur

4
adipiscing elit. Nunc ut elit id mi ultricies

5
adipiscing. Nulla facilisi. Praesent pulvinar,

6
sapien vel feugiat vestibulum, nulla dui pretium orci,

7
non ultricies elit lacus quis ante. Lorem ipsum dolor

8
sit amet, consectetur adipiscing elit. Aliquam

9
pretium ullamcorper urna quis iaculis. Etiam ac massa

10
sed turpis tempor luctus. Curabitur sed nibh eu elit

11
mollis congue. Praesent ipsum diam, consectetur vitae

12
ornare a, aliquam a nunc. In id magna pellentesque

13
tellus posuere adipiscing. Sed non mi metus, at lacinia

14
augue. Sed magna nisi, ornare in mollis in, mollis

15
sed nunc. Etiam at justo in leo congue mollis.

16
Nullam in neque eget metus hendrerit scelerisque

17
eu non enim. Ut malesuada lacus eu nulla bibendum

18
id euismod urna sodales. ";
19
20
$compressed = gzcompress($string);
21
22
echo "Original size: ". strlen($string)."\n";
23
/* prints

24
Original size: 800

25
*/
26
27
28
29
echo "Compressed size: ". strlen($compressed)."\n";
30
/* prints

31
Compressed size: 418

32
*/
33
34
// getting it back

35
$original = gzuncompress($compressed);

Pudimos alcanzar casi el 50% de reducción de tamaño. También las funciones gzencode() y gzdecode() tienen resultados similares, utilizando un algoritmo de compresión diferente.


9. Función de Cierre de Registro

Hay una función llamada register_shutdown_function(), que le permitirá ejecutar algún código justo antes de que el script termine de ejecutarse.

Imagine que desea capturar algunas estadísticas de referencia al final de la ejecución del script, como cuánto tardó en ejecutarse:

1
2
// capture the start time

3
$start_time = microtime(true);
4
5
// do some stuff

6
// ...

7
8
// display how long the script took

9
echo "execution took: ".
10
		(microtime(true) - $start_time).
11
		" seconds.";

Al principio esto puede parecer trivial. Sólo agregue el código al final de la secuencia de comandos y se ejecuta antes de que finalice. Sin embargo, si alguna vez llama a la función exit(), ese código nunca se ejecutará.  Además, si hay un error fatal, o si el script es terminado por el usuario (presionando el botón Detener en el navegador), de nuevo puede no ejecutarse.

Cuando utiliza register_shutdown_function(), su código se ejecutará sin importar por qué el script ha dejado de ejecutarse:

1
2
$start_time = microtime(true);
3
4
register_shutdown_function('my_shutdown');
5
6
// do some stuff

7
// ...

8
9
10
function my_shutdown() {
11
	global $start_time;
12
13
	echo "execution took: ".
14
			(microtime(true) - $start_time).
15
			" seconds.";
16
}

Conclusión

¿Está al tanto de otras funciones de PHP que no son ampliamente conocidas pero que pueden ser muy útiles? Por favor, comparta con nosotros en los comentarios. ¡Y gracias por leer!