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

21 mar 2012, 18:43:23
Vistas: 14.5K
Votos: 14

Quiero subir una imagen y establecerla como imagen destacada en una publicación. Lo que intenté 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 el HTML de la imagen renderizada. ¿Cómo puedo obtener el image_id?

0
Todas las respuestas a la pregunta 8
4
30

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

function new_attachment( $att_id ){
    // ¡El post al que se subió este archivo adjunto es el padre del adjunto!

    // obtener el post del adjunto
    $att = get_post( $att_id );

    // tomar su post padre
    $post_id = $att->post_parent;

    // establecer el post destacado
    set_post_thumbnail( $post_id, $att_id );
}

// agregar la función anterior para capturar la creación del adjunto
add_action('add_attachment','new_attachment');

// cargar el adjunto desde la URL
media_sideload_image($image_url, $post_id, $post_id);

// ahora tenemos la imagen, y la función anterior se habrá ejecutado estableciendo el ID del thumbnail en el proceso, así que eliminemos el hook para no causar más problemas
remove_action('add_attachment','new_attachment');

La idea es que cuando se ejecuta media_sideload_image, esto:

  • descarga la imagen
  • la agrega como un adjunto (un post de tipo attachment)
  • luego adjunta ese adjunto al post cuyo ID proporcionaste ($post_id)

Tu problema es que no proporciona el ID del post de adjunto recién creado.

Pero, cuando se crea un adjunto, se dispara una acción que contiene su ID. Podemos engancharnos a esto antes de crear el adjunto, guardar el thumbnail destacado con el ID de post que nos dio, y luego desengancharnos después.

21 mar 2012 18:56:45
Comentarios

¡Brillante! Eso ayudó muchísimo.

MTT MTT
11 dic 2014 19:43:30

Si esto responde a tu pregunta, ¿podrías marcarla como correcta?

Tom J Nowell Tom J Nowell
11 dic 2014 21:07:28

No puedo leer tu inglés. ¿Alguien puede editar esta publicación?

HiDd3N HiDd3N
20 dic 2016 12:58:25

@HiDd3N He simplificado algo del inglés utilizado, debería tener palabras más comunes con un nivel de lectura más bajo

Tom J Nowell Tom J Nowell
20 dic 2016 16:55:46
0
13

Ya no es necesario utilizar las soluciones antiguas.

Puedes obtener el ID configurando un cuarto parámetro ($return) como 'id'

<?php media_sideload_image($file, $post_id, $desc, $return); ?>

https://codex.wordpress.org/Function_Reference/media_sideload_image

2 nov 2017 00:05:31
0

He creado una función para obtener el ID desde la base de datos, 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;
}

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

$src = media_sideload_image($url, $item_id, $desc,'src');
get_attachment_id_from_src($src);
19 may 2016 15:02:10
1

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

En mi caso tengo un array de $posts con todas las entradas que quiero insertar y un $media separado (con las mismas claves $nid que $posts) con los medios. Mi código es la misma solución que la de Tom pero refactorizada 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 asumo que el primer elemento en cada $media[$nid] debería ser la imagen destacada de su entrada.

WordPress definitivamente debería cambiar media_sideload_image() para que devuelva el $id. De hecho la función lo tiene a mano, mira el código fuente aquí. Incluso hay un ticket de seguimiento para esto y ya tienen parches para aplicar esto al núcleo mientras tanto si lo deseas.

23 oct 2014 02:48:40
Comentarios

Parece que está programado para ser corregido en la versión 4.8

Tom Auger Tom Auger
9 may 2017 23:03:33
0

Estaba buscando una solución y decidí revisar el código de <a href="https://codex.wordpress.org/Function_Reference/media_sideload_image" rel="nofollow noreferrer">media_sideload_image()</a> que era bastante sencillo. Utiliza <a href="https://codex.wordpress.org/Function_Reference/media_handle_sideload" rel="nofollow noreferrer">media_handle_sideload()</a> que nos proporciona el id del adjunto.

Lo modifiqué para que devuelva el id del adjunto en lugar del código HTML de la imagen, e incluso añadí 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) ) {
        // Descargar archivo a ubicación temporal
        $tmp = download_url( $file );

        // corregir nombre de archivo para consultas con parámetros
        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;

        // Si hay error al almacenar temporalmente, eliminar
        if ( is_wp_error( $tmp ) ) {
            @unlink($file_array['tmp_name']);
            $file_array['tmp_name'] = '';
        }

        // realizar validación y almacenamiento
        $id = media_handle_sideload( $file_array, $post_id, $desc );

        // Si hay error al almacenar permanentemente, eliminar
        if ( is_wp_error($id) ) {
            @unlink($file_array['tmp_name']);
        }
        return $id;
    }
    return null;
}
20 may 2017 18:40:52
0

Puedes usar media_handle_sideload en lugar de media_sideload_image. Además, si estás usando esta función en functions.php, no olvides agregar las siguientes tres líneas.

require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');

$id = media_handle_sideload( $file_array, $post_id );
var_dump($id);
24 feb 2023 15:37:35
1

Revisé la función, https://developer.wordpress.org/reference/functions/media_sideload_image/ -- tiene un cuarto argumento, "return_type" que especifica la respuesta. Si deseas el ID, añade el cuarto argumento con 'id'

18 ene 2024 01:28:08
Comentarios

¡Gracias! Sí, creo que la respuesta de Olaf incluye eso

Rup Rup
22 ene 2024 12:24:57
1

En este ejemplo, media_sideload_image() se utiliza para cargar la imagen de forma externa, y luego get_posts() se usa para consultar la publicación de adjunto buscando un adjunto con la clave meta _wp_attached_file que coincida con el nombre del archivo de la imagen

  // Descargar y adjuntar la imagen

    $attachment_id = media_sideload_image($image_url, $post_id);
    
    // Obtener el ID del adjunto consultando la publicación de adjunto
    $attachment = get_posts(array('post_type' => 'attachment', 'posts_per_page' => 1, 'post_status' => 'inherit', 'meta_query' => array(array('key' => '_wp_attached_file', 'value' => basename($image_url)))));
    if (!empty($attachment)) {
        $image_id = $attachment[0]->ID;
        
        // Ahora tienes el $image_id
        echo "ID de la imagen: $image_id";
    } else {
        echo "No se pudo obtener el ID de la imagen.";
    }
18 ene 2024 08:36:26
Comentarios

Pero media_sideload_image puede devolverte el ID de la publicación, como en la mayoría de las otras respuestas aquí.

Rup Rup
19 ene 2024 12:18:42