mayo
31

Generar fechas al azar con PHP

Posted In: PHP, Programación by Mauro Zadunaisky

A veces sucede que debemos llenar una tabla con cientos de miles de registros para probar el rendimiento de una aplicación, de modo que no tengamos sorpresas el día de mañana cuando la base de datos crezca mucho. Por lo general los registros se llenan con información al azar y para eso hemos creado una función que genera fechas al azar dentro de un rango establecido.

	function random_date($from = 0, $to = null) {
		if (!$to) {
			$to = date('U');
		}
		if (!ctype_digit($from)) {
			$from = strtotime($from);
		}
		if (!ctype_digit($to)) {
			$to = strtotime($to);
		}
		return date('Y-m-d h:i:s', rand($from, $to));
	}
marzo
24

Tenemos el siguiente array

$r = array(
	0 => 'verde',
	1 => 'azul',
	2 => 'verde',
	3 => 'verde',
	4 => 'amarillo',
);

Y queremos eliminar los elementos duplicados, para lo cual tenemos dos opciones

1. array_values + array_unique

$r = array_values(array_unique($r));

2. array_keys + array_flip

$r = array_keys(array_flip($r));

¿Cuál es mejor?

Desde el punto de vista de legibilidad del código ambas opciones son válidas, ya que el comportamiento de cada una de las funciones utilizadas es bastante simple de comprender y se pueden consultar en el manual de PHP. Por lo tanto, lo único que puede determinar la conveniencia de una opción por sobre la otra es el tiempo de ejecución de cada una.

Para determinarlo, hemos realizado un benchmark. Estos son los resultados:

Opción 1 (array_values + array_unique)

-> Testing http://localhost/experimental/array_unique/1.php

Total Requests made: 1000
Total Time elapsed: 14.009807348251 (seconds)

Requests/Second: 71.379 req/sec
Average request time: 0.014 seconds
Standard deviation of average request time: 0.002
Longest/shortest request: 0.017 sec/0.004 sec

Opción 2 (array_keys + array_flip )

-> Testing http://localhost/experimental/array_unique/2.php

Total Requests made: 1000
Total Time elapsed: 13.918713331223 (seconds)

Requests/Second: 71.846 req/sec
Average request time: 0.014 seconds
Standard deviation of average request time: 0.003
Longest/shortest request: 0.017 sec/0.004 sec

Conclusión

La diferencia entre una opción y otra es prácticamente despreciable, así que la conclusión es que da lo mismo usar cualquiera.

Otra idea que podemos rescatar de esto es que realizar comparaciones entre funciones nativas de PHP realmente es un desperdicio de tiempo porque casi nunca se lograrán resultados significativos. Las verdaderas mejoras en la performance de una aplicación o website se consiguen atacando aquellas partes del código que mayores recursos consumen, como por ejemplo: consultas a base de datos, llamados excesivos a funciones recursivas, consumo de webservices, mala gestión de caché, etc.

marzo
21

En las últimas dos semanas tuve que realizar modificaciones en aplicaciones desarrolladas por otros programadores sin usar frameworks. En ambos casos noté que al ejecutar el código en local aparecían muchos errores de tipo notice que no se veían en producción. En el manual de PHP dice claramente que durante el desarrollo es recomendado tener activados los error notice:

Habilitar E_NOTICE durante el desarrollo tiene algunos beneficios. Para depuración: los mensajes NOTICE le avisarán de posibles errores en su código. Por ejemplo, se avisa del uso de valores no asignados. Es extremadamente útil para encontrar erratas y ahorrar tiempo de depuración. Los mensajes NOTICE le avisarán sobre un estilo malo. Por ejemplo, $arr[item] es mejor que sea escrito como $arr['item'] ya que PHP intenta tratar "item" como una constante. Si no es una constante, PHP asume que es un índice de cadena del array.

PHP por defecto viene configurado para ocultar los error notice, para activarlos hay que abrir el archivo php.ini y en la línea donde dice:

error_reporting = E_ALL & ~E_NOTICE

cambiarlo por

error_reporting = E_ALL

Después reiniciar Apache y listo, ya estarás un paso más cerca de ser un desarrollador web profesional.

marzo
17

Supongamos que tenemos un sitio que originalmente no fue preparado para múltiples idiomas y el cliente ahora nos pide una versión en inglés. Para simplificar vamos a suponer que tenemos un único modelo llamado Product que tiene un campo name, el cual ahora va a tener que ser guardado en dos idiomas.

CakePHP ya viene preparado para una situación así, sólo basta con crear la tabla i18n, adjuntar el TranslateBehavior al modelo, con el siguiente código:

var $actsAs = array('Translate' => array('name'));

Y listo, todo todo estará funcionando.

Sin embargo tenemos un problema: si el modelo ya tenía datos, veremos que desde el momento en que el behavior se agrega, estos datos ya no se verán cuando se haga un find(). Esto sucede porque la consulta SQL que realiza el Translate Behavior hace un JOIN entre la tabla del modelo (en este caso products) con la tabla i18n, y como la tabla i18n está vacía porque recién la creamos, la consulta no devuelve resultados.

La solución sería inicializar la tabla i18n con los datos que ya tiene la tabla products, lo cual se podría hacer mediante programación, pero es mucho más fácil escribiendo código SQL puro.

La siguiente consulta sirve para copiar los datos del campo name de la tabla products a la tabla i18n de modo que quede funcional para el Translate Behavior. Suponemos que los contenidos originalmente estaban publicados en español.

insert into i18n (select null, 'spa', 'Product', Product.id, 'name', Product.name from products as Product)

Este procedimiento hay que repetirlo para cada campo de cada modelo que queremos traducir.

No es una solución muy elegante ni tampoco muy automática, pero resuelve el problema de manera bastante rápida.

« Anterior