Todas las entradas por Rubén Lacasa Mas

Uso de Foreach y For (Parte II el Bucle Foreach) – PHP Tips

PHP Programming languageEn la primera entrada del Uso de Foreach y For hablaba sobre el uso del bucle for

Veamos primero la definición del constructor foreach en la documentación de PHP:

Constructor Foreach

El constructor foreach proporciona un modo sencillo de iterar sobre arrays. foreach funciona sólo sobre arrays y objetos, y emitirá un error al intentar usarlo con una variable de un tipo diferente de datos o una variable no inicializada. Existen dos sintaxis:

foreach (expresión_array as $valor)
    sentencias
foreach (expresión_array as $clave => $valor)
    sentencias

La primera forma recorre el array dado por expresión_array. En cada iteración, el valor del elemento actual se asigna a $valor y el puntero interno del array avanza una posición (así en la próxima iteración se estará observando el siguiente elemento).

La segunda forma además asigna la clave del elemento actual a la variable $clave en cada iteración.

Recorrer Arrays

Tal como dice la definición foreach nos sirve para recorrer arrays de una manera sencilla, bastante mas sencilla que con el bucle for, ya que no necesitamos conocer la longitud del array para recorrerla y el array puede tener claves tanto numéricas como no numéricas.


$array = array('Uno'=>'Hola', 'Dos'=>'Mundo, 'Tres' => 'Hello');

// Mostramos todas los valores del array

foreach ($array as $var) {

echo $var.PHP_EOL;

}

// Mostramos todas las claves y los valores del array

foreach ($array as $key => $var) {

echo $key .  " " . $var . PHP_EOL;

}

Recorrer objetos

Otra de las características que tiene foreach es la posibilidad de iterar sobre objetos, es decir, podriamos mostrar por pantalla todas las propiedades de un objeto.


$coche = new stdClass();
$coche->color = 'rojo';
$coche->ruedas = '4';
$coche->puertas = '3';
$coche->combustible = 'gasolina';

foreach ($coche as $key => $var) {
echo $key. " " . $var .PHP_EOL;
}

¿Podemos modificar los valores del array/objeto usando el foreach?

La respuesta es si, aunque con matices. Cuando recorremos un array o un objeto con foreach no recorremos el objeto en si sino una copia de ese objeto la cual se destruye una vez finalizada la iteración. Para poder modificar los valores tenemos que pasar el valor por referencia


foreach ($coche as $key => &$var) {
$var = $var." modificado";
}

Aqui el bucle foreach nos recorrería el array/objeto $coche y modificaría sus valores añadiendo «modificado» al final de cada uno de ellos.

Referenciar $var sólo es posible si el array iterado puede ser referenciado (es decir, si es una variable). El siguiente código no funcionará:


foreach ( array(1, 2, 3) as &var) {

$var = $var * 2;

}

Es decir, el array/objeto tiene que estar definido fuera del foreach para que pueda ser referenciado.

Utilizar arrays anidados con list PHP >= 5.5.0

Una de las novedades de la versión 5.5.0 de PHP es la posibilidad de recorrer un array de arrays y utilizar el array interior en las variables del bucle proporcionando list() como el valor.

// Este codigo solo funciona con PHP >= 5.5.0
$array = [
    [1, 2],
    [3, 4],
];

foreach ($array as list($a, $b)) {
// $a contiene el primer elemento del array interior,
// y $b contiene el segundo elemento.
echo "A: $a; B: $b\n";
}
/* Mostrara
A: 1; B: 2
A: 3; B: 4
*/

http://es1.php.net/manual/es/control-structures.foreach.php

Enhanced by Zemanta

Uso de Foreach y For (Parte I el Bucle For) – PHP Tips

Hace unos días @chupetho76 pedía en Twitter  tips para usar el foreach, en base a esa petición voy ha hacer un tips en el cual explicar el for, el foreach y sus diferencias.
En esta primera entrada de una serie de tres explicare el bucle for.

Bucle For

El manual de PHP define el bucle for como:

Los bucles for son los más complejos en PHP. Se comportan como sus homólogos en C. La sintaxis de un bucle for es:

for (expr1; expr2; expr3)
    sentencia

La primera expresión (expr1) es evaluada (ejecutada) una vez incondicionalmente al comienzo del bucle.

En el comienzo de cada iteración, se evalúa expr2. Si se evalúa como TRUE, el bucle continúa y se ejecutan la/s sentencia/s anidada/s. Si se evalúa como FALSE, finaliza la ejecución del bucle.

Al final de cada iteración, se evalúa (ejecuta) expr3.

Cada una de las expresiones puede estar vacía o contener múltiples expresiones separadas por comas. En expr2, todas las expresiones separadas por una coma son evaluadas, pero el resultado se toma de la última parte. Que expr2 esté vacía significa que el bucle debería ser corrido indefinidamente (PHP implícitamente lo considera como TRUE). Esto puede no ser tan inútil como se pudiera pensar, ya que muchas veces se debe terminar el bucle usando una sentencia condicional break en lugar de utilizar la expresión verdadera del for.

El bucle for es uno de los mas comunes en programación, haciendo un poco de memoria rápida creo que esta presente en la mayoría de lenguajes de programación, aunque la estructura puede variar un poco.

Su uso mas común, es el repetir un numero de veces una secuencia predeterminada.

for ($i=0; $i < 10; $i++) {
    echo "Hola, soy el saludo numero " . $i . PHP_EOL;
}

Este código nos mostrara el mensaje 10 veces y los números que aparecerán serán del 0 al 9.

El análisis de las expresiones en este ejemplo seria: Desde que $i es 0 y mientras $i sea menor que 10 suma 1 a $i. En la primera pasada el valor de $i es 0 ya que la suma la efectúa en la siguiente iteración. Si quisiéramos que el primer numero fuera 1 tendriamos que cambiar el $i=0 a $i=1.

¿Si cambiaramos el $i++ a ++$i, se empezara desde el 1?

La respuesta a esta pregunta es no, ya que la expr2, como dice la definición de arriba si bien se evalúa al principio, el resultado se toma al final, por lo tanto el primer valor en ambos casos es 0.

Otras características del bucle for, es que se pueden poner mas condiciones dentro de las expresiones, separadas por comas.

for ($i=0, $j=9; $i < 10, $i++, $j--) {
    echo "Hola, soy el saludo numero ". $i ." quedan ". $j ." . PHP_EOL;
}

Este código nos mostraría por ejemplo «Hola, soy el saludo numero 0 quedan 9», e iría incrementando el $i y decreciendo el $j.

También podemos dejar alguna expresión vacía, aunque tenemos que tener cuidado a la hora de escapar del bucle ya que podemos caer en uno de los problemas que tiene el bucle for, entrar en bucle infinito.

for ($i = 1; ; $i++) {
    if ($i > 10) {
        break;
    }
    echo $i;
}

En este ejemplo la expr1 esta vacía, y controlamos con un if si el valor es mayor que 10, si lo es, escapamos del bucle con el break;

Recorrer cadenas de texto

Otro uso que puede tener el for es recorrer cadenas de texto carácter a carácter.

$cadena = "Hola mundo";
for ($i=0; $i < strlen($cadena); $i++) {
    echo $cadena[$i] . PHP_EOL;
}

Este código nos mostrara por pantalla carácter a carácter la cadena de texto, una por linea.

Recorrer Arrays

También podemos recorrer arrays con el bucle for

$array = array('Hola', 'Mundo', 'Hello', 'World');
for ($i=0; $i < count($array); $i++) {
    echo $array[$i].PHP_EOL;
}

En este ejemplo mostramos por pantalla cada uno de los elementos del array.

Recorrer letras

for ($i='a'; $i < 'z'; $i++) {
    echo $i.PHP_EOL; // Mostraria a, b, c, d, e.. hasta la y
}

Si quisiéramos mostrar el abecedario completo, hasta la z tendríamos que hacerlo de otra manera ya que la comparación en la expresión $i <= ‘z’ no funcionara y nos mostrara hasta ‘yz’. Para mostrar hasta la z podemos, o bien sustituir en la función anterior la ‘z’ por ‘aa’ o bien hacer el bucle asi:

for ($i ='a'; ; $i++ ) {
    echo $i.PHP_EOL; // Mostrariamos de la a hasta la z
    if ($i == 'z') {
        break;
    }
}

En este ejemplo vemos también el no uso de la expr1 y la salida del bucle por medio del break dentro de una condición.

Este bucle también funcionaria con las mayúsculas, y el abecedario que mostrara por pantalla es el ingles (sin ñ).

Problemas del For

Los mayores problemas del for son el entrar en bucle infinito y el desbordamiento de buffer.

Tanto en el primero como en el segundo es muy fácil caer, es tan simple como confundirse en la expr1, y establecer que se remita mientras el valor sea menor que 0 » $i > 0″ y en el desbordamiento, el cual es mas común al recorrer arrays es establecer el numero máximo mayor que el numero de elementos. En el ejemplo de la cadena de texto he usado strlen para detectar la longitud de cadena y en el del array el count para contar el numero de elementos del array, tanto en uno u otro el criterio lo he establecido de la siguiente manera «$i < numeroTotal» en muchos sitios se utiliza este otro criterio «$i <= numeroTotal -1» que viene a significar lo mismo que el anterior pero mas corto.

¿Se pueden recorrer arrays con clave no numérica con el bucle for?

Sin tener el cuenta el ejemplo del bucle del alfabeto, la respuesta simple seria no, pero podríamos recorrer un array de claves no numéricas si este tiene las claves definidas como una de esas letras, siempre y cuando las letras estuvieran ordenadas, y no faltara ninguna entre medio, ya que si no devolvería error. Luego otra manera, que no seria directa seria crear una matriz numérica que tuviera como valores las claves del array que queremos recorrer.

http://es1.php.net/manual/es/control-structures.for.php

Enhanced by Zemanta

Archivos y carpetas desaparecidos del Escritorio – Windows Tips

El otro dia, a un ordenador con windows, de un compañero le desaparecion todas las carpetas y los ficheros que tenia en el escritorio, eso si los enlaces a las aplicaciones si que estaban, y como no me lo trajo a ver si podia hacer algo, ‘tu eres el informatico, mira a ver si puedes arreglarlo’ me dijo. Asi que primero me puse a mirar en el directorio a ver si en realidad habia ficheros en el escritorio, no sea que se hubieran borrado, y ahi estaban. Total que me puse a googlear y descubri esta solucion en la pagina de soporte de microsoft, y siguiendo la primera opcion que proponen, editando el registro, y una vez reiniciafo, todoo volvio a su sitio.
http://support.microsoft.com/kb/947215/es

¿Por que el botón reset no vacia los campos hidden? – HTML Tips

Hoy mientras desarrollaba un formulario y comprobaba los datos que enviaba me he dado cuenta de algo que en todos los años que llevo programando no me había dado cuenta, o quizá no me había visto en esa situación. Explico el escenario, tengo un formulario en el cual pongo un rango de fechas y luego en otro campo tengo un autocompletar el cual cuando marco la selección, se queda el nombre en el campo visible y el id en un campo hidden. Al darle a buscar pues me busca los datos relacionados de ese id en ese rango de fechas. Pues bien, a la vez del botón enviar, he puesto un botón reset para limpiar el formulario, y me he dado cuenta que si por ejemplo buscaba solo entre rangos de fechas, sin buscar nada en el autocompletar, me buscaba filtrando por los datos anteriores.

Depurando he visto que si no ponía nada en el campo autocompletar ( el cual al cambiar establecía el valor en el campo hidden) este se mantenía con el valor establecido en la búsqueda anterior.

A esto uno se pregunta ¿el reset no lo borraba todos los datos de un formulario?, pues la respuesta es si y no.

Vamos en la documentación de la w3.org que nos dice acerca del estado hidden en los inputs

«El estado hidden representa un valor el cual no esta permitido que el usuario lo examine o lo manipule».

Y la definición de reset dice «El estado reset de un button representa un button que cuando se activa restablece el formulario».

Con estas definiciones, de primeras pensaríamos que no tiene sentido que al pulsar el reset  no se restablezcan los valores de un hidden, pero reflexionemos un momento y hagamosnos una pregunta ¿quien establece el valor del campo hidden? ¿el usuario? ¿o nosotros con una programación? La respuesta es la segunda, el usuario no establece el valor del campo hidden ni lo puede modificar, y la acción del reset la efectúa el usuario, por lo tanto, no puede modificar el valor del hidden.

Para solucionar esto, si estamos usando jQuery podemos hacerlo de una manera muy sencilla

$('button[type=reset]').click(function(){
    $('#idCampoHidden').val('');
});

En este ejemplo estoy usando button, y serviria igual poniendo input[type=reset] y luego en el nombre del campo, donde pone #idCampoHidden, lo sustituiremos por #nuestrocampohidden.
El estado hidden http://www.w3.org/community/webed/wiki/HTML/Elements/input/hidden

El estado reset http://www.w3.org/community/webed/wiki/HTML/Elements/input/reset

Regla de la suma en bases de datos – MySQL Tips

Esta entrada no es específicamente para bases de datos MySQL, y se puede aplicar a cualquier otra base de datos.

Este es un pequeño truco que utilizo a la hora de explicar a alguien como decidir que tipo de dato a establecer a la hora de crear campos en una tabla en una base de datos, y es hacernos la siguiente pregunta ¿vas a sumarlo?, si la respuesta es no el tipo de campo puede establecerse de tipo varchar y si vamos a sumarlo sera de tipo numérico. Por ejemplo, los códigos postales o los teléfonos, ¿vamos a sumar códigos postales o teléfonos? la respuesta es no, por lo tanto los pondremos como tipo varchar, además en el tema de los códigos postales no hay tanto problema pero en el tema de los teléfonos… cada usuario te lo puede poner de cualquier manera, y si ponemos controles de validación del teléfono, pero al final lo que queremos es tener el teléfono del usuario.

Ficheros .user.ini – PHP Tips

Una de las novedades que trajo la versión 5.3 de PHP fue la de soportar ficheros INI, al estilo .htaccess a nivel de directorios, siempre y cuando lo tengamos configurado el SERVER API como CGI/FastCGI.

Esto quiere decir que, al igual que podemos especificar con .htaccess propiedades en cada directorio, podemos hacerlo con PHP a nivel de directorio o a nivel de raíz del sitio. Por ejemplo, si tenemos nuestra web en un hosting externo lo mas normal es que no podamos cambiar propiedades en el php.ini, pues bien, lo que si podemos hacer es crear nuestro fichero .user.ini y especificar esas propiedades en ese fichero, pero no todas, solo se reconocerán las configuraciones que tengan los modos PHP_INI_PERDIR y PHP_INI_USER.

Mas Información http://www.php.net/manual/es/configuration.file.per-user.php

Enhanced by Zemanta

Mejorar la velocidad de nuestro sitio Moodle

Uno de los sitios que gestiono es una plataforma de formación basada en Moodle, y la verdad que es bastante completa y tiene todo lo que una plataforma de formación puede necesitar, aunque algunas cosas, en mi opinión son mejorables, y se podrían presentar de una manera mas clara.

Pero dentro de las cosas que mas me preocupaban era lo lento que funcionaba el sitio, y la verdad no comprendía como una plataforma con tanta comunidad detrás de ella y tan usada funcionara tan lenta. Primero pensé que podría ser del servidor,  pero la única web que tenia problemas de rendimiento era esta. Hasta que un día googleando descubrí esta pagina http://opensourceelearning.blogspot.com.es/2012/10/why-your-moodle-site-is-slow-five.html y la verdad, realizando los 5 pasos, y algún otro mas, la velocidad y el rendimiento de la plataforma se ha visto muy mejorado.

Los pasos que nos indica en la web son los siguientes:

  1. Deshabilitar las Copias de seguridad automáticas.  Esto se hace desde Administración del sitio > Cursos > Copias de seguridad > Copia de seguridad programada. Si esta opción no note diferencia, supongo que el problema puede venir cuando se realiza la copia de seguridad que baja el rendimiento.
  2. Deshabilitar las Estadísticas.  Esto se hace desde Administración del sitio > Características avanzadas. Esta opción me mejoro mucho el rendimiento.
  3. Deshabilitar el modo de diseño de temas. Esto se hace desde Administración del sitio > Apariencia > Temas > Ajustes de temas. Esta opción me mejoro mucho el rendimiento.
  4. Establecer el Mantener registros para igual o menor a 365 días. Esto lo establecemos desde Administración del sitio > Servidor > Limpieza. Esta opción no la cambie ya que necesito tener registros de muchos años atrás.
  5. Deshabilitar Usar la base de datos para información de la sesión. Esto se hace desde Administración del sitio > Servidor > Gestión de la sesión. Esta también mejoro mucho el rendimiento del sitio, y como apunte decir que no os asustéis si una vez deshabilitada se cierra la sesión, es normal, se vuelve a iniciar listo.

A parte de estos 5 puntos que nos recomiendan en esa web, hay otra cosa que hay que tener en cuenta y que a mi me ha servido para mejorar el rendimiento del sitio, y es eliminar paneles innecesarios en las paginas, es decir, usar solo los necesarios, y si tenéis que mostrar listados de cursos por pantalla intentar limitar el tamaño a mostrar a 10.

Espero que os sirvan estos consejos.

 

 

Ocultar la extensión de nuestras paginas web – Apache Tips

Apache Web Server

A veces, por el motivo que sea, puede que no nos interese que los visitantes que accedan a nuestra pagina web sepan como esta hecha, algunas veces este motivo es por motivos de seguridad, y otras, por motivos de posicionamiento web, queda bastante mejor tener un enlace de la manera http://midominio.com/contacta que http://midominio.com/contacta.php .

Si el servidor en el cual esta nuestra web es Apache y tiene el mod_rewrite habilitado podemos hacerlo creando un fichero .htaccess en la raíz de nuestro sitio de la siguiente manera:


Options Indexes FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ – [NC,L]
RewriteRule ^([A-Za-z0-9-]+)/?$ $1.php
ErrorDocument 404 /404.php

view raw

.htaccess

hosted with ❤ by GitHub

Este fichero esta configurado para ficheros php, si lo queremos hacer con ficheros html o htm solo tenemos que cambiar donde pone .php en la linea 7 por .html o .htm.

Decir también que la ultima linea no es necesaria, pero a mi me gusta ponerla ya que así evitamos que si alguien «escribe mal» la ruta no salga un error de servidor. Lo de «escribe mal» lo pongo entre comillas ya que muchas veces se hace intencionadamente con el único objetivo de conocer las características del servidor en el cual se esta ejecutando la web, así que no cuesta nada crear nuestra propia pagina de error o bien que aparezca la principal del sitio.

Enhanced by Zemanta

About:robots en Firefox

Muchas de las aplicaciones que usamos a diario tienen estos «easter eggs» o huevos de pascua, los cuales se muestran cuando escribimos algo o cuando pulsamos algún botón o botones en un orden especifico.

Por ejemplo si abrimos una nueva pestaña en el Firefox y tecleamos en la barra de direcciones about:robots nos saldrá la siguiente pagina.
Bienvenidos Humanos

Como curiosidad decir que todas la frases que aparecen tienen relación con algún famoso robot, y si os apetece podéis darle al botón Reintentar y ver que sucede.

Enhanced by Zemanta

Como extraer un valor numerico de una cadena en una consulta MySQL – MySQL Tips

MySQLPuede ser que alguna vez nos veamos en la necesidad que extraer los números que hay almacenados dentro de campo en el cual están combinados los números y texto, por ejemplo ( 1 litro, 1 hora, 25 euros, $4,  horas), etc…)

Si el numero esta al principio de la cadena

En estas situación la solución es muy sencilla, y es la que nos encontraremos la mayoría de las veces, simplemente utilizamos la función CONVERT().

CONVERT() es una función que nos convierte datos entre distintos tipos de caracteres. A esta función le pasaremos como parámetros la cadena o el campo en el cual este el dato que queramos extraer y SIGNED, el cual indicara que queremos que nos lo convierta a un entero, la función quedaría así:


SELECT CONVERT('25 euros', SIGNED)

Esta consulta devolverá 25, pero que pasaría si el numero no estuviera al principio de la cadena de texto,  pues que nos devolverá 0. Por lo tanto solo nos sirve la función CONVERT() cuando la cadena empieza con numero si no no sirve.

Si el numero esta en el segundo lugar

Esta situación es un poco mas complicada, y tendremos que utilizar REGEXP() e IF.  Hace unos días ya hice una entrada referente a RLIKE y REGEXP así que decir que nos permite realizar búsquedas y comparaciones con patrones, y el IF generalmente se usa a la hora de crear procedimientos o funciones, pero también se puede usar dentro de una consulta, basicamente el IF se usa de la siguiente manera:

IF (condicion, si verdadero, si falso)

Imaginemos que nos han introducido los importes de esta manera ‘€ 25’, y queremos con una consulta sacar la suma de todos los importes.


SELECT SUM(
IF (
CONVERT(campo, SIGNED) != 0,
campo,
IF (
campo REGEXP('[0-9]'),
CONVERT(SUBSTR(campo FROM 2) , SIGNED),
0
)
)
)
FROM tabla;

Básicamente lo que hago es primero comprobar si hay un numero en el principio, en caso que que lo detecte lo devuelve, si no lo detecta, o devuelve 0, comprobamos con REGEXP() a ver si hay un numero en la cadena, en el caso que lo encuentre hago un CONVERT() desde la posición 2 de la cadena por medio de un SUBSTR(), si no devuelvo 0.

El numero puede estar en cualquier parte de la cadena

Para esta situación ya tenemos que recurrir a crear una función, no es recomendable ponernos a anidar IF. Partiendo de la combinación de REGEXP(), CONVERT() y SUBSTR() he realizado la siguiente función la cual nos devolverá el primer numero que encuentre en la cadena, este donde este.


DROP FUNCTION IF EXISTS extractNumber;
DELIMITER //
CREATE FUNCTION extractNumber (cadena1 VARCHAR(255))
RETURNS INT(11)
DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE posicion, resultado, longitud INT(11) DEFAULT 0;
DECLARE cadena2 VARCHAR(255);
SET longitud = LENGTH(cadena1);
SET resultado = CONVERT(cadena1, SIGNED);
IF resultado = 0 THEN
IF cadena1 REGEXP('[0-9]') THEN
SET posicion = 2;
checkString:WHILE posicion <= longitud DO
SET cadena2 = SUBSTR(cadena1 FROM posicion);
IF CONVERT(cadena2, SIGNED) != 0 THEN
SET resultado = CONVERT(cadena2, SIGNED);
LEAVE checkString;
END IF;
SET posicion = posicion + 1;
END WHILE;
END IF;
END IF;
RETURN resultado;
END //
DELIMITER ;

Limitaciones de la función extractNumber()

La mayoría de las pruebas las he realizado con números enteros, en plan «Un camión con 500 kilos de patatas» o en el plan «tortilla de 12 huevos», en todos esos casos funciona perfectamente, al igual que si ponemos «1€» o «€1» o «Total Euros: 20», pero si hay decimales solo devuelve la parte entera de estos.