Как установить изображение записи (миниатюру) по URL изображения при использовании wp_insert_post()?
Просматривая справочник функций для wp_insert_post(), я заметил, что в массиве параметров нет опции, которая позволила бы установить 'Изображение записи', отображаемое как миниатюра записи в моей теме.
Я изучил такие функции как set_post_thumbnail(), как предложил Mr. Bennett, но это относительно новое дополнение к WordPress и документации WordPress. Поэтому я не могу найти источники, которые объясняют, как получить и передать параметр $thumbnail_id. Если это действительно та функция, которую нужно использовать, каким образом я могу предоставить ей корректный параметр $thumbnail_id, когда у меня есть только URL изображения?
Заранее спасибо!

Вы можете установить изображение в качестве миниатюры записи (поста), если оно находится в вашей медиатеке. Чтобы добавить изображение в медиатеку, вам нужно загрузить его на сервер. WordPress уже имеет функцию для добавления изображений в медиатеку, вам нужен только скрипт для загрузки файла.
Использование:
Generate_Featured_Image( '../wp-content/my_image.jpg', $post_id );
// $post_id - это числовой ID... Вы также можете получить ID с помощью:
wp_insert_post()
Функция:
function Generate_Featured_Image( $image_url, $post_id ){
$upload_dir = wp_upload_dir();
$image_data = file_get_contents($image_url);
$filename = basename($image_url);
if(wp_mkdir_p($upload_dir['path']))
$file = $upload_dir['path'] . '/' . $filename;
else
$file = $upload_dir['basedir'] . '/' . $filename;
file_put_contents($file, $image_data);
$wp_filetype = wp_check_filetype($filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $file, $post_id );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
$res1= wp_update_attachment_metadata( $attach_id, $attach_data );
$res2= set_post_thumbnail( $post_id, $attach_id );
}
http://codex.wordpress.org/Function_Reference/wp_upload_dir
http://codex.wordpress.org/Function_Reference/wp_insert_attachment
ИЗМЕНЕНИЕ: Добавлено создание пути

Спасибо за ваши усилия! Это работает только при использовании $upload_dir['basedir'] (а не path), потому что когда я проверяю вложение через интерфейс редактирования записи, оно ссылается на .../uploads/ИМЯ_ФАЙЛА.РАСШИРЕНИЕ, тогда как $upload_dir['path'] сохранил бы его в что-то вроде .../uploads/2012/02/ИМЯ_ФАЙЛА.РАСШИРЕНИЕ.
Возможно, было бы еще лучше как-то изменить способ ссылки на файл, но я не знаю как.

Ценю ваш быстрый ответ :). Однако я все равно получаю тот же результат, вот скриншот, демонстрирующий мою проблему: http://i.imgur.com/iKTNs.png. Верхняя секция - результат размещения echo в вашем условии, просто чтобы посмотреть, что происходит.

Снова изменил, не передавал полный путь в wp_insert_attachment и wp_generate_attachment_metadata. Надеюсь, это решит проблему.

Работает безупречно, огромное спасибо! Это также исправило проблему с размерами, которая, по-видимому, была вызвана некорректными путями (хотя изображение и отображалось). Лучше и быть не может!

Спасибо за ваш отличный код. Потребовалась всего одна правка, чтобы заставить его работать с моим CSV-импортом — добавление ID поста к имени файла, чтобы гарантировать уникальность файлов изображений.

Позвольте и мне присоединиться к похвалам. Обожаю этот фрагмент кода. Спасибо, что сэкономили мне часы!

Просто интересно: это безопасно? Есть ли риск, что кто-то замаскирует изображение, или функция wp_check_filetype() позаботится об этом?

Я использовал приведенный выше код и немного изменил его, чтобы получать изображения записи, названные как slug поста (что довольно трудоемко, если у вас тысячи записей):
code
<?php
$slug = basename(get_permalink());
$featuredimageurl = '[ВАШ ПУТЬ]/wp-content/uploads/featuredimages/' . $slug . '.png';
Generate_Featured_Image( $featuredimageurl, $post_id );
?>

использование file_get_contents
с URL не будет работать, если allow_url_fopen
отключен в php.ini
- wp_remote_get
будет более совместимым в разных средах WordPress

Предупреждение: Этот ответ перезаписывает файл, если у него такое же имя, будьте осторожны. Следует генерировать имена с использованием $post_id или хотя бы uniqid()

Когда я использую этот код, создаваемые изображения в папке "uploads" имеют нулевой размер файла.

Я хочу улучшить ответ Rob, используя основные функции WordPress download_url
и media_handle_sideload
<?php
/**
* Загружает изображение по указанному URL и прикрепляет его к записи в качестве миниатюры.
*
* @param string $file URL изображения для загрузки.
* @param int $post_id ID записи, к которой будет прикреплено изображение.
* @param string $desc Опционально. Описание изображения.
* @return string|WP_Error ID вложения или объект WP_Error в случае ошибки.
*/
function Generate_Featured_Image( $file, $post_id, $desc ){
// Устанавливаем переменные для хранения, исправляем имя файла для строк запроса.
preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches );
if ( ! $matches ) {
return new WP_Error( 'image_sideload_failed', __( 'Неверный URL изображения' ) );
}
$file_array = array();
$file_array['name'] = basename( $matches[0] );
// Загружаем файл во временное местоположение.
$file_array['tmp_name'] = download_url( $file );
// Если произошла ошибка при временном сохранении, возвращаем ошибку.
if ( is_wp_error( $file_array['tmp_name'] ) ) {
return $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 set_post_thumbnail( $post_id, $id );
}

Использование нативных функций WordPress является лучшей практикой. Спасибо.

По какой-то причине эта версия выдавала мне ошибки с сообщением "Не предоставлен действительный URL", в то время как ответ Роба Вермеера сработал.

Могу подтвердить, что модифицированный код не работает, что очень жаль, так как загрузка по URL была бы отличной возможностью!

Попробуйте использовать функцию set_post_thumbnail()
.
Редакция от Otto: Вы уточнили свой вопрос, поэтому я уточню ответ, который дал Chip.
По сути, вам также нужно создать 'вложение' (attachment) для записи. Когда изображение загружается в медиабиблиотеку WordPress, для него создается специальная запись с типом post_type 'attachment'. Это вложение связано с определенной записью через идентификатор post_parent.
Так что, если вам известен ID вложения, то вызов set_post_thumbnail с объектом записи или его ID и ID вложения просто установит флаг миниатюры записи.
Если вы еще не создали вложение, то сначала вам нужно это сделать. Самый простой способ — использовать функцию wp_insert_attachment()
. Эта функция принимает массив параметров, имя файла (файл уже должен находиться в правильной папке загрузок) и ID родительской записи, к которой вы хотите прикрепить вложение.
Просто загруженный и прикрепленный к записи файл сам по себе ничего не делает. Это просто механизм категоризации. Например, механизм галереи использует прикрепленные изображения записи для построения [gallery] для этой записи. Миниатюра записи — это одно из прикрепленных изображений, которое было установлено в качестве миниатюры.
Подробнее о том, как использовать wp_insert_attachment, можно узнать в Кодексе (ссылка выше).

Спасибо за ответ! Но как мне получить ID миниатюры? Я начинаю с URL изображения, поэтому, наверное, мне нужно сначала добавить изображение в медиатеку WordPress с помощью другой функции?

Раз уж вы уже вставляете запись, я предположил, что вы уже прикрепляете изображения к этой записи. Разве это неверное предположение?

Извините, но я пока не разобрался, как именно прикреплять изображения к записи по URL. Кроме того, мне не нужно, чтобы изображение фактически отображалось в самой записи. Сейчас я ищу функцию, которая вернет $thumbnail_id, и думал, что может подойдет wp_insert_attachment(), пока не заметил, что она требует, чтобы вложение уже было в директории загрузок. Я не знаю, как загрузить файл изображения туда по его URL, и не уверен, что это вообще та функция, которая мне нужна. Спасибо за помощь!

Не могли бы вы переформулировать ваш вопрос с учетом этой информации, чтобы точнее описать, чего вы пытаетесь достичь? (Или оставьте этот вопрос как есть и создайте новый, чтобы спросить, как получить ID вложения при добавлении записи?)

Только что нашел это и сделал намного проще, работает, но я не специалист по безопасности
if(!empty($_FILES)){
require_once( ABSPATH . 'wp-admin/includes/post.php' );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
$post_ID = "ваш ID записи!";
$attachment_id = media_handle_upload( 'file', $post_ID );
set_post_thumbnail( $post_ID, $attachment_id );
}
Просто или как? После подключения нужных файлов WordPress сам обработает медиафайл, загрузит его и установит как миниатюру.

set_post_thumbnail()
— это лучшая функция для данной задачи.
Думаю, вы можете найти ID вложения с помощью get_children()
или get_posts()
. Результат представляет собой массив, внутри которого находится ID. Вот пример для тестирования; я надеюсь, он сработает; написан без тестов, набросок.
Для вашей задачи важно заменить get_the_ID()
на ваш post-ID
; функция возвращает ID вложения, который можно использовать в set_post_thumbnail()
.
$attachments = get_children(
array(
'post_parent' => get_the_ID(),
'post_type' => 'attachment',
'post_mime_type' => 'image'
)
);
foreach ( $attachments as $attachment_id => $attachment ) {
echo wp_get_attachment_image($attachment_id);
}

Вам потребуются основные библиотеки, чтобы упростить задачу.
function attach_image_from_url_to_post($image_url, $post_id) {
// Проверяем, существует ли функция (она находится в media.php)
if (!function_exists('media_sideload_image')) {
require_once(ABSPATH . 'wp-admin/includes/image.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
}
// Загружаем и добавляем изображение
$image = media_sideload_image($image_url, $post_id, null, 'id');
// Если произошла ошибка, возвращаем её
if (is_wp_error($image)) {
return $image;
}
// Устанавливаем изображение как миниатюру записи
set_post_thumbnail($post_id, $image);
return true;
}
