Cómo mostrar miniaturas en tu tema de WordPress sin plugins


El día de año nuevo cambié el tema del blog (una versión modificada de Redoable) por Arthemia 2 y descubrí que incluía el script timthumb.php para generar las miniaturas de las entradas en la portada, archivos y búsqueda, ¡qué bien!. Pero nada más activarlo y entrar en el blog propiamente dicho, las imágenes no se muestran… Voy a la documentación del tema y veo que hay que copiar la ruta de la imagen que quiero como miniatura en un campo personalizado de la entrada, con nombre ‘Image’ y la URL relativa (esto es, wp-content/uploads/año/mes/imagen.jpg). Vaya rollazo, ¿no hay nada automático?.

No me cuentes historias, show me the code!
Obtener los archivos adjuntos a una entrada
Buscando por el Codex de WordPress encontré algo que podía ser útil: la función get_children(). Por lo visto WordPress relaciona internamente cada fichero con su entrada correspondiente, y esta función devuelve todos los adjuntos que hemos subido mediante el uploader al escribir la entrada. Además permite filtrar el resultado por tipo (attachment), el identificador de la entrada (post_id) y el tipo MIME del archivo (image).

$attachments =& get_children( array(
       'post_type' => 'attachment',
       'post_parent' => get_the_ID(),
        'post_mime_type' => 'image'
));
Tras varias pruebas -no todo sale siempre a la primera- compruebo que las todas miniaturas funcionan sin tener que usar los campos personalizados (que sinceramente, nunca me iba a molestar en rellenar) y me voy a la cama tan tranquilo.

El desastre
Al día siguiente… ¡horror!, el blog carga lentísimo y pocos minutos después recibo un mensaje del Hostmaster porque hay un proceso que está llamando continuamente a una IP caída (que resultó ser la de Twitter). Desactivo el plugin culpable -Twittwoo- e instalo WP-Super-Cache a petición del Hostmaster. Segundo horror: las miniaturas a tomar por saco. Borro la caché que había generado, desactivo y elimino todos los ficheros. Siguen sin aparecer las miniaturas y el Hostmaster me indica que desde el día de año nuevo a las 21:15h aparece este otro mensaje de error en los logs del servidor:

[Thu Jan 01 21:15:04 2009] [error] [client 84.77.X.X] Usage: file [-bcikLhnNsvz] [-f namefile] [-F separator] [-m magicfiles] file..., referer: http://www.frickr.es/
[Thu Jan 01 21:15:04 2009] [error] [client 84.77.X.X]        file -C -m magicfiles, referer: http://www.frickr.es/
Pues parece que timthumb.php hace una llamada a una función que calcula no-se-qué de un número mágico y falla o el servidor no la soporta. Y encima el WP-Super-Cache me ha modificado el .htaccess, pero por suerte el Hostmaster me sube uno limpio para WordPress. Resumiendo: que el dichoso timthumb.php en realidad nunca ha funcionado bien, y hay que encontrar otra solución.

Me pongo a buscar otra vez en el Codex y esta vez descubro que desde la versión 2.5 WordPress permite especificar tamaños para generar miniaturas de todas las imágenes que se suben. Perfecto: si nativamente el sistema genera las miniaturas, y yo puedo acceder a todos los adjuntos de un post, me falta relacionar el adjunto con la miniatura del tamaño que necesito. Sigo inspeccionando las funciones internas y me encuentro con wp_get_attachment_image_src(), justo lo que necesito:

(array) $image = function wp_get_attachment_image_src (
     $attachment_id,
     $size='thumbnail',
     $icon = false
);

// Returns an array containing:
$image[0] => url
$image[1] => width
$image[2] => height
Bueno, pues vamos a configurar WordPress y a modificar el código del tema (theme) para hacer que soporte las miniaturas internas de WordPress y eliminar cualquier rastro del timthumb.php.


Nota: el código a continuación ha sido probado bajo WordPress 2.7. Debería funcionar también en WordPress 2.5 o superior, aunque no me hago responsable de los resultados.

Paso 1: Configurar el tamaño de las miniaturas
Antes que nada, tendremos que pensar cuáles serán los tamaños que necesitaremos para nuestras miniaturas. WordPress genera 3 tamaños distintos de miniaturas, además de conservar el tamaño original. Para el que no sepa dónde se cambian, está en Opciones » Objetos (vaya nombre tan poco intuitivo). Yo puse los mismos valores que venían especificados en mi theme Arthemia 2.

wordpress_miniaturas

Paso 2: Insertando el código final en el theme

Lo bueno que tiene dejar de utilizar timthumb.php es que ya no se llamará más a este script cada vez que queramos cargar una miniatura. Vale que tiene un sistema de cachés y es bastante efectivo, pero el approach de los chicos de WordPress es mucho más eficiente: subes una imagen y se almacenan las miniaturas en 3 tamaños diferentes, para siempre. Esto hace las cosas mucho más sencillas y no hay que procesar un PHP entre medias, libera recursos de CPU, RAM y se reduce el tiempo de carga. Todos ganan (menos Tim :-D). El código final es este (los comentarios están en inglés por si alguien llega hasta aquí y no entiende español):

<?php
    $image = null; // Clear the value from the previous post
    // Get all attachments from the post ID with type image
    $attachments =& get_children(array('post_parent'=>get_the_ID(),'post_type'=>'attachment','post_mime_type'=>'image'));

    // If attachments are found...
    if ($attachments == TRUE) {
        // ... go through all of them
        foreach($attachments as $att) {
            // Get the image source for every image attachment found
            // Post_ID, Size ('thumbnail', 'medium', 'large', 'full' or an Array), Icon (true/false)
            $image = wp_get_attachment_image_src($att->ID,'thumbnail',false);
            break; // Comment this line to get all images inside the post
        }
    }

    echo '<!-- Attachment_ID='.$att_id.'-->'; // Comment this line if everything works OK (used for debugging)

    if (isset($image)) {
?>
    <a href="<?php the_permalink() ?>" rel="bookmark" title="Enlace permanente a <?php the_title(); ?>">
    <img src="<?php echo $image[0] ?>" alt="<?php the_title(); ?>" class="left" width="<?php echo $image[1]; ?>" height="<?php echo $image[2]; ?>" /></a>
    <?php } ?>
Paso 3: Vamos por partes (para amateurs)
1
2
3
4
<?php
    $image = null; // Clear the value from the previous post
    // Get all attachments from the post ID with type image
    $attachments =& get_children(array('post_parent'=>get_the_ID(),'post_type'=>'attachment','post_mime_type'=>'image'));
Lo primero que hacemos es abrir una etiqueta php allí donde queramos mostrar la miniatura, siempre dentro de El Bucle (The Loop). Con $image = null; vaciamos esta variable por si contiene valores de la iteración (post) anterior. Si no lo hacemos, la minuatura podría repetirse en una entrada que vaya después y a la que no le hayamos adjuntado ninguna imagen. Por último, utilizamos la función get_children() que hemos visto antes pasándole como parámetros el número del post actual, y los filtro para que sólo nos devuelva los adjuntos y dentro de éstos, las imágenes. El resultado de esta operación se almacena en la variable $attachments.

6
7
8
9
10
11
12
13
14
15
    // If attachments are found...
    if ($attachments == TRUE) {
        // ... go through all of them
        foreach($attachments as $att) {
            // Get the image source for every image attachment found
            // Post_ID, Size ('thumbnail', 'medium', 'large', 'full' or an Array), Icon (true/false)
            $image = wp_get_attachment_image_src($att->ID,'thumbnail',false);
            break; // Comment this line to get all images inside the post
        }
    }
Comprobamos si al hacer la petición a get_children() hemos recibido algún resultado, y en caso afirmativo, recorremos cada uno de los adjuntos con la sentencia foreach, y pedimos con wp_get_attachment_image_src() que nos almacene en $image los datos que necesitamos (URL, ancho y alto) para la miniatura de tamaño thumbnail (por ejemplo). Para ello, le hemos especificado tambien el identificador de adjunto que usa internamente WordPress con $att->ID y que no queremos incluir un icono en la imagen con el tercer parámetro false. Como en mi caso yo sólo quiero la primera imagen que tenga incluída en mis entradas -podría tener varias-, he colocado un break; (salto) para que se detenga al obtener la miniatura de la primera imagen.

17
18
19
20
    echo '<!-- Attachment_ID='.$att_id.'-->'; // Comment this line if everything works OK (used for debugging)

    if (isset($image)) {
?>
La línea 17 simplemente imprime un comentario con el identificador interno de la imagen que ha obtenido de nuestro post. Para poder ver el resultado tendremos que mostrar el código fuente en el navegador. Si todo funciona correctamente, podemos comentar esta línea insertando dos barras // delante del echo. En la línea 19 indicamos que sólo queremos que se ejecute el código que viene a continuación si se ha obtenido una miniatura. Quedaría bastante mal insertar una imagen con una URL rota que no lleva a ninguna parte.

21
22
23
<a href="<?php the_permalink(); ?>" rel="bookmark" title="Enlace permanente a <?php the_title(); ?>">
    <img src="<?php echo $image[0] ?>" alt="<?php the_title(); ?>" class="left" width="<?php echo $image[1]; ?>" height="<?php echo $image[2]; ?>" /></a>
    <?php } ?>
Y por último creamos el código HTML de el enlace al post, con la imagen en su interior. Usamos la función the_permalink() para obtener la URL de la entrada y the_title() para el título. Para finalizar imprimimos la URL de la minuatura con echo $image[0];, el ancho con $image[1] y la altura con $image[2], tal como vimos antes en la documentación del Codex. Y que no se nos olvide cerrar la condición al final con su llave } correspondiente.

Paso 4: Regenerar las miniaturas con los nuevos tamaños
Si habéis cambiado los tamaños de las miniaturas en el paso 1, hay que tener en cuenta que todas las imágenes subidas hasta la fecha fueron escaladas al tamaño que estaba especificado entonces. La solución manual sería eliminar todas las imágenes una por una y volverlas a subir para que WordPress coja los nuevos tamaños. Suerte que está el plugin Regenerate Thumbnails para solucionarnos la papeleta automáticamente por nosotros. Una vez instalado y activado, sólo hay que ir a Herramientas » Regen. Thumbnails y pulsar sobre el botón Regenerate all Thumbnails para establecer todas las miniaturas a los nuevos tamaños. ¿A que no ha sido para tanto? ;-)

Entradas similares

0 Comentarios