Obtenha $ image_id após o upload com media_sideload_image ()

10

Quero fazer upload de uma imagem e defini-la como imagem em destaque em uma postagem. O que eu tentei foi o seguinte:

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

Mas media_sideload_image()não está retornando a imagem image_id, mas a renderização html. Como posso obter o image_id?

Xavin
fonte

Respostas:

28

Aqui está um exemplo de como ignorar essa limitação usando ações / 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');

A idéia é que, quando media_sideload_imageexecutado, ele:

  • baixa a imagem
  • adiciona-o como um anexo (uma postagem do tipo attachment)
  • depois anexa esse anexo à postagem cujo ID você forneceu ($ post_id)

Seu problema é que ele não fornece o ID de postagens de anexo recém-criado.

Porém , quando um anexo é criado, uma ação é acionada contendo seu ID. Podemos nos conectar a isso antes de criar o anexo e salvar a miniatura em destaque com o ID da postagem que ele nos forneceu e depois soltá-la depois.

Tom J Nowell
fonte
11
Brilhante! Isso ajudou muito.
M-torin
2
Se isso responder à sua pergunta, você pode marcá-la como correta?
Tom J Nowell
não consigo ler o seu inglês. alguém pode editar esta publicação?
HiDd3N
2
@ HiDd3N Simplifiquei um pouco do inglês usado, ele deveria ter palavras mais comuns com uma idade de leitura mais baixa
Tom J Nowell
6

Eu criei uma função para obter o ID do banco de dados, pesquisando 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;
}

Você pode obter o URL (insted do código html) com um quarto parâmetro definido como 'src' Codex: media_sideload_image ()

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

A resposta de @Tom J Nowell é imediata. Encontrei outra alternativa (usando funções diferentes) explicada aqui, mas gosto mais desta.

No meu caso, tenho uma matriz de $ posts com todas as postagens que desejo inserir e uma $ media separada (as mesmas chaves $ nid que $ posts) com a mídia. Meu código é a mesma solução que a de Tom, mas refatorada para usar uma função 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' );
    }

No meu caso, suponho que o primeiro item em cada $ media [$ nid] seja a imagem em destaque de sua postagem.

O WordPress definitivamente mudará media_sideload_image () para retornar o $ id. De fato, a função tem em mãos, veja a fonte aqui . Na verdade, há um ticket para isso e eles ainda têm patches para aplicar isso ao seu núcleo nesse meio tempo, se você quiser.

Jorge Orpinel
fonte
Parece que é programado para se corrigido em 4,8
Tom Auger
3

Eu estava procurando uma solução e decidi olhar o código para o media_sideload_image()qual era muito simples. Usa o media_handle_sideload()que nos dá o apego id.

Modifiquei-o para retornar o anexo em idvez da fonte html da imagem e até adicionei uma maneira de enviar um novo nome de arquivo.

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
fonte