¿Es posible establecer una imagen destacada con una URL de imagen externa?
Sé que existen plugins que obtienen imágenes desde URLs remotas y las almacenan localmente. Solo quiero saber si es posible no almacenar la imagen en la Biblioteca de Medios y aún así usarla como Imagen Destacada.

Sí, es posible y bastante fácil.
Este es el flujo de trabajo que sugiero:
- Colocar en algún lugar una interfaz para insertar la URL de la imagen destacada. Probablemente la mejor opción es usar el gancho de filtro
'admin_post_thumbnail_html'
- Usar el gancho de acción
'save_post'
para guardar la URL (después de una rutina de seguridad y validación) en un meta post personalizado - Usar el gancho de filtro
'post_thumbnail_html'
para mostrar el marcado correcto<img>
, sobrescribiendo el predeterminado, si el post para el que se requiere la imagen destacada tiene el meta post con la imagen externa
Para que funcione, este flujo de trabajo necesita que la imagen destacada se muestre en la plantilla usando las funciones get_the_post_thumnbail()
o the_post_thumbnail()
.
Además, debemos asegurarnos de que el valor meta '_thumbnail_id'
tenga un valor no vacío cuando establezcamos el meta para la URL externa, de lo contrario has_post_thumbnail()
devolverá falso para posts que solo tengan una imagen destacada externa.
De hecho, es posible que un post tenga tanto una imagen destacada estándar local como una establecida mediante nuestro flujo de trabajo, y en este caso se usará la externa.
Para implementar nuestro flujo de trabajo necesitamos una función para validar la URL usada como imagen destacada externa, porque tenemos que asegurarnos de que sea una URL de imagen válida.
Hay diferentes formas de hacer esta tarea; aquí uso una forma muy simple que solo mira la URL, sin descargar la imagen. Esto funciona solo para URLs de imágenes estáticas y no verifica que la imagen realmente exista, pero es rápido. Modifícalo a algo más avanzado si lo necesitas (aquí hay alguna ayuda).
function url_is_image( $url ) {
if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
return FALSE;
}
$ext = array( 'jpeg', 'jpg', 'gif', 'png' );
$info = (array) pathinfo( parse_url( $url, PHP_URL_PATH ) );
return isset( $info['extension'] )
&& in_array( strtolower( $info['extension'] ), $ext, TRUE );
}
Bastante fácil. Ahora agreguemos los 3 ganchos descritos en el flujo de trabajo anterior:
add_filter( 'admin_post_thumbnail_html', 'thumbnail_url_field' );
add_action( 'save_post', 'thumbnail_url_field_save', 10, 2 );
add_filter( 'post_thumbnail_html', 'thumbnail_external_replace', 10, PHP_INT_MAX );
y las funciones relacionadas. Primero la que muestra el campo en el admin:
function thumbnail_url_field( $html ) {
global $post;
$value = get_post_meta( $post->ID, '_thumbnail_ext_url', TRUE ) ? : "";
$nonce = wp_create_nonce( 'thumbnail_ext_url_' . $post->ID . get_current_blog_id() );
$html .= '<input type="hidden" name="thumbnail_ext_url_nonce" value="'
. esc_attr( $nonce ) . '">';
$html .= '<div><p>' . __('O', 'txtdomain') . '</p>';
$html .= '<p>' . __( 'Introduce la URL para la imagen externa', 'txtdomain' ) . '</p>';
$html .= '<p><input type="url" name="thumbnail_ext_url" value="' . $value . '"></p>';
if ( ! empty($value) && url_is_image( $value ) ) {
$html .= '<p><img style="max-width:150px;height:auto;" src="'
. esc_url($value) . '"></p>';
$html .= '<p>' . __( 'Deja la URL vacía para eliminar.', 'txtdomain' ) . '</p>';
}
$html .= '</div>';
return $html;
}
Nota que he usado 'txtdomain'
como el dominio de texto, pero deberías usar un dominio de texto propio y registrado.
Así se ve la salida cuando está vacío:
Y así se ve después de haber añadido una URL de imagen y guardado/actualizado el post:
Así que, ahora nuestra interfaz de admin está lista, escribamos la rutina de guardado:
function thumbnail_url_field_save( $pid, $post ) {
$cap = $post->post_type === 'page' ? 'edit_page' : 'edit_post';
if (
! current_user_can( $cap, $pid )
|| ! post_type_supports( $post->post_type, 'thumbnail' )
|| defined( 'DOING_AUTOSAVE' )
) {
return;
}
$action = 'thumbnail_ext_url_' . $pid . get_current_blog_id();
$nonce = filter_input( INPUT_POST, 'thumbnail_ext_url_nonce', FILTER_SANITIZE_STRING );
$url = filter_input( INPUT_POST, 'thumbnail_ext_url', FILTER_VALIDATE_URL );
if (
empty( $nonce )
|| ! wp_verify_nonce( $nonce, $action )
|| ( ! empty( $url ) && ! url_is_image( $url ) )
) {
return;
}
if ( ! empty( $url ) ) {
update_post_meta( $pid, '_thumbnail_ext_url', esc_url($url) );
if ( ! get_post_meta( $pid, '_thumbnail_id', TRUE ) ) {
update_post_meta( $pid, '_thumbnail_id', 'by_url' );
}
} elseif ( get_post_meta( $pid, '_thumbnail_ext_url', TRUE ) ) {
delete_post_meta( $pid, '_thumbnail_ext_url' );
if ( get_post_meta( $pid, '_thumbnail_id', TRUE ) === 'by_url' ) {
delete_post_meta( $pid, '_thumbnail_id' );
}
}
}
La función, después de algunas comprobaciones de seguridad, mira la URL enviada y si está bien, la guarda en el meta post '_thumbnail_ext_url'
. Si la URL está vacía y el meta estaba guardado, se elimina, permitiendo eliminar el meta simplemente vaciando el campo de URL externa.
Lo último que queda por hacer es mostrar el marcado de la imagen destacada cuando nuestra URL de imagen externa está establecida en el meta:
function thumbnail_external_replace( $html, $post_id ) {
$url = get_post_meta( $post_id, '_thumbnail_ext_url', TRUE );
if ( empty( $url ) || ! url_is_image( $url ) ) {
return $html;
}
$alt = get_post_field( 'post_title', $post_id ) . ' ' . __( 'miniatura', 'txtdomain' );
$attr = array( 'alt' => $alt );
$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, NULL );
$attr = array_map( 'esc_attr', $attr );
$html = sprintf( '<img src="%s"', esc_url($url) );
foreach ( $attr as $name => $value ) {
$html .= " $name=" . '"' . $value . '"';
}
$html .= ' />';
return $html;
}
Hemos terminado.
Qué queda por hacer
En la salida de la imagen destacada no he usado propiedades width
o height
, ni clases que WordPress normalmente añade, como 'attachment-$size'
. Eso es porque detectar el tamaño de una imagen requiere trabajo extra que ralentizará la carga de la página, especialmente si tienes más de una imagen destacada en la página.
Si necesitas esos atributos, puedes usar mi código añadiendo un callback al filtro wp_get_attachment_image_attributes'
(es un gancho estándar de WordPress) o quizás puedes modificar mi código para detectar el tamaño de la imagen y mostrar los atributos y clases relacionados.
Plugin Gist
Todo el código publicado aquí, con la excepción de añadir una inicialización propia del dominio de texto, está disponible como un plugin completamente funcional en un Gist aquí. El código allí usa un namespace, por lo que requiere PHP 5.3+.
Notas
Por supuesto, debes asegurarte de que tienes licencia y autorización para usar y enlazar imágenes en tu sitio desde fuentes externas.

¿Puedes explicar qué código, en qué página tenemos que escribir? Soy principiante en PHP/Wordpress así que por favor explica paso a paso. Gracias
