Detectar Internet Explorer con PHP

Es habitual que algunas versiones de Internet Explorer den la tabarra al ser un navegador que no sigue los estándares. Tranquilos, don’t worry. Podéis detectar con PHP si el navegador es Explorer y, dependiendo del resultado, mostrar una maquetación u otra. La función es simple:

<?php
$browser = getenv("HTTP_USER_AGENT");
if (preg_match("/MSIE/i", "$browser"))
{
    //Lo que toque hacer con el Explorer
}
else
{
   //El resto
}
?>

Claro que hay que reconocer que IE9 o IE10 no son tan problemáticos como las versiones anteriores ¿Y si sólo quieres descartar del 8 para abajo? Bueno, toca cambiar un poco el código, para así poder detectar el número de versión (que por suerte está casi extinto, pero todavía arreglo equipos con Internet Explorer 6):

if(preg_match('/(?i)MSIE [5-8]/',$_SERVER['HTTP_USER_AGENT']))
{
   //Aquí lo que va a hacer si es menor que 8
}
else
{
    //Aquí el resto de navegadores y explorers más nuevos.
}

En fin, si queréis sí permitir el 8 y no el 6 y el 7… bueno, pues cambiáis el rango en la expresión regular del ejemplo, y listo.

Usar Bit.ly en WordPress para acortar URL’s

Existen dos formas de usar el acortador de URL Bit.ly en WordPress. ¿Por qué usar Bit.ly para acortar url’s y no usar, por ejemplo, perce.be? Bueno, depende del uso que le queráis dar, claro. Un site como perce.be os permite acortar la URL, cumple su función. Pero Bit.ly además de permitirnos  acortar un link también nos dará estadísticas sobre cuántas veces se ha hecho click, desde donde… en fin, tiene un completo sistema de estadísticas. (Si no queréis generarlas entonces os será más cómodo un servicio más directo, como perce.be).

Bueno, ya os he comentado que hay dos formas de usar Bit.ly en WP. La primera y la más sencilla es instalar un plugin para Bit.ly, de los que ya hay varios disponibles, pero el más recomendable es WP-bitly, ya que otros de las más populares llevan tiempo sin actualizaciones.

Pero si no quieres depdender de un plugin externo siempre puedes meterle mano al código (recordad que hablamos de instalaciones de WordPress en vuestros propios servidores, no de los WP gratuitos de wordpress.com, como este). Lo primero es que os hagáis una cuenta para acceder al API de Bit.ly, y tras esto le metéis mano a functions.php:

function bitly()
{
  //información del login
  $url = get_permalink(); //genera el permalink de wordpress
  $login = 'tulogin'; //aquí mete tu nombre de usuario de Bit.ly
  $apikey = 'R_churro_de_letras_y_números'; //tu API key de Bit.ly
  $format = 'json'; //puedes elegir json o xml, en este caso json
  $version = '2.0.1';

  //creando la url
  $bitly = 'http://api.bit.ly/shorten?version='.$version.'&longUrl='.urlencode($url).'&login='.$login.'&apiKey='.$apikey.'&format='.$format;

  //obtener la url
  //también podría usarse cURL
  $response = file_get_contents($bitly);

  //ahora toca parsear según el formato
  //vamos a usar las dos posibilidades aunque arriba haya elegido json
  if(strtolower($format) == 'json')
  {
    $json = @json_decode($response,true); //descodificamos el json
    echo $json['results'][$url]['shortUrl']; //imprimimos datos
  }
  else //xml
  {
    $xml = simplexml_load_string($response); //cargamos el xml
    echo 'http://bit.ly/'.$xml->results->nodeKeyVal->hash; //imprimimos lo buscado
  }
}

Y con esto tenemos ya la función. Ahora nos queda añadirla a nuestro código. En single.php, debajo de la llamada a the_content() es el lugar ideal para meter tu llamada a bitly(). Y listo, ya estás generando tu url acortada con Bit.ly.

Deshabilitar cambio de Theme en WordPress

A veces, cuando montas un Wodpress para un cliente, no te interesa que este pueda cambiar el theme. No es por limitar la libertad del cliente, es por el riesgo de que trasteando lo cambie, luego no sea capaz de volver a ponerlo y tengas que ir a hacer mantenimiento (que siempre le puedes cobrar, pero si te está pagando una tarifa fijo por mantenimiento, que es lo normal,  eso acaba en «más trabajo por el mismo precio«). Tranquilo, basta con añadir unas pocas líneas a functions.php y evitaremos que esto ocurra, bloqueando la posibilidad de cambiar el theme del usuario.

add_action('admin_init', 'que_cambie_el_theme_tu_abuela');
function que_cambie_el_theme_tu_abuela() {
  global $submenu, $userdata;
  get_currentuserinfo();
  if ($userdata->ID != 1) {
    unset($submenu['themes.php'][5]);
    unset($submenu['themes.php'][15]);
  }
}

Y point ball (oseáse, punto pelota). Bueno, mejor no le llaméis «que_cambie_el_theme_tu_abuela» a la función, por cosas de profesionalidad, ponedle algo como «bloquear_cambio_theme«, «bloquear_theme«, etc.

Deshabilitar trackbacks en WordPress hacia tus artículos cuando los autorreferencias

Como sabéis todos los que tenéis un blog, los trackbacks son un sistema que os avisa cuando un bloguero ha hecho una referencia a uno de vuestros artículos en el suyo. Pero claro, si tú haces una referencia a uno de tus propios artículos en otro (tipo «Como ya comenté en el artículo X…») el trackback también se envía. Como generalmente no queremos comentarios de nuestros propios trackbacks en nuestros artículos os voy a enseñar un pequeño fragmento de código que, añadido a functions.php deshabilitará el auto-trackback:

function deshabilitar_autoping(&$links){
    foreach ($links as $l=>$link){
      if(0===strpos($link, get_option('home')))
         unset($links[$l]);
    }
}
add_action('pre_ping'; 'deshabilitar_autoping');

Una simple función que os ahorrará tener que estar borrando cada dos por tres vuestros propios trackbacks.

Hashes de passwords en PHP 5.5

Uno de los problemas de los algoritmos criptográficos, como le explicaba el otro día a mi madre, es que al ser susceptibles de poder ser rotos por fuerza bruta cada X tiempo tienen que renovarse, dado que la mayor capacidad de procesamiento de los equipos (y más con la posibilidad de hacer computación distribuida) los hace vulnerables con el paso de los años. Decía un profesor mío, y un gran profesor por cierto, «por fuerza bruta todo se rompe, sólo hace falta tiempo«.

La hasta ahora última versión de PHP nos ofrece nuevas funciones a la hora de trabajar con hashes de passwords. Antes era tradicional utilizar funciones como md5(), sha1(), crypt() o hash(). El problema de usar md5() o sha1() es que usan algoritmos muy directos y ligeros. Es decir, que hacen la encriptación y resumen muy rápido, lo cual aunque beneficia el rendimiento en caso de un ataque (lo más habitual con md5() es el llamado «ataque de cumpleaños» que en lugar de intentar encontrar tu contraseña intenta encontrar simplemente una que de el mismo resultado como resumen) facilita la labor del atacante. En cambio hash() y crypt() son algoritmos más complejos, más lentos, tardan más en devolver el resultado. Algo que para el usuario es un imperceptible segundo de espera, pero que en caso de un ataque que tiene que probar millones de combinaciones se convierte en un poderoso impedimento.

En todo caso PHP 5.5 nos provee de nuevas funciones para trabajar con hashes de passwords:

  • password_get_info
  • password_hash
  • password_needs_rehash
  • password_verify

Las más importantes, en el uso normal que podemos hacer de estas funciones son la segunda y la cuarta. Empecemos entonces por password_hash():

Como su nombre indica, la función genera un hash de tu contraseña. Lógicamente tiene que recibir dicha contraseña como primer parámetro. Como segundo debe recibir una constante con el algoritmo a usar (las opciones son PASSWORD_DEFAULT, que es el que usa por defecto PHP, y PASSWORD_BCRYPT, que nos permite definir varias opciones), y si eliges PASSWORD_BCRYPT puedes pasarle como tercer parámetro una serie de opciones. Las más habituales son cost, que es el «coste de computación» o «número de vueltas» que dará el algoritmo y cuanto más alto sea este número menos rendimiento y más seguridad, y salt, que nos permite «salar» el password (añadirle una cadena para hacer más complejo el asalto a la contraseñas). Un ejemplo con las dos opciones, sacado de la web de php.net


<?php
echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";

$options = [
    'cost' => 7,
    'salt' => 'BCryptRequires22Chrcts',
];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
?>

Como podéis ver se hacen dos hashes. El primero con los parámetros por defecto y el segundo usando PASSWORD_BCRYPT con un menor coste para el sistema (el cost en el algoritmo por defecto sería 10) pero con un salt definido. Por lo que he leído el algoritmo por defecto siempre mete un salt aunque no lo definas e incluso se recomienda que mejor dejar a PHP hacerlo antes que meter una cadena estática.

En el caso de password_verify() la cosa es más facililla. La función recibe la contraseña en texto plano y el hash, encriptado con la función password_hash(). Si conciden nos devuelve TRUE y si no coinciden nos devuelve FALSE.

De nuevo me remito al ejemplo del php.net para esto:


<?php
// Ver el ejemplo de password_hash() arriba para ver de dónde viene este hash.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo '¡La contraseña es válida!';
} else {
    echo 'La contraseña no es válida.';
}
?>

Con estas dos funciones podéis hacer de manera muy simple un sistema de login en PHP, con apoyo de una base de datos.

Títulos de apertura con CSS3

En fin, para empezar este artículo sobre animaciones sobre títulos en CSS3 primero echad un ojo a esta página de ejemplo.Vamos a trabajar para hacer algo similar (bueno, de hecho para hacer ese ejemplo).

Ojo, yo no me he currado el css en este caso, me la encontré mientras me documentaba para otra cosa a través de este artículo, y creo que merece que lo traduzca/explique en castellano.

Años atrás un efecto como este sólo sería posible con Flash, pero ahora podemos hacerlo con la tecnología nativa de los navegadores (bueno, como siempre con la excepción de nuestro querido Internet Explorer, al menos hasta la versión 10). Cierto que en este caso también hay ayuda de un poco de Javascript, no es CSS puro, pero se trata de una simple librería que permitirá trabajar con las letras por separado sin tener que crear nosotros a mano un span para cada una. La biblioteca de JS a utilizar será Lettering.js.

Por tanto vamos primero con el marcado. Crearemos un div para envolverlo todo y meteremos dentro de él todas las frases a usar como títulos de segundo nivel (h2):

</pre>
<div class="hiddenSpellError">class="os-phrases"></div>
<pre></pre>
<h2>Sometimes it's better</h2>
<pre>
    <h2>to hide</h2></pre>
<h2>in order to</h2>
<pre>
    <h2>survive evil</h2>
    <h2>Thanatos</h2>
    <h2>This fall</h2>
    <h2>Prepare</h2>
    <h2>Refresh to replay</h2>
</div>

Ok, ya tenemos el marcado. Como dije antes, toca meter una línea de javascript (en este caso, con jQuery además)

$("#os-phrases > h2").lettering('words').children("span").lettering().children("span").lettering();

Esto lo que hará será, primero, separar cada título en palabras y cada palabra en letras, y además cada letra está metida en dos span distintos con la misma clase. En la página original podéis ver un ejemplo de cómo sería hacer eso codeándolo a mano.

Muy bien, ya tenemos la parte de marcado lista, a base tanto de código manual como de javascript para facilitar las tareas. Toca ponerse manos a la obra con el CSS.

Lo primero será lograr que nuestros títulos ocupen el 100% de la página, posicionado de forma absoluta, en mayúsculas y bien tocho:

.os-phrases h2 {
    font-family: 'Dosis', 'Lato', sans-serif;
    font-size: 70px;
    font-weight: 200;
    height: 100%;
    width: 100%;
    overflow: hidden;
    text-transform: uppercase;
    padding: 0;
    margin: 0;
    position: absolute;
    top: 0;
    left: 0;
    letter-spacing: 14px;
    text-align: center;
}

Right now! Este paso ya está listo, el título es bien tochaco. Eso sí, podría pasar que no se ajustase bien a todos los tamaños de pantalla, así que vamos a usar flexbox para solucionarlo.

.os-phrases h2,
.os-phrases h2 > span {
    height: 100%;
    /* Centrando con flexbox */
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

El siguiente paso es meter espaciado entre palabras:

.os-phrases h2 > span {
    margin: 0 15px;
}

Y ahora vamos a ver el por qué de los dos span para cada letra. Al primero de ellos le vamos a aplicar perspectiva:

.os-phrases h2 > span > span {
    display: inline-block;
    perspective: 1000px;
    transform-origin: 50% 50%;
}

Las letras en si serán transparentes y les meteremos una animación, que durará 5.2 segundos.

.os-phrases h2 > span > span > span {
    display: inline-block;
    color: hsla(0,0%,0%,0);
    transform-style: preserve-3d;
    transform: translate3d(0,0,0);
    animation: OpeningSequence 5.2s linear forwards;
}

Con esto ya ves la lógica del doble span.

Una vez tenemos la orientación de las letras toca definir los delays de las frases. La quinta frase, la que es el título de la «película imaginaria» tendrá un delay especial, aparecerá más lentamente. En cambio las secuencias 6 y 7 irán más rápido.

.os-phrases h2:nth-child(2) > span > span > span {
    animation-delay: 5s;
}

.os-phrases h2:nth-child(3) > span > span > span {
    animation-delay: 10s;
}

.os-phrases h2:nth-child(4) > span > span > span {
    animation-delay: 15s;
}

.os-phrases h2:nth-child(5) > span > span > span {
    font-size: 150px;
    animation-delay: 21s;
    animation-duration: 8s;
}

.os-phrases h2:nth-child(6) > span > span > span {
    animation-delay: 30s;
}

.os-phrases h2:nth-child(7) > span > span > span {
    animation-delay: 34s;
}

Antes de meternos con la última frase, que tendrá un tratamiento más especial, toca definir cómo se comportarán las letras durante la animación (es decir, cómo va evolucionando la separación, la opacidad, etc durante la animación):

@keyframes OpeningSequence {
    0% {
        text-shadow: 0 0 50px #fff;
        letter-spacing: 80px;
        opacity: 0.2;
        transform: rotateY(-90deg);
    }
    50% {
        text-shadow: 0 0 1px #fff;
        letter-spacing: 14px;
        opacity: 0.8;
        transform: rotateY(0deg);
    }
    85% {
        text-shadow: 0 0 1px #fff;
        opacity: 0.8;
        transform: rotateY(0deg) translateZ(100px);
    }
    100% {
        text-shadow: 0 0 10px #fff;
        opacity: 0;
        transform: translateZ(130px);
        pointer-events: none;
    }
}

Ok, con esto ya tenemos todo lo relativo a todas las frases… menos la última, que ya dijimos que tendría un tratamiento especial, ya que la animación será distinta al resto, usando en este caso un fundido:

.os-phrases h2:nth-child(8) > span > span > span {
    font-size: 30px;
    animation: FadeIn 4s linear 40s forwards;
}

@keyframes FadeIn {
    0% {
        opacity: 0;
        text-shadow: 0 0 50px #fff;
    }
    100% {
        opacity: 0.8;
        text-shadow: 0 0 1px #fff;
    }
}

Y ahora pensarás «¿No había algunas palabras destacadas?». Y tienes razón, algunas estaban en negrita. Pero tranqui, eso lo arreglamos con esta última línea, donde aplicamos la negrita a ciertas palabras concretas:

.os-phrases h2:first-child .word3,
.os-phrases h2:nth-child(2) .word2,
.os-phrases h2:nth-child(4) .word2 {
    font-weight: 600;
}

En fin, ya ves que es un pelín tocho el código pero que tampoco come a nadie, y se logra un resultado muy espectacular. Si no os apetece copiar, el código original está en este enlace.

A la hora de terminar este artículo, la web original estaba en remodelación. Pero echadle un ojo por si acaso porque cuando vuelva a estar activa tiene muchos trucos de diseño web muy interesantes, como todos los que ha colgado la creadora de este efecto Mary Lou.

Bluefish, la alternativa libre a Dreamweaver en Linux

Cierto es que yo utilizo Aptana Studio, Eclipse y Geany para todo, por lo que nunca me he preocupado mucho de buscar una alternativa en Linux a Dreamweaver, puesto que ese software apenas lo usaba cuando desarrollaba en Windows por parecerme especialmente incómodo para editar código.

Pero si lo que quieres es un editor que te permita generar código a base de rellenar datos en un formulario y pulsar botones para generar conexiones a bases de datos, tablas o formularios entonces tu alternativa es Bluefish, bastante más sólido y completo que Kompozer, el cual siempre me ha parecido muy limitado.

Logotipo Bluefish Editor 2.2

Bluefish te permitirá trabajar con multitud de lenguajes (podéis ver el listado de lenguajes y CMS soportados en la web del proyecto), dándote referencias en línea, marcadores varios para distintas etiquetas y palabras claves, autocompletado, autocerrado de etiquetas, resaltado de comienzos y finales de bloque, cliente de FTP para trabajar con archivos remotos,  generador de thumbnails…

A pesar del título no sólo está disponible para Linux, sino que hay versiones para Mac, Solaris, BSD y Windows. En fin, si echas en falta el programa de Adobe esta puede ser tu solución.

Se trata de software libre, así que lo podéis descargar gratis desde la propia web o, en caso de Ubuntu, instalarlo con un apt-get install bluefish.

Obtener la url de una página en PHP

Cuando trabajamos con CMS o con frameworks suele ser habitual tener una función que nos indique la url de la página con la que estás trabajando. Pero claro, no siempre trabajamos con frameworks o CMS, a veces nos vemos metidos en el hard-code puro y duro.

En ese caso ¿cómo conseguimos la url? En fin, tendremos que usar la variable $_SERVER.

La variable $_SERVER es un array que almacena cierta información sobre el servidor. En la variable $_SERVER[‘HTTP_HOST’] se guarda la información sobre el nombre de domino, En $_SERVER[‘SERVER_PORT’] el puerto contra el que realizamos la conexión y en $_SERVER[‘REQUEST_URI’] la URI.

Con lo cual si queremos obtener la url basta con usar dos o tres de estas variables, dependiendo de si queremos o no el puerto. Abajo un ejemplo:

//Con puerto
$url_port="http://".$_SERVER['HTTP_HOST'].":".$_SERVER['SERVER_PORT'].$_SERVER['REQUEST_URI'];
//sin puerto
$url = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

Y si vamos a usarlo a menudo lo mejor es utilizarlo dentro de una función que nos devuelva el resultado, para no andar repitiendo código.

Usar codificación utf-8 con MySQLi

Como estos días estoy hablando de MySQLi voy a seguir un poco más con el tema y comentar una peculiaridad: si quieres recuperar datos de una BD donde se hayan guardado en utf-8 y manipularlos e imprimirlos sin problemas de codificación tienes que especificarlo.

Es decir, no basta con que los datos estén en la base codificados como utf-8 y que, además, en la web también esté definido que usaremos esta codificación. No, además debemos indicar a MySQLi que queremos trabajar con utf-8 específicamente. Esto no es para nada complicado porque ya hay una función que te permite elegir la codificación. Un ejemplillo de código simplón os lo aclarará:

$con = new mysqli("server", "user", "password");
if (mysqli_connect_errno($con)) { //comprobamos que no haya fallo en la conexión
	die("Fallo al conenctar a MySQL: " . mysqli_connect_error());
}
				
if (!$con->set_charset("utf8")) {//asignamos la codificación comprobando que no falle
       die("Error cargando el conjunto de caracteres utf8");
}

Como podéis ver, es simple: creamos la conexión y luego simplemente definimos un juego de caracteres. En el ejemplo he usado utf-8, pero vamos, que podéis usar cualquiera de los soportados por MySQL.

Bucles en PHP: do, while, foreach y for

Hoy vamos con una lección de PHP básico: el uso de los distintos bucles existentes en este lenguaje de programación. Esencialmente tenemos cuatro bucles, por lo que no es muy difícil aprendérselos. Lo curioso es que muchas veces la gente hace un mal uso de ellos, os lo digo yo que en los últimos meses casi he trabajado más sobre código de otros (plugins de CMS, terminar trabajos a medias) que creando el mío.

Empezamos por el bucle for. Este debe usarse cuando queremos ejecutar una instrucción o bloque de instrucciones un número conocido de veces. Es decir, si sabes que tienes que repetir una instrucción exactamente, por ejemplo, diez veces entonces usa for. La sintaxis sería for(inicialización; condición de terminación; incremento) pero mejor te la explico en un ejemplillo:

for($i=0; $i<10; $i++){
    echo 'Voy a imprimir esto 10 veces y esta es la '.$i;
}

Es habitual ver a programadores usando el for de forma abusiva e inadecuada.

El siguiente bucle a comentar será el while. En este caso el código de este bucle se ejecuta si una condición dada es cierta y se repite mientras esta sigue siendo cierta. Es decir, si no se da la condición antes de entrar ya no se ejecuta, y se se entra se hará hasta que la condición deje de darse, evaluándola en cada iteración. Debemos usar este bucle cuando no sepamos con exactitud la cantidad de veces que tiene que ejecutarse el bucle, pero sí el valor que queremos alcanzar. La sintaxis es while(condición). Un ejemplo:

<?php
$i=0;
$precio = 50;

while( $precio < 5000)
{
   $precio*2;
   $i++;
}
echo ("Hemos doblado el precio  ".$i." veces hasta superar los 5000");
?>

Parecido, pero no igual, es el bucle do-while. La diferencia es que este se ejecuta siempre al menos una vez, aunque la condición de salida no se cumpla a la entrada. Es decir, en el ejemplo anterior entró en el bucle porque la variable precio era menor de 5000, pero en caso de un do-while habría entrado y ejecutado el código al menos una vez aunque hubiéramos inicializado la variable con un valor superior a 5000. La sintaxis es do{código}while(condición). Veamos un ejemplo simple donde lo diferenciamos del while:

$i=5;
while($i<4)
{
   echo 'Esto no se va a imprimir porque no va a entrar';
}

do
{
    echo 'Aunque la condición es la misma, esto se imprimirá al menos una vez';
}while($i<4);

Finalmente tenemos el foreach, pensado para iterar dentro de arrays. En este bucle lo que hacemos es recorrer todos los elementos de un array. La sintaxis es foreach(array as valor). Es el bucle que debemos utilizar siempre para este propósito. Un ejemplo donde imprimimos los nombres de una serie de frutas:

$frutas = array('melón','limón','fresa','manzana');
echo 'Existencias:'
foreach($frutas as $fruta){
   echo $fruta;
}

Con esto ya estarían repasados los cuatro bucles. Existen, además, dos sentencias que pueden usarse para romper/modificar el flujo natural del bucle: break y continue.

La sentencia break fuerza la salida de un bucle, saltando a la siguiente línea tras el mismo. Su uso natural es para las condicionales switch/case, si bien a veces se ve dentro de bucles. Por cuestiones de elegancia y comprensión del código se recomienda no usarlo. El ejemplo sería:

while( $i < 10)
{
   $i++;
   if( $i == 5 )break;
}

En cuanto a continue se utiliza con un condicional antes y lo que hace es saltarse las instrucciones cuando se cumpla esa condición, pero sin salir del bucle. Por ejemplo imaginemos que queremos recorrer una serie de números pero imprimir sólo los pares:

$i=1;
while($i<10)
{
  if($i % 2 != 0) continue;
  echo $i;
}

El código del ejemplo no haría nada cuando se cumpliera la condición, y cuando no se cumpliera imprimiría el valor.

En fin, con esto ya damos por terminada la lección sobre bucles en PHP. Espero que haya sido de ayuda a alguien. Y recordad, usad cada bucle cuando sea necesario, no de forma indiscriminada.