
Hay ocasiones en las que tenemos que crear una plantilla para páginas, entradas o entradas personalizadas en las que es necesario asignar una o varias imágenes.
Podemos hacerlo subiendo las imágenes mediante el apartado “Multimedia” y luego copiando la URL de la imagen en un Campo Personalizado:

Si la web es para nosotros mismos puede ser que no nos importe este sistema tan rudimentario, pero si es para un tercero quizás no sea esta la mejor opción.
Lo mejor es usar la función que WordPress nos ofrece y que hemos visto en artículos anteriores. Se trata de add_meta_box().
Ya vimos en un artículo anterior cómo crear un plugin que añade meta boxes para subir imágenes. Pero aprovechando este artículo de wp-tuts+ y basándome en él, vamos a crear una serie de funciones que nos permitan nó sólo crear un meta box para subir imágenes, sino incluso añadir todos los que queramos en función de las imágenes que queramos subir en cada página.
Esto es lo que vamos a conseguir:

Hay un texto explicativo abajo de todo, donde podéis poner lo que queráis, por ejemplo unas breves instrucciones con el tamaño que tienen que tener las imágenes, etc.
Para crear esto abrimos el archivo functions.php de nuestro tema. Vamos a ver el código.
Lo primero que hacemos es crear el meta box con la función add_meta_box:
1 2 3 4 5 6 7 8 9 10 | function add_custom_meta_box() { add_meta_box( 'custom_meta_box', // id 'Fotos de la web XYZ', // título 'show_custom_meta_box', // función a la que llamamos 'page', // sólo para páginas 'normal', // contexto 'high'); // prioridad } add_action('add_meta_boxes', 'add_custom_meta_box'); |
Como vemos estos nuevos campos personalizados van a aparecer sólo en las páginas. Si quieres que aparezcan en las entradas, pon “posts” y si quieres que aparezcan en entradas personalizadas, pon el nombre de la misma. Si queremos que salgan en las páginas y en las entradas, haríamos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function add_custom_meta_box() { add_meta_box( 'custom_meta_box', // id 'Fotos de la web XYZ', // título 'show_custom_meta_box', // función a la que llamamos 'page', // sólo para páginas 'normal', // contexto 'high'); // prioridad add_meta_box( 'custom_meta_box', // id 'Fotos de la web XYZ', // título 'show_custom_meta_box', // función a la que llamamos 'post', // sólo para entradas 'normal', // contexto 'high'); // prioridad } add_action('add_meta_boxes', 'add_custom_meta_box'); |
Seguimos. Necesitaremos un poco de jQuery para cargar el editor multimedia. Para añadir un archivo de Javascript la manera adecuada de hacerlo es mediante wp_enqueue_script. A continuación escribimos:
// Para imágenes cargamos el script sólo si estamos en páginas. function add_admin_scripts( $hook ) { global $post; if ( $hook == 'post-new.php' || $hook == 'post.php' ) { wp_enqueue_script('custom-js', get_template_directory_uri().'/js/custom-js.js'); } } add_action( 'admin_enqueue_scripts', 'add_admin_scripts', 10, 1 );
Como vemos, en este caso cargaremos el archivo sólo si estamos en una página. El archivo está ubicado en la carpeta “js” de nuestro tema.
¿Qué tiene este archivo custom-js.js?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | jQuery(function(jQuery) { jQuery('.custom_upload_image_button').click(function() { formfield = jQuery(this).siblings('.custom_upload_image'); preview = jQuery(this).siblings('.custom_preview_image'); tb_show('', 'media-upload.php?type=image&TB_iframe=true'); window.send_to_editor = function(html) { imgurl = jQuery('img',html).attr('src'); classes = jQuery('img', html).attr('class'); id = classes.replace(/(.*?)wp-image-/, ''); formfield.val(id); preview.attr('src', imgurl); tb_remove(); } return false; }); jQuery('.custom_clear_image_button').click(function() { var defaultImage = jQuery('.custom_default_image').text(); jQuery(this).parent().parent().find('.custom_upload_image').val(''); jQuery(this).parent().parent().find('.custom_preview_image').attr('src', defaultImage); return false; }); jQuery('.repeatable-add').click(function() { var defaultImage = jQuery('.custom_default_image').text(); field = jQuery(this).closest('td').find('.custom_repeatable li:last').clone(true); fieldLocation = jQuery(this).closest('td').find('.custom_repeatable li:last'); jQuery('img.custom_preview_image', field).attr('src', defaultImage); jQuery('input.custom_upload_image', field).val('').attr('name', function(index, name) { return name.replace(/(\d+)/, function(fullMatch, n) { return Number(n) + 1; }); }) field.insertAfter(fieldLocation, jQuery(this).closest('td')) return false; }); jQuery('.repeatable-remove').click(function(){ jQuery(this).parent().remove(); return false; }); jQuery('.custom_repeatable').sortable({ opacity: 0.6, revert: true, cursor: 'move', handle: '.sort' }); }); |
Como veis hay varios eventos importantes. El primero se activa al hacer click en el botón de “Seleccionar imagen”, lanzando el cargador multimedia de WordPress y sustituyendo la imagen por defecto por la que hemos elegido para poder verla una vez subida en el administrador. A continuación tenemos el botón de Quitar imagen.
Luego viene el botón para añadir un nuevo campo donde subir una imagen, para lo que usamos la función clone() de jQuery. Nos aseguramos también de que el campo “name” de este nuevo campo sea diferente del anterior. Buscamos el último introducido ye incluimos el clonado a continuación.
A continuación está el botón para quitar una fila (usamos simplemente remove() de jQuery) y por último, gracias a sortable() de jQuery tenemos la función para mover el orden de cada fila.
Bueno, después de este paréntesis volvemos a nuestro archivo functions.php. Vamos a definir el campo personalizado. Como sólo tenemos un tipo (la imagen repetible) escribimos:
1 2 3 4 5 6 7 8 9 | $prefix = 'custom_'; $custom_meta_fields = array( // Dentro de este array podemos incluir más tipos array( 'label' => 'Fotos', 'desc' => 'Aquí va la descripción o instrucciones que consideremos oportunas', 'id' => $prefix.'imagenrepetible', 'type' => 'imagenrepetible' ) ); |
Podríamos haber incluido más tipos dentro del array. Os aconsejo que leáis el artículo que os enlacé más arriba para ver otras opciones.
A continuación escribiremos la función a la que se llama desde add_meta_box. Si veis más arriba veréis que se llama show_custom_meta_box(). Como es muy largo el código he intentado comentarlo todo lo posible:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | function show_custom_meta_box() {
global $custom_meta_fields, $post;
// Usamos nonce para verificación
echo '<input type="hidden" name="custom_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />';
// Creamos la tabla de campos personalizados y empezamos un loop con todos ellos
echo '<table class="form-table">';
foreach ($custom_meta_fields as $field) { // Hacemos un loop con todos los campos personalizados
// obtenemos el valor del campo personalizado si existe para este $post->ID
$meta = get_post_meta($post->ID, $field['id'], true);
// comenzamos una fila de la tabla
echo '<tr>
<th><label for="'.$field['id'].'">'.$field['label'].'</label></th>
<td>';
switch($field['type']) { // Si tenemos varios tipos de campos aquí se seleccionan
// En nuestro caso tenemos solo uno: Imagen repetible
case 'imagenrepetible': // Lo que pone en "type" más arriba
$image = get_template_directory_uri().'/images/no-hay-imagen.png'; // Ponemos una imagen por defecto
echo '<span class="custom_default_image" style="display:none">'.$image.'</span>'; // Al principio no la mostramos
echo '<ul id="'.$field['id'].'-repeatable" class="custom_repeatable">';
$i = 0;
if ($meta) { // Si get_post_meta nos ha dado valores, hacemos un foreach
foreach($meta as $row) {
// Obtenemos la imagen en su tamaño máximo. Podéis poner en su lugar
// thumbnail, medium o large
$image = wp_get_attachment_image_src($row, 'full');
// la primera parte de wp_get_attachment_image_src nos da su url.
$image = $image[0]; ?>
<li>
<!-- Añadimos la imagen que se arrastra para cambiar posición, dentro de tu tema -->
<span class="sort hndle" style="float:left;"><img src="<?php echo get_template_directory_uri().'/images/move.png';?>" /> </span>
<!-- El input con el valor del meta. Su attributo "name" tiene un número que se irá incrementando a
medida que creamos nuevos campos -->
<input name="<?php echo $field['id'] . '['.$i.']'; ?>" id="<?php echo $field['id']; ?>" type="hidden" class="custom_upload_image" value="<?php echo $row; ?>" />
<!-- mostramos la imagen con 200px de ancho para ver lo que hemos subido -->
<img src="<?php echo $image; ?>" class="custom_preview_image" alt="" width="200"/><br />
<!-- El botón de Seleccionar Imagen -->
<input class="custom_upload_image_button button" type="button" value="Seleccionar imagen" />
<!-- Los botones de eliminar imagen y de quitar fila-->
<small> <a href="#" class="custom_clear_image_button">Eliminar imagen</a></small>
<a class="repeatable-remove button" href="#">- Quitar fila</a>
</li>
<?php $i++; // Incrementamos el contador para que no se repita el atributo "name"
} // Fin del foreach
} else { // Si no hay datos ?>
<li><span class="sort hndle" style="float:left;"><img src="<?php echo get_template_directory_uri().'/images/move.png';?>" /> </span>
<input name="<?php echo $field['id'] . '['.$i.']'; ?>" id="<?php echo $field['id']; ?>" type="hidden" class="custom_upload_image" value="<?php echo $row; ?>" />
<img src="<?php echo $image; ?>" class="custom_preview_image" alt="" width="200" /><br />
<input class="custom_upload_image_button button" type="button" value="Seleccionar imagen" />
<small> <a href="#" class="custom_clear_image_button">Eliminar imagen</a></small>
<a class="repeatable-remove button" href="#">- Quitar fila</a>
</li>
<?php } ?>
</ul>
<br />
<!-- Botón para añadir una nueva fila -->
<a class="repeatable-add button-primary" href="#">+ Añadir</a>
<!-- Aquí va la descripción -->
<br clear="all" /><br /><p class="description"><?php echo $field['desc']; ?></p>
<?php break;
} // fin del switch
echo '</td></tr>';
} // fin del foreach
echo '</table>'; // fin de la tabla
} // Fin de la función |
Ya nos falta una sola función, la de grabar los datos. A continuación (y seguimos en functions.php) escribimos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // Grabar los datos function save_custom_meta($post_id) { global $custom_meta_fields; // verificamos usando nonce if (!wp_verify_nonce($_POST['custom_meta_box_nonce'], basename(__FILE__))) return $post_id; // comprobamos si se ha realizado una grabación automática, para no tenerla en cuenta if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id; // comprobamos que el usuario puede editar if ('page' == $_POST['post_type']) { if (!current_user_can('edit_page', $post_id)) return $post_id; } elseif (!current_user_can('edit_post', $post_id)) { return $post_id; } // hacemos un loop por todos los campos y guardamos los datos foreach ($custom_meta_fields as $field) { $old = get_post_meta($post_id, $field['id'], true); $new = $_POST[$field['id']]; if ($new && $new != $old) { update_post_meta($post_id, $field['id'], $new); } elseif ('' == $new && $old) { delete_post_meta($post_id, $field['id'], $old); } } // final del foreach } add_action('save_post', 'save_custom_meta'); |
Una vez tenemos ya creados los campos personalizados toca ir subiendo imágenes en cada página/entrada o entrada personalizada de nuestro tema.
Para luego obtener las imágenes para la web usaremos la función de WordPress get_post_meta.
En este caso lo que obtendremos es un array con todos los ID de las imágenes que pertenecen al $post->ID actual:
1 | <?php $attachID = (get_post_meta( $post->ID, 'custom_imagenrepetible', true ));?> |
Si hacéis un:
1 | <?php print_r($attachID); ?> |
veréis que tenéis en el array los ID de las imágenes. ¿Como podemos ahora verlas? Si las imágenes tienen que estar todas seguidas, una detrás de otra, podéis hacer:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php foreach($attachID as $item){ $imagen = wp_get_attachment_image_src($item, 'full'); // Obtenemos la imagen "full". En vez de full podemos poner otro que dispongamos en nuestro tema $alt = get_post_meta($item, '_wp_attachment_image_alt', true); // Si queremos obtener el alt de la imagen $descripcion = get_post_field('post_content', $item); // Si queremos obtener la descripción de la imagen echo '<img src="' . $imagen[0] . '" width="' . $imagen[1] . '" height="' . $imagen[2] . '"'; if(count($alt)) { echo ' alt="' . $alt . '"';} echo ' />'; echo '<p>' . $descripcion . '</p>'; } ?> |
Fijaros que vamos recorriendo imagen a imagen a través del bucle que crea el foreach. Obtenemos la url, el ancho y el alto de la imagen gracias a la función de WordPress wp_get_attachment_image_src y lo almacenamos en el array $imagen. Por ello $imagen[0] será la url, $imagen[1] será el ancho y $imagen[2] será el alto de la imagen.
Luego obtenemos el valor del atributo alt de la imagen con get_post_meta y lo grabamos en la variable $alt. Comprobamos si existe y si es así lo ponemos.
Si no queremos poner una imagen tras otra, al hacer print_r veremos en qué posición está la imagen que queremos recuperar en cada momento, por lo que en vez de $item tendríamos por ejemplo $attachID[1] etc..
Como veis en el código hemos usado la imagen “full”, que es la de mayor tamaño al subir la imagen. Podemos poner otra que hayamos creado en nuestro archivo functions.php de nuestro tema, por ejemplo:
1 2 3 4 5 6 7 8 | ////////////////////////////////////////////////////////////////////////////////////////// // Añadimos nuevos tamaños de imagen if ( function_exists( 'add_image_size' ) ) { add_image_size('muy-grande', 654, 905, true); // foto grande entrada add_image_size('portada', 330, 457, true); // foto destacado en portada add_image_size('galeria', 150, 207, true); // foto pequeña galerias } |
Para este ejemplo podríamos poner en vez de “full”, “portada” (por ejemplo).
Y con esto hemos acabado! Os dejo a continuación las dos imágenes que he usado en el código, por si os fueran útiles:
![]()

Sigue a Juan en Twitter, en Google+, o suscríbete al RSS Feed de Emenia para estar al día de nuestros artículos.
2011-2012 © Copyright Emenia S.L. - Creación y Diseño web \ Marketing Online \ Comunicación - Todos los derechos reservados.

Hola Juan! Un placer saludarte desde Argentina. La verdad son muy buenos las articulos que publicas, he visto varios… muy bien explicados!
Con respecto a este caso, te hago una consulta, lo revise mil veces y no lo pude hacer funcionar… O sea, el código está bien, el campo me aparece en el editor de articulos… Cuando me abre el multimedia probe con todas las opciones para poder ingresar la imagen y nunca me la mostro en la “preview” del editor… y tampoco en el template (pensando que quizás el campo hubiese estado bien cargado pero que no se veia en el editor) El resto de las funcionalidad creo que funcionan bien…
Sabes que puede estar ocurriendo?
Muchas gracias! Un saludo!
Hola Juan Pablo,
Desde Multimedia (en el menú lateral) las puedes subir bien?
Hola! Gracias por la respuesta…
Las imágenes me las carga el sistema, las carga en “uploads” como todas. El problema es que no me lo carga en el campo personalizado que he generado con tus funciones. O sea, yo le doy click a “seleccionar imágen” me abre el Multimedia, selecciono el archivo… lo carga; le doy click a “insertar en la entrada” y no me aparece la preview como vos mostras a comienzos en el articulo. Actualizo la entrada y veo si se carga en el theme, pero tampoco…
Probablemente algo no este funcionando correctamente… o yo le erre en algo…
Hola Juan Pablo,
No sé que puede estarte fallando… Acabo de hacer un copia-pega rápido de todo el código (menos la parte inicial que se repite para seleccionar entradas y páginas) y funciona bien….
Hola Juan! Gracias nuevamente…
Hice una copy/Paste rápido, por si había errado en algo, pero nada… no se que puede estar fallandome… Tengo que dar click en “Insertar en la entrada” verdad? digo, en Multimedia…
Bueno, después me pongo con más tiempo, a ver si lo soluciono… Cualquier cosa vuelvo a preguntar! Muchas Gracias!
Si, en el cargador multimedia en “Insertar en la entrada”. En el copy/paste rápido no habrás copiado la parte inicial dos veces? (está puesto si quieres sólo para posts o si quieres para posts y páginas)
No, revise y lo pegue tal cual al primero, solo para post… y cambie el ‘page’ por ‘post’ dado que yo luego llamo al campo personalizado desde un single.php … La verdad, no sé, lo revise mil veces… Tendrá algo que ver con la integración del jquery? no, no?
Tienes Chrome o Firebug para ver errores de Javascript que se puedan estar produciendo?
Tengo Firebug en Mozilla y Chrome… el tema es que no se leer los problemas de Javascript ni el DOM… solo HTML y CSS…
El script (custom-js.js) lo carga bien… cuando pongo print_r($attachID); me tira en el theme: Array ( [0] =>; [1] =>; [2] =&>; ). Habiendo intentado cargar 3 imágenes. Quizás debería probar las funciones en otra instalación de WP más limpia.
Me habia olvidado de comentarte que encontre un “}” que tira ERROR antes del segundo add_meta_box en el ejemplo para ‘post’ y ‘page’.
Gracias por la ayuda Juan!
Gracias Juan Pablo,
No sé a qué se puede deber…. Yo lo tengo sobre la última versión de WordPress, no sé si dependerá de eso…
Ya quite el “}”, muchas gracias!
Hola Juan!
Lo probé en la última versión (3.3.1) y anda perfectamente! Era ese el problema… estaba usando la versión 3.2.1 asi que para los que tengan este problema… fijarse la versión que usan!
Muchas gracias Juan por compartir! Un abrazo!
Genial, gracias Juan Pablo. Está bien saberlo.
Hola Juan, volvi… es para decirte que descubri finalmente el problema que tenia. no se si tiene relación directa con la versión de WP (por que no lo intente aun)… es más bien el pluggin “Custom Field Template” evidentemente algo sucede cuando ese pluggin está activo… y es lo que NO me permitia usar correctamente tu “pluggin” que a decir verdad es excelente. Tienes idea que puede ser? Un abrazo, y nuevamente… gracias!
Gracias Juan Pablo, ¿quizás el problema sea que haya conflicto con el nombre de alguna de las variables? Prueba a poner un prefijo a todas las variables del tutorial, por ejemplo em_. No sé si con eso se arreglaría.
Excelente post!, era lo que estaba buscando en galerías wordpress desde hace tiempo.
muchas gracias por ayudarnos.
Hola Juan, primero que todo muchísimas gracias por este aporte que ha sido de gran utilidad poder encontrarlo, pero tengo un problema al implementarlo, tengo todo listo pero cuando quiero ver el sitio me aparece:
Warning: Invalid argument supplied for foreach() in C:\wamp\www\wordpress\wp-content\themes\BLANK-Theme\single-portafolio.php on line 23y la verdad es que no sé mucho de programación y no sé cual podría ser el error ya que he copiado y pegado el código tal como lo entregas. Estoy implementando este campo personalizado para subir imagenes y el post de Campos personalizados para las Entradas personalizadas en WordPress. Muchas gracias desde ya por cualquier ayuda.Gracias Claudio,
El error veo que te lo da ya dentro de tu tema. Las imágenes se han subido y guardado bien? Podrías poner el código que tienes en single-portafolio.php?
Muchas gracias por responder, disculpa la demora en contestar, pero estuve un tiempo fuera. No me funcionaba porque no habia subido ninguna imagen, luego de algunos cambios logré que funcionara y de nuevo muchas gracias porque me ha sido muy útil.
Me alegro, gracias Claudio.
Hola he implementado este tutorial en mi sitio de wordpress y funciona perfectamente. Muchísimas gracias por tu aporte.
Solo tengo una duda, quisiera poder mostrar todas estas imagenes que he subido a mi post coo un slideshow al principio del mismo, cree que se podría hacer, soy algo nuevo en esto del php y no me aclaro muy bien. Te agradecería si me ayudaras a mirar en la buena dirección.
Gracias de antemano !!
Si, claro, una vez que tienes las imágenes las puedes usar como quieras. Si no tienes mucha experiencia con PHP y Javascript busca alguna solución ya existente, algún plugin de jQuery para crear un Slideshow, y aplícalo en tu tema.
Hola Juan
Muuuy Bueno y funciona de 10 lo estoy implementando en una galería junto a bxslider cuando lo termine lo paso a la comunidad, tengo una consulta si quisiera agregar a cada imagen una descripción por donnde debería iniciar mi busqueda? intente agregarlo un campo de texto a cada imagen pero no logro guardarlo. la otra opción sería colocarle descripción a la imagen mediante wp pero no logro obtener esa descripción.
saludos y espero puedas ayudarme.
Gracias. Puedes añadir la descripción de cada imagen en el campo de “Descripción” que aparece en el cargador multimedia. Puedes acceder a todos los campos ahí existentes (Título, texto alternativo, descripción, los diferentes tamaños…)
Por ejemplo:
Juan Sos lo Maximo lo pruebo y te comento, una vez terminado te paso el codigo para que lo puedas compartir.
Hola, fantastico el tutorial me ha sido de gran utilidad.
Pero tengo una duda, intente seguir el post en el que te basaste, pero mi ingles es pesimo, y el traductor de google deja bastante que desear.
Como podria aplicar este mismo proceso, pero a una textarea, y como aplicarle diferentes estilos.
Muchas gracias