Obtenga $ image_id después de subir con media_sideload_image ()

10

Quiero subir una imagen y configurarla como imagen destacada en una publicación. Lo que probé fue esto:

$image_id = media_sideload_image($image_url, $post_id, $post_id);
update_post_meta($post_id, '_thumbnail_id', $image_id);

Pero media_sideload_image()no está devolviendo el image_id, sino la imagen html de renderizado. ¿Cómo puedo obtener el image_id?

Xavin
fuente

Respuestas:

28

Aquí hay un ejemplo de cómo evitar esta limitación usando acciones / ganchos:

function new_attachment( $att_id ){
    // the post this was sideloaded into is the attachments parent!

    // fetch the attachment post
    $att = get_post( $att_id );

    // grab it's parent
    $post_id = $att->post_parent;

    // set the featured post
    set_post_thumbnail( $post_id, $att_id );
}

// add the function above to catch the attachments creation
add_action('add_attachment','new_attachment');

// load the attachment from the URL
media_sideload_image($image_url, $post_id, $post_id);

// we have the image now, and the function above will have fired too setting the thumbnail ID in the process, so lets remove the hook so we don't cause any more trouble 
remove_action('add_attachment','new_attachment');

La idea es que cuando media_sideload_imagese ejecuta, se:

  • descarga la imagen
  • lo agrega como un archivo adjunto (una publicación de tipo attachment)
  • luego adjunta ese archivo adjunto a la publicación cuyo ID proporcionó ($ post_id)

Su problema es que no proporciona la ID de las publicaciones adjuntas recién creadas.

Pero , cuando se crea un archivo adjunto, se dispara una acción que contiene su ID. Podemos conectarnos a esto antes de crear el archivo adjunto y guardar la miniatura destacada con la ID de publicación que nos dio, luego desengancharla.

Tom J Nowell
fuente
1
¡Brillante! Eso ayudó mucho.
m-torin
2
Si esto responde a su pregunta, ¿podría marcarlo como correcto?
Tom J Nowell
No puedo leer tu inglés. ¿Alguien puede editar esta publicación?
HiDd3N
2
@ HiDd3N He simplificado algo del inglés usado, debería tener palabras más comunes con una edad de lectura más baja
Tom J Nowell
6

Construí una función para obtener la ID de DB, buscando por URL.

function get_attachment_id_from_src ($image_src) {
  global $wpdb;
  $query = "SELECT ID FROM {$wpdb->posts} WHERE guid='$image_src'";
  $id = $wpdb->get_var($query);
  return $id;
}

Puede obtener la URL (en lugar del código html) con un cuarto parámetro configurado en 'src' Codex: media_sideload_image ()

$src = media_sideload_image($url, $item_id, $desc,'src');
get_attachment_id_from_src($src);
yondemon
fuente
4

La respuesta de @Tom J Nowell es acertada. Encontré otra alternativa (usando diferentes funciones) explicada aquí, pero me gusta más esta.

En mi caso, tengo una serie de $ posts con todas las publicaciones que quiero insertar y un $ media separado (las mismas claves $ nid que $ posts) con los medios. Mi código es la misma solución que Tom, pero se refactorizó para usar una función anónima:

foreach( $posts as $nid=>$post )
    $posts[$nid]['ID'] = wp_insert_post( $post );

foreach( $posts as $nid=>$post )
    foreach( $media[$nid] as $m=>$mitem ) {

        if( 0 == $m ) add_action( 'add_attachment',
            function( $att_id ) use ($posts, $nid, $mitem) {
                update_post_meta($posts[$nid]['ID'], '_thumbnail_id', $att_id);
                $posts[$nid]['media_urls'][] = $mitem['url'];
            }
        );
        media_sideload_image($mitem['url'], $post['ID']);
        remove_all_actions( 'add_attachment' );
    }

En mi caso, supongo que el primer elemento de cada $ media [$ nid] debe ser la imagen destacada de su publicación.

WordPress debe cambiar definitivamente media_sideload_image () para que devuelva el $ id. De hecho, la función lo tiene a mano, vea la fuente aquí . De hecho, hay un boleto de pista para esto e incluso tienen parches para aplicar esto a su núcleo mientras tanto si lo desea.

Jorge Orpinel
fuente
Parece que está programado para parchearse en 4.8
Tom Auger
3

Estaba buscando una solución y decidí mirar el código, media_sideload_image()que era muy sencillo. Utiliza lo media_handle_sideload()que nos da el apego id.

Lo modifiqué para devolver el archivo adjunto en idlugar de la fuente html de la imagen, e incluso agregué una forma de enviarle un nuevo nombre de archivo.

function media_sideload_image_custom($file, $post_id, $desc = null, $file_name = null)
{
    if ( ! empty($file) ) {
        // Download file to temp location
        $tmp = download_url( $file );

        // fix file filename for query strings
        if( empty($file_name) ) { 
            preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $file, $matches);
            $file_array['name'] = basename($matches[0]);
        } else {
            $file_array['name'] = sanitize_file_name($file_name);
        }
        $file_array['tmp_name'] = $tmp;

        // If error storing temporarily, unlink
        if ( is_wp_error( $tmp ) ) {
            @unlink($file_array['tmp_name']);
            $file_array['tmp_name'] = '';
        }

        // do the validation and storage stuff
        $id = media_handle_sideload( $file_array, $post_id, $desc );

        // If error storing permanently, unlink
        if ( is_wp_error($id) ) {
            @unlink($file_array['tmp_name']);
        }
        return $id;
    }
    return null;
}
Dario Zadro
fuente