¿Cómo establecer una imagen destacada (miniatura) mediante URL de imagen al usar wp_insert_post()?
Mientras revisaba la entrada de referencia de la función wp_insert_post(), noté que no hay ningún parámetro en el array requerido que permita establecer la 'Imagen Destacada' para una entrada, que se muestra como la miniatura de la entrada en mi tema.
He investigado funciones como set_post_thumbnail(), como sugirió el Sr. Bennett, pero esta parece ser una adición relativamente nueva a WordPress y al codex de WordPress. Como tal, no hay fuentes que pueda encontrar que expliquen cómo se debe obtener y proporcionar el parámetro $thumbnail_id. Si esta es realmente la función que se debe usar, ¿de qué manera podría proporcionarle un parámetro $thumbnail_id válido cuando todo lo que tengo es una URL de imagen?
¡Gracias de antemano!

Puedes establecer una imagen como imagen destacada (thumbnail) cuando está en tu biblioteca de medios. Para añadir una imagen a tu biblioteca de medios necesitas subirla a tu servidor. WordPress ya tiene una función para colocar imágenes en tu biblioteca de medios, solo necesitas un script que suba tu archivo.
Uso:
Generate_Featured_Image( '../wp-content/mi_imagen.jpg', $post_id );
// $post_id es un ID numérico... También puedes obtener el ID con:
wp_insert_post()
Función:
function Generate_Featured_Image( $image_url, $post_id ){
$upload_dir = wp_upload_dir();
$image_data = file_get_contents($image_url);
$filename = basename($image_url);
if(wp_mkdir_p($upload_dir['path']))
$file = $upload_dir['path'] . '/' . $filename;
else
$file = $upload_dir['basedir'] . '/' . $filename;
file_put_contents($file, $image_data);
$wp_filetype = wp_check_filetype($filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $file, $post_id );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
$res1= wp_update_attachment_metadata( $attach_id, $attach_data );
$res2= set_post_thumbnail( $post_id, $attach_id );
}
http://codex.wordpress.org/Function_Reference/wp_upload_dir
http://codex.wordpress.org/Function_Reference/wp_insert_attachment
EDITADO: Añadida creación de ruta

¡Gracias por tus esfuerzos! Esto solo funciona cuando se usa $upload_dir['basedir'] (en lugar de path), porque cuando inspecciono el adjunto a través de la interfaz de edición de la publicación, se referencia como .../uploads/NOMBRE_DEL_ARCHIVO.EXT mientras que $upload_dir['path'] lo almacenaría en algo como .../uploads/2012/02/NOMBRE_DEL_ARCHIVO.EXT.
Podría ser incluso mejor cambiar cómo se referencia el archivo, pero no sabría cómo hacerlo.

Aprecio tu rápida respuesta :). Sin embargo, sigo obteniendo el mismo resultado, aquí hay una captura de pantalla que muestra mi problema: http://i.imgur.com/iKTNs.png. La sección superior es el resultado de colocar un echo en tu condicional, solo para ver qué está pasando.

Lo cambié nuevamente, no pasé la ruta completa a wp_insert_attachment y wp_generate_attachment_metadata. Espero que esto resuelva el problema.

¡Funciona perfectamente, muchas gracias! Esto también solucionó un problema de tamaño, que aparentemente era causado por rutas incorrectas (aunque la imagen se mostraba). ¡No podría ser mejor!

Gracias por tu excelente código. Solo se necesitó una modificación para que funcionara con mi importación CSV y fue anteponer el postid al nombre del archivo para garantizar que los archivos de imagen permanezcan únicos.

Permíteme también unirme a los elogios. Me encanta este fragmento de código. ¡Gracias por ahorrarme horas de trabajo!

Solo por curiosidad: ¿Es esto seguro? ¿Existe el riesgo de que alguien disfrace una imagen, o wp_check_filetype() se encarga de eso?

Usé el código anterior y lo modifiqué ligeramente para obtener imágenes destacadas que tienen el nombre del slug del post (lo cual consume bastante tiempo si tienes miles de posts):
code
<?php
$slug = basename(get_permalink());
$featuredimageurl = '[TU RUTA]/wp-content/uploads/featuredimages/' . $slug . '.png';
Generate_Featured_Image( $featuredimageurl, $post_id );
?>

el uso de file_get_contents
con una URL no funcionará si allow_url_fopen
está deshabilitado en php.ini
- wp_remote_get
tendrá mayor compatibilidad en diferentes entornos de WordPress

Advertencia: Esta respuesta sobrescribe el archivo si tiene el mismo nombre, ten cuidado. Debería generar nombres usando $post_id o al menos uniqid()

Cuando uso esto, las imágenes creadas en "uploads" tienen un tamaño de archivo de cero.

Me gustaría mejorar la respuesta de Rob utilizando las funciones principales de WP download_url
y media_handle_sideload
<?php
/**
* Descarga una imagen desde la URL especificada y la adjunta a una publicación como imagen destacada.
*
* @param string $file La URL de la imagen a descargar.
* @param int $post_id El ID de la publicación a la que se asociará la imagen destacada.
* @param string $desc Opcional. Descripción de la imagen.
* @return string|WP_Error ID del adjunto, objeto WP_Error en caso de error.
*/
function Generate_Featured_Image( $file, $post_id, $desc ){
// Establece variables para almacenamiento, corrige el nombre del archivo para cadenas de consulta.
preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches );
if ( ! $matches ) {
return new WP_Error( 'image_sideload_failed', __( 'URL de imagen inválida' ) );
}
$file_array = array();
$file_array['name'] = basename( $matches[0] );
// Descarga el archivo a una ubicación temporal.
$file_array['tmp_name'] = download_url( $file );
// Si hay un error al almacenar temporalmente, devuelve el error.
if ( is_wp_error( $file_array['tmp_name'] ) ) {
return $file_array['tmp_name'];
}
// Realiza la validación y el almacenamiento.
$id = media_handle_sideload( $file_array, $post_id, $desc );
// Si hay un error al almacenar permanentemente, elimina el archivo temporal.
if ( is_wp_error( $id ) ) {
@unlink( $file_array['tmp_name'] );
return $id;
}
return set_post_thumbnail( $post_id, $id );
}

Usar las funciones nativas de WordPress es la mejor práctica, gracias.

Por alguna razón, esta versión me dio errores diciendo "No se proporcionó una URL válida", mientras que la respuesta de Rob Vermeer funcionó.

Puedo confirmar que el código modificado no funciona, lo cual es una pena porque la carga lateral de URL sería increíble.

Prueba usando set_post_thumbnail()
.
Edición por Otto: Has aclarado tu pregunta, así que aclararé la respuesta que dio Chip.
Básicamente, necesitas crear el 'attachment' para la publicación también. Cuando una imagen se sube a la biblioteca de medios de WordPress, se crea una entrada especial de publicación para ella con un tipo de publicación de attachment. Este attachment está vinculado a una publicación específica a través del identificador post_parent.
Entonces, si conoces el ID del attachment, llamar a set_post_thumbnail con el objeto o ID de la publicación y el ID del attachment simplemente establecerá la bandera de miniatura de la publicación.
Si aún no has creado el attachment, entonces necesitarás hacerlo primero. La forma más fácil de hacerlo es con wp_insert_attachment()
. Esta función toma un array de algunos parámetros, el nombre del archivo (el archivo ya debe estar en el directorio correcto de subidas), y el ID de la publicación padre a la que quieres adjuntar el attachment.
Simplemente tener un archivo subido y adjunto a una publicación no hace nada automáticamente. Esto es simplemente un mecanismo de categorización. El mecanismo de galería, por ejemplo, usa las imágenes adjuntas de una publicación para construir la [galería] de esa publicación. Una miniatura para una publicación es solo una de las imágenes adjuntas que se ha configurado como miniatura.
Puedes encontrar más información sobre cómo usar wp_insert_attachment en el codex (enlace arriba).

¡Gracias por tu respuesta! ¿Pero cómo obtendría el ID de la miniatura? Estoy comenzando con una URL de imagen, así que supongo que debería agregar una imagen a la biblioteca de WordPress usando otra función, ¿no?

Como ya estás insertando una publicación, había asumido que ya estabas adjuntando imágenes a la publicación que estás insertando. ¿No es una suposición válida?

Lo siento, pero aún no he descubierto cómo adjuntar imágenes a una publicación mediante una URL. Además, no quiero que la imagen se muestre realmente en la publicación en sí. Actualmente estoy buscando la función que devolverá el $thumbnail_id, y pensé que tal vez wp_insert_attachment() funcionaría, hasta que noté que ya requería que el adjunto estuviera en el directorio de subida. No sé cómo obtener un archivo de imagen allí por su URL, y no estoy seguro de si esta es la función que estoy buscando en primer lugar. ¡Gracias por tu ayuda!

¿Podrías reescribir tu pregunta con esta información, para describir mejor lo que estás tratando de lograr? (O deja esta tal como está y crea una nueva pregunta para preguntar cómo obtener el ID del adjunto al insertar una publicación).

Acabo de encontrar esto y lo he simplificado mucho, funciona pero no soy un experto en seguridad
if(!empty($_FILES)){
require_once( ABSPATH . 'wp-admin/includes/post.php' );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
$post_ID = "tu id de post!"; // Reemplaza con el ID de tu post
$attachment_id = media_handle_upload( 'file', $post_ID );
set_post_thumbnail( $post_ID, $attachment_id );
}
¿Simple o no? Después de incluir los archivos necesarios, WordPress se encargará del media y lo subirá, luego lo establecerá como imagen destacada.

set_post_thumbnail()
es la mejor función para este requisito.
Creo que puedes encontrar el ID de un adjunto mediante get_children()
o get_posts()
. El resultado es un array y dentro de este array está el ID. El siguiente ejemplo es para pruebas; espero que funcione; lo escribí sin probarlo, solo como borrador.
Para tu requisito es importante que reemplaces get_the_ID()
con tu post-ID
; esto devuelve el ID del Adjunto y puedes usarlo para set_post_thumbnail()
.
$attachments = get_children(
array(
'post_parent' => get_the_ID(),
'post_type' => 'attachment',
'post_mime_type' => 'image'
)
);
foreach ( $attachments as $attachment_id => $attachment ) {
echo wp_get_attachment_image($attachment_id);
}

Necesitas cargar algunas bibliotecas principales para mantenerlo simple.
function attach_image_from_url_to_post($image_url, $post_id) {
// Verifica si la función existe (es parte de media.php)
if (!function_exists('media_sideload_image')) {
require_once(ABSPATH . 'wp-admin/includes/image.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
}
// Descarga y carga lateralmente la imagen
$image = media_sideload_image($image_url, $post_id, null, 'id');
// Si hay un error, devuélvelo
if (is_wp_error($image)) {
return $image;
}
// Establece la imagen como imagen destacada (thumbnail del post)
set_post_thumbnail($post_id, $image);
return true;
}
