Как программно установить изображение записи для произвольного типа записи извне WordPress

27 мая 2013 г., 10:21:12
Просмотры: 35.2K
Голосов: 16

Я пытаюсь получить и вставить изображения извне среды WordPress в произвольный тип записи через PHP.

Как переместить/загрузить это изображение в директорию загрузок WordPress с форматом папок по году и дате, как это делает WordPress, и установить это изображение как изображение записи для произвольного поста?

А также как загрузить изображение в галерею произвольного поста?

Вот мой код:

$filename = $image['name'];
$target_path = "../wp-content/uploads/";
$target_path = $target_path . $filename;
$wp_filetype = wp_check_filetype(basename($filename), null );
$wp_upload_dir = wp_upload_dir();
$attachment = array(
    'guid' => $wp_upload_dir['baseurl'] . '/' . basename( $filename ),
    'post_mime_type' => $wp_filetype['type'],
    'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
    'post_content' => '',
    'post_status' => 'inherit',
);
$attach_id = wp_insert_attachment( $attachment, $target_path, $post_id );
$attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
wp_update_attachment_metadata( $attach_id, $attach_data );
set_post_thumbnail( $post_id, $attach_id );

Мне удалось загрузить изображение в директорию uploads, но я не могу создать папки с годом и датой. Есть ли функция WordPress для этого?

0
Все ответы на вопрос 3
4
29

Разве это нельзя сделать просто с помощью media_sideload_image()?

Кажется довольно просто. Единственная загвоздка - если вы не в админ-панели, нужно подключить некоторые библиотеки из WordPress includes:

// эти файлы нужны только при выполнении вне админки
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');

// пример изображения
$image = 'http://example.com/logo.png';

// media_sideload_image возвращает HTML изображения, а не ID
$media = media_sideload_image($image, $post_id);

// поэтому нам нужно найти его, чтобы установить как featured ID
if(!empty($media) && !is_wp_error($media)){
    $args = array(
        'post_type' => 'attachment',
        'posts_per_page' => -1,
        'post_status' => 'any',
        'post_parent' => $post_id
    );

    // получаем вложения для поиска нового изображения
    $attachments = get_posts($args);

    if(isset($attachments) && is_array($attachments)){
        foreach($attachments as $attachment){
            // получаем URL полноразмерного изображения (чтобы не было 300x150 в пути)
            $image = wp_get_attachment_image_src($attachment->ID, 'full');
            // проверяем, содержится ли URL в $media изображении, которое мы создали
            if(strpos($media, $image[0]) !== false){
                // если да, то нашли наше изображение. Устанавливаем его как thumbnail
                set_post_thumbnail($post_id, $attachment->ID);
                // нам нужно только одно изображение
                break;
            }
        }
    }
}
29 авг. 2013 г. 22:33:35
Комментарии

Это решение работает просто отлично (y)

Omar Tariq Omar Tariq
2 мая 2015 г. 23:16:42

Куда я могу добавить этот код?

er.irfankhan11 er.irfankhan11
28 июн. 2016 г. 14:51:18

Начиная с WordPress 4.8 вы можете установить четвертый параметр в media_sideload_image как 'id', и функция вернет ID нового вложения. Например: $new_att_id = media_sideload_image($image, $post_id, "описание изображения...", 'id'); if(!is_wp_error($new_att_id)) { set_post_thumbnail($post_id, $new_att_id); }

Don Wilson Don Wilson
3 мар. 2018 г. 00:49:07

Это точно сработало для меня, используя предложение от @DonWilson, просто не забудьте включить 3 медиабиблиотеки, если используете форму на фронтенде (иначе функция media_sideload_image не будет найдена). Мне нужно было скопировать изображения записи с одного сайта на отдельный сайт в мультисайте через switch_to_blog()

cogdog cogdog
2 июн. 2020 г. 23:58:16
0

Попробуйте это объяснение о загрузке с использованием пути и ID записи.

Вот код (для устаревших версий):

/* Импорт медиа по URL
 *
 * @param string $file_url URL существующего файла с исходного сайта
 * @param int $post_id ID записи, к которой будет прикреплен импортированный медиафайл
 *
 * @return boolean True при успехе, false при неудаче
 */

function fetch_media($file_url, $post_id) {
require_once(ABSPATH . 'wp-load.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
global $wpdb;

if(!$post_id) {
    return false;
}

//директория для импорта    
$artDir = 'wp-content/uploads/2013/06';

//если директория не существует, создаем ее 
if(!file_exists(ABSPATH.$artDir)) {
    mkdir(ABSPATH.$artDir);
}

//переименовываем файл
$ext = array_pop(explode("/", $file_url));
$new_filename = 'blogmedia-'.$ext;

if (@fclose(@fopen($file_url, "r"))) { //проверяем, что файл действительно существует
    copy($file_url, ABSPATH.$artDir.$new_filename);


    $siteurl = get_option('siteurl');
    $file_info = getimagesize(ABSPATH.$artDir.$new_filename);

    //создаем массив данных вложения для вставки в таблицу wp_posts
    $artdata = array();
    $artdata = array(
        'post_author' => 1, 
        'post_date' => current_time('mysql'),
        'post_date_gmt' => current_time('mysql'),
        'post_title' => $new_filename, 
        'post_status' => 'inherit',
        'comment_status' => 'closed',
        'ping_status' => 'closed',
        'post_name' => sanitize_title_with_dashes(str_replace("_", "-", $new_filename)),                                            'post_modified' => current_time('mysql'),
        'post_modified_gmt' => current_time('mysql'),
        'post_parent' => $post_id,
        'post_type' => 'attachment',
        'guid' => $siteurl.'/'.$artDir.$new_filename,
        'post_mime_type' => $file_info['mime'],
        'post_excerpt' => '',
        'post_content' => ''
    );

    $uploads = wp_upload_dir();
            $save_path = $uploads['basedir'].'/2013/06/'.$new_filename;

    //вставляем запись в базу данных
    $attach_id = wp_insert_attachment( $artdata, $save_path, $post_id );

    //генерируем метаданные и миниатюры
    if ($attach_data = wp_generate_attachment_metadata( $attach_id, $save_path)) {
        wp_update_attachment_metadata($attach_id, $attach_data);
    }

    //опционально делаем его миниатюрой записи, к которой он прикреплен
    $rows_affected = $wpdb->insert($wpdb->prefix.'postmeta', array('post_id' => $post_id, 'meta_key' => '_thumbnail_id', 'meta_value' => $attach_id));
}
else {
    return false;
}

return true;
}
20 июн. 2013 г. 13:45:16
4

Возможно, я неправильно понимаю, но зачем вам это делать вне среды WordPress? Воссоздание этой функциональности потребует много работы! WordPress делает гораздо больше, чем просто загружает файл и помещает его в определенную директорию. Например, он контролирует, каким пользователям разрешена загрузка файлов, добавляет записи в базу данных для загруженных файлов, устанавливает связи для изображений записи, выполняет действия и фильтры для внешних плагинов, зависящих от загрузки файлов — и все это с учетом настроек сайта (например, соглашений об именовании, расположения загружаемых медиафайлов и т.д.).

Если вам просто нужно загружать файлы без входа в админ-панель WordPress (например, для загрузки файлов с внешнего сайта), вы можете изучить XML-RPC API, в частности метод uploadFile.

Другой вариант — создать небольшой API самостоятельно. В основном вам потребуется сделать следующее:

  1. Получить файл на сервере путем загрузки (или заставить сервер загрузить его по указанному URL).
  2. Использовать wp_upload_dir() для получения пути к директории загрузки и sanitize_file_name() для формирования пути и записи файла по полученному адресу.
  3. Использовать wp_insert_attachment() для сохранения вложения в базе данных (функция wp_check_filetype() поможет установить post_mime_type). При необходимости также можно установить post_parent и мета-ключ _thumbnail_id.
  4. Сделать ваш API доступным для внешних пользователей или требовать авторизацию, в зависимости от потребностей. Если вы используете публичную форму, как минимум применяйте wp_create_nonce() и wp_verify_nonce() для небольшого повышения безопасности формы.
27 мая 2013 г. 11:47:16
Комментарии

Я пишу веб-сервис для приложения. Приложение отправляет мне массив FILE, через который я хочу вставить данные поста и изображение. Я вставил детали поста в базу данных, но застрял на части с изображением.

Faisal Shehzad Faisal Shehzad
27 мая 2013 г. 13:10:49

Проверьте документацию для wp_insert_attachment(), она должна сделать большую часть того, что вам нужно. Я настоятельно не рекомендую вручную изменять базу данных вне WordPress, если это то, что вы делаете. Вместо этого просто посмотрите исходный код WordPress и попытайтесь определить части, отвечающие за добавление данных поста, обработку загрузки файлов и вставку вложений. Другими словами, практически то, что я описал в своем ответе выше.

Simon Simon
27 мая 2013 г. 15:57:18

@Simon У меня такая же проблема. Другая причина, по которой вы можете захотеть загрузить изображения, — это когда у вас есть пакетная обработка изображений, которые вы хотите прикрепить к разным постам, а не делать это вручную.

hitautodestruct hitautodestruct
20 июн. 2013 г. 13:39:04

@hitautodestruct: Абсолютно верно, я часто так делаю при переносе данных с существующих сайтов, унаследованных систем, экспортов баз данных и т.д. Моя мысль в том, что вы всегда должны стремиться использовать базовый функционал WordPress для решения этой задачи, а не просто писать собственный скрипт, который размещает изображения в нужном месте (что, как я понял, в некоторой степени и было в вопросе).

Simon Simon
24 июн. 2013 г. 14:19:26