Come impostare programmaticamente l'immagine in evidenza per un post personalizzato dall'esterno
Sto cercando di recuperare e inserire immagini dall'esterno dell'ambiente WordPress in un post personalizzato tramite PHP.
Come posso spostare/caricare quell'immagine nella directory di upload di WordPress con il formato cartella anno/data come fa WordPress e impostare quell'immagine come immagine in evidenza per il post personalizzato?
E come caricare l'immagine nella galleria del post personalizzato?
Questo è il mio codice
$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 );
Sono riuscito a caricare l'immagine nella mia directory uploads ma non riesco a creare la cartella dell'anno e della data. Esiste una funzione WordPress per questo?

Non può essere fatto semplicemente con media_sideload_image()?
Sembra abbastanza semplice. L'unica complicazione è che se non sei nell'area di amministrazione, devi includere alcune librerie dagli include di WordPress:
// necessari solo se eseguito al di fuori dell'ambiente di amministrazione
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
// immagine di esempio
$image = 'http://example.com/logo.png';
// media_sideload_image restituisce un'immagine HTML, non un ID
$media = media_sideload_image($image, $post_id);
// quindi dobbiamo trovarla per poterla impostare come ID featured
if(!empty($media) && !is_wp_error($media)){
$args = array(
'post_type' => 'attachment',
'posts_per_page' => -1,
'post_status' => 'any',
'post_parent' => $post_id
);
// referenzia la nuova immagine da impostare come featured
$attachments = get_posts($args);
if(isset($attachments) && is_array($attachments)){
foreach($attachments as $attachment){
// ottieni il percorso delle immagini a dimensione intera (senza ridimensionamenti tipo 300x150)
$image = wp_get_attachment_image_src($attachment->ID, 'full');
// verifica se nell'immagine $media creata esiste la stringa dell'URL
if(strpos($media, $image[0]) !== false){
// se sì, abbiamo trovato la nostra immagine. impostala come thumbnail
set_post_thumbnail($post_id, $attachment->ID);
// vogliamo solo un'immagine
break;
}
}
}
}

A partire da WordPress 4.8 puoi impostare il quarto parametro in media_sideload_image
a 'id'
e restituirà il nuovo ID dell'allegato. Esempio: $new_att_id = media_sideload_image($image, $post_id, "descrizione immagine...", 'id'); if(!is_wp_error($new_att_id)) { set_post_thumbnail($post_id, $new_att_id); }

Questo ha funzionato sicuramente per me utilizzando il suggerimento di @DonWilson, basta non dimenticare di includere le 3 librerie dei media se si usa su un form frontend (altrimenti media_sideload_image
non viene trovato). Avevo bisogno di copiare le immagini in evidenza da un sito a un altro multisite tramite switch_to_blog()

Prova questa spiegazione su come caricare utilizzando un percorso e un ID post.
Ecco il codice (per legacy):
/* Importa media da URL
*
* @param string $file_url URL del file esistente dal sito originale
* @param int $post_id L'ID del post a cui il media importato sarà associato
*
* @return boolean True in caso di successo, false in caso di fallimento
*/
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;
}
//directory in cui importare
$artDir = 'wp-content/uploads/2013/06';
//se la directory non esiste, creala
if(!file_exists(ABSPATH.$artDir)) {
mkdir(ABSPATH.$artDir);
}
//rinomina il file
$ext = array_pop(explode("/", $file_url));
$new_filename = 'blogmedia-'.$ext;
if (@fclose(@fopen($file_url, "r"))) { //verifica che il file esista davvero
copy($file_url, ABSPATH.$artDir.$new_filename);
$siteurl = get_option('siteurl');
$file_info = getimagesize(ABSPATH.$artDir.$new_filename);
//crea un array di dati allegato da inserire nella tabella 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;
//inserisci il record nel database
$attach_id = wp_insert_attachment( $artdata, $save_path, $post_id );
//genera metadata e miniature
if ($attach_data = wp_generate_attachment_metadata( $attach_id, $save_path)) {
wp_update_attachment_metadata($attach_id, $attach_data);
}
//opzionale: rendilo l'immagine in evidenza del post a cui è associato
$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;
}

Forse ho capito male, ma perché vorresti farlo al di fuori dell'ambiente WordPress? Replicare questa funzionalità richiederebbe un sacco di lavoro! WordPress fa molto più che semplicemente caricare il file e posizionarlo in una directory specifica, ad esempio controlla quali utenti possono caricare file, aggiunge record nel database per gli upload e imposta relazioni per le immagini in evidenza, esegue azioni e filtri per plugin esterni che dipendono dal caricamento dei file - il tutto rispettando le impostazioni del sito (riguardo alle convenzioni di denominazione, posizione di caricamento dei media, ecc.).
Se cerchi semplicemente di caricare file senza essere loggato nella sezione di amministrazione di WordPress, ad esempio per caricare file da un sito esterno, potresti voler dare un'occhiata all'API XML-RPC e nello specifico al metodo uploadFile
.
Un'altra opzione potrebbe essere quella di scrivere una mini API personalizzata. Fondamentalmente quello che dovresti fare è questo:
- Ottenere il file sul server tramite upload (o far scaricare al server il file da un URL specificato).
- Usare
wp_upload_dir()
per ottenere il percorso della directory di upload esanitize_file_name()
per costruire il percorso e scrivere il file nella posizione risultante. - Usare
wp_insert_attachment()
per memorizzare l'allegato nel database (wp_check_filetype()
sarà utile per impostarepost_mime_type
). Opzionalmente puoi anche impostarepost_parent
e la chiave meta_thumbnail_id
se lo desideri. - Esponi la tua API agli utenti esterni, o richiedi il login, se necessario. Se usi un modulo pubblico, come minimo utilizza
wp_create_nonce()
ewp_verify_nonce()
per rendere il modulo un po' più sicuro.

Sto scrivendo un servizio web per un'applicazione. L'applicazione mi invia un array FILE attraverso il quale voglio inserire i dati del post e l'immagine. Ho inserito i dettagli del post nel database ma sono bloccato nella parte relativa all'immagine.

Consulta la documentazione per wp_insert_attachment()
, dovrebbe fare gran parte di ciò che ti serve secondo me. Sconsiglio vivamente di modificare manualmente il database al di fuori di WordPress, se è quello che stai facendo. Invece, dai un'occhiata al codice sorgente di WordPress e cerca di identificare le parti responsabili dell'aggiunta dei dati dei post, della gestione degli upload di file e dell'inserimento degli allegati. In altre parole, più o meno quello che ho descritto nella mia risposta sopra.

@Simon Ho lo stesso problema. Un altro motivo per cui potresti voler caricare è quando hai un lavoro in batch di immagini che vuoi allegare a diversi post e non vuoi farlo manualmente.

@hitautodestruct: Assolutamente, lo faccio spesso quando migro dati da siti esistenti, sistemi legacy, esportazioni di database, ecc. Il mio punto è che dovresti sempre cercare di sfruttare la funzionalità principale di WordPress per ottenere questo risultato, piuttosto che scrivere semplicemente uno script personalizzato che posiziona le immagini nel percorso corretto (che era in qualche modo ciò che percepivo fosse il fulcro della domanda).
