Получить $image_id после загрузки с помощью media_sideload_image()

21 мар. 2012 г., 18:43:23
Просмотры: 14.5K
Голосов: 14

Мне нужно загрузить изображение и установить его как миниатюру записи. Вот что я пробовал:

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

Но функция media_sideload_image() возвращает не image_id, а HTML-код изображения. Как я могу получить image_id?

0
Все ответы на вопрос 8
4
30

Вот пример того, как обойти это ограничение с помощью действий/хуков:

function new_attachment( $att_id ){
    // запись, к которой прикреплено вложение, является родителем для вложения!

    // получаем запись вложения
    $att = get_post( $att_id );

    // получаем ID родительской записи
    $post_id = $att->post_parent;

    // устанавливаем миниатюру записи
    set_post_thumbnail( $post_id, $att_id );
}

// добавляем функцию выше, чтобы перехватить создание вложения
add_action('add_attachment','new_attachment');

// загружаем вложение по URL
media_sideload_image($image_url, $post_id, $post_id);

// теперь изображение загружено, и функция выше сработала, установив ID миниатюры, поэтому удаляем хук, чтобы избежать проблем
remove_action('add_attachment','new_attachment');

Идея в том, что при выполнении media_sideload_image происходит следующее:

  • изображение загружается
  • добавляется как вложение (запись типа attachment)
  • затем это вложение прикрепляется к записи, ID которой вы указали ($post_id)

Ваша проблема в том, что функция не возвращает ID созданной записи вложения.

Но при создании вложения срабатывает действие, содержащее его ID. Мы можем подключиться к этому действию перед созданием вложения, сохранить миниатюру записи с полученным ID, а затем отключиться.

21 мар. 2012 г. 18:56:45
Комментарии

Блестяще! Это очень помогло.

MTT MTT
11 дек. 2014 г. 19:43:30

Если это ответило на ваш вопрос, не могли бы вы отметить его как правильный?

Tom J Nowell Tom J Nowell
11 дек. 2014 г. 21:07:28

Я не могу понять ваш английский. Кто-нибудь может отредактировать этот пост?

HiDd3N HiDd3N
20 дек. 2016 г. 12:58:25

@HiDd3N Я упростил часть английского текста, теперь в нём используются более распространённые слова с более низким уровнем сложности для чтения

Tom J Nowell Tom J Nowell
20 дек. 2016 г. 16:55:46
0
13

Старые решения больше не нужны.

Вы можете получить ID, установив четвертый параметр ($return) в значение 'id'

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

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

2 нояб. 2017 г. 00:05:31
0

Я создал функцию для получения ID из базы данных, осуществляя поиск по 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;
}

Вы можете получить URL (вместо HTML-кода) с помощью четвертого параметра, установленного в 'src' Кодекс: media_sideload_image()

$src = media_sideload_image($url, $item_id, $desc,'src');
get_attachment_id_from_src($src);
19 мая 2016 г. 15:02:10
1

Ответ @Tom J Nowell абсолютно верен. Я нашел альтернативное решение (используя другие функции), описанное здесь, но мне больше нравится этот вариант.

В моем случае у меня есть массив $posts со всеми записями, которые я хочу вставить, и отдельный массив $media (с теми же ключами $nid, что и в $posts) с медиафайлами. Мой код представляет собой то же решение, что и у Тома, но переработанное с использованием анонимной функции:

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' );
    }

В моем случае я предполагаю, что первый элемент в каждом $media[$nid] должен быть миниатюрой (featured image) для соответствующей записи.

WordPress определенно стоит изменить функцию media_sideload_image(), чтобы она возвращала $id. Фактически функция уже имеет этот идентификатор под рукой, см. исходный код здесь. Более того, существует тикет в трекере с патчами, которые можно применить к ядру WordPress, если нужно получить эту функциональность уже сейчас.

23 окт. 2014 г. 02:48:40
Комментарии

Похоже, это исправление запланировано в версии 4.8

Tom Auger Tom Auger
9 мая 2017 г. 23:03:33
0

Я искал решение и решил изучить код функции <a href="https://codex.wordpress.org/Function_Reference/media_sideload_image" rel="nofollow noreferrer">media_sideload_image()</a>, который оказался очень простым. Она использует функцию <a href="https://codex.wordpress.org/Function_Reference/media_handle_sideload" rel="nofollow noreferrer">media_handle_sideload()</a>, которая возвращает ID вложения.

Я модифицировал её, чтобы она возвращала ID вложения вместо HTML-кода изображения, и даже добавил возможность задавать новое имя файла.

function media_sideload_image_custom($file, $post_id, $desc = null, $file_name = null)
{
    if ( ! empty($file) ) {
        // Скачиваем файл во временное местоположение
        $tmp = download_url( $file );

        // Исправляем имя файла для строк запроса
        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 ( is_wp_error( $tmp ) ) {
            @unlink($file_array['tmp_name']);
            $file_array['tmp_name'] = '';
        }

        // Выполняем валидацию и сохранение
        $id = media_handle_sideload( $file_array, $post_id, $desc );

        // Если есть ошибка при постоянном сохранении, удаляем файл
        if ( is_wp_error($id) ) {
            @unlink($file_array['tmp_name']);
        }
        return $id;
    }
    return null;
}
20 мая 2017 г. 18:40:52
0

Вы можете использовать media_handle_sideload вместо media_sideload_image. Также, если вы используете эту функцию в functions.php, не забудьте добавить следующие три строки.

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 февр. 2023 г. 15:37:35
1

Я посмотрел функцию https://developer.wordpress.org/reference/functions/media_sideload_image/ — у неё есть 4-й аргумент "return_type", который определяет тип возвращаемого значения. Если вам нужен ID, добавьте 4-й аргумент со значением 'id'.

18 янв. 2024 г. 01:28:08
Комментарии

Спасибо! Да, в ответе Олафа, кажется, это есть

Rup Rup
22 янв. 2024 г. 12:24:57
1

В этом примере функция media_sideload_image() используется для загрузки изображения, а затем get_posts() применяется для поиска вложения (attachment) по метаполю _wp_attached_file, которое соответствует имени файла изображения.

  // Загрузка и прикрепление изображения

    $attachment_id = media_sideload_image($image_url, $post_id);
    
    // Получение ID вложения через запрос к записи вложения
    $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;
        
        // Теперь у вас есть $image_id
        echo "ID изображения: $image_id";
    } else {
        echo "Не удалось получить ID изображения.";
    }
18 янв. 2024 г. 08:36:26
Комментарии

Но функция media_sideload_image может вернуть вам ID записи, как и большинство других ответов здесь.

Rup Rup
19 янв. 2024 г. 12:18:42