Cum setăm programatic imaginea reprezentativă pentru o postare personalizată din exterior
Încerc să preiau și să inserez imagini în afara mediului WordPress într-o postare personalizată folosind PHP.
Cum pot muta/încărca acea imagine în directorul de încărcare WordPress cu formatul folder an/dată așa cum face WordPress și să setez acea imagine ca imagine reprezentativă pentru postarea personalizată?
De asemenea, cum pot încărca imaginea în galeria postării personalizate?
Mai jos este codul meu
$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 );
Am reușit să încarc imaginea în directorul meu de încărcări, dar nu pot crea folderul pentru an și dată. Există vreo funcție WordPress pentru asta?

Nu se poate face acest lucru simplu cu media_sideload_image()?
Pare destul de simplu. Singura condiție este că dacă nu ești în zona de administrare, trebuie să incluzi câteva biblioteci din WordPress includes:
// acestea sunt necesare doar dacă execuția are loc în afara mediului de administrare
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
// exemplu de imagine
$image = 'http://example.com/logo.png';
// funcția magică media_sideload_image returnează un tag HTML de imagine, nu un ID
$media = media_sideload_image($image, $post_id);
// prin urmare, trebuie să o găsim pentru a o seta ca fiind ID-ul imaginii reprezentative
if(!empty($media) && !is_wp_error($media)){
$args = array(
'post_type' => 'attachment',
'posts_per_page' => -1,
'post_status' => 'any',
'post_parent' => $post_id
);
// referință către noua imagine pentru a o seta ca fiind reprezentativă
$attachments = get_posts($args);
if(isset($attachments) && is_array($attachments)){
foreach($attachments as $attachment){
// obține sursa imaginilor în dimensiune completă (fără denumiri gen 300x150 în cale)
$image = wp_get_attachment_image_src($attachment->ID, 'full');
// verifică dacă URL-ul există în imaginea $media pe care am creat-o
if(strpos($media, $image[0]) !== false){
// dacă da, am găsit imaginea. Setează-o ca imagine reprezentativă
set_post_thumbnail($post_id, $attachment->ID);
// dorim doar o singură imagine
break;
}
}
}
}

Începând cu WordPress 4.8, poți seta al patrulea parametru în media_sideload_image
la 'id'
și va returna noul ID al atașamentului. Exemplu: $new_att_id = media_sideload_image($image, $post_id, "descrierea imaginii...", 'id'); if(!is_wp_error($new_att_id)) { set_post_thumbnail($post_id, $new_att_id); }

Acest lucru a funcționat cu siguranță pentru mine folosind sugestia lui @DonWilson, doar nu uitați să includeți cele 3 biblioteci media dacă utilizați pe un formular front-end (altfel media_sideload_image
nu este găsită). Am avut nevoie să copiez imaginile reprezentative de pe un site pe un alt site din rețeaua multisite prin switch_to_blog()

Încearcă această explicație despre încărcarea folosind o cale și un ID de postare.
Iată codul (pentru versiuni mai vechi):
/* Importă media din URL
*
* @param string $file_url URL-ul fișierului existent de pe site-ul original
* @param int $post_id ID-ul postării căreia i se atașează media importată
*
* @return boolean True la succes, false la eșec
*/
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;
}
//directorul în care se importă
$artDir = 'wp-content/uploads/2013/06';
//dacă directorul nu există, creează-l
if(!file_exists(ABSPATH.$artDir)) {
mkdir(ABSPATH.$artDir);
}
//redenumește fișierul
$ext = array_pop(explode("/", $file_url));
$new_filename = 'blogmedia-'.$ext;
if (@fclose(@fopen($file_url, "r"))) { //verifică dacă fișierul există
copy($file_url, ABSPATH.$artDir.$new_filename);
$siteurl = get_option('siteurl');
$file_info = getimagesize(ABSPATH.$artDir.$new_filename);
//creează un array cu datele atașamentului pentru inserare în tabelul 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;
//inserează înregistrarea în baza de date
$attach_id = wp_insert_attachment( $artdata, $save_path, $post_id );
//generează metadata și thumbnails
if ($attach_data = wp_generate_attachment_metadata( $attach_id, $save_path)) {
wp_update_attachment_metadata($attach_id, $attach_data);
}
//opțional - setează ca imagine reprezentativă a postării
$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;
}

Poate înțeleg greșit, dar de ce ai vrea să faci asta în afara mediului WordPress? Replicarea acestei funcționalități ar implica multă muncă! WordPress face mult mai mult decât simpla încărcare a fișierului și plasarea lui într-un director specific, de exemplu controlează care utilizatori au voie să încarce fișiere, adaugă înregistrări în baza de date pentru încărcări și stabilește relații de imagine reprezentativă, execută acțiuni și filtre pentru plugin-uri externe care depind de încărcarea de fișiere - toate acestea în timp ce respectă setările site-ului (în ceea ce privește convențiile de denumire, locația de încărcare a fișierelor, etc).
Dacă pur și simplu dorești să încarci fișiere fără a fi autentificat în secțiunea de administrare WordPress, de exemplu pentru încărcarea fișierelor de pe un site extern, ai putea să te uiți la API-ul XML-RPC și mai exact la metoda uploadFile
.
O altă opțiune ar putea fi să scrii tu un mini API. Practic, ceea ce ai vrea să faci este următorul lucru:
- Obține fișierul pe server prin încărcare (sau determină serverul să-l descarce dintr-un URL specificat).
- Folosește
wp_upload_dir()
pentru a obține calea directorului de încărcare șisanitize_file_name()
pentru a construi calea și a scrie fișierul în locația rezultată. - Folosește
wp_insert_attachment()
pentru a stoca atașamentul în baza de date (wp_check_filetype()
va fi util pentru setareapost_mime_type
). Opțional, poți seta șipost_parent
și cheia meta_thumbnail_id
dacă dorești. - Expune API-ul tău utilizatorilor externi sau solicită autentificare, după caz. Dacă folosești un formular public, cel puțin utilizează
wp_create_nonce()
șiwp_verify_nonce()
pentru a face formularul puțin mai sigur.

Scriu un serviciu web pentru o aplicație. Aplicația îmi trimite un array FILE prin care vreau să introduc datele postării și imaginea. Am introdus detaliile postării în baza de date, dar sunt blocat la partea cu imaginea.

Verifică documentația pentru wp_insert_attachment()
, ar trebui să facă cam tot ce ai nevoie, cred. Aș recomanda cu tărie să eviți modificarea manuală a bazei de date în afara WordPress, dacă asta faci. În schimb, uită-te la codul sursă al WordPress și încearcă să identifici părțile responsabile pentru adăugarea datelor postării, gestionarea încărcărilor de fișiere și inserarea atașamentelor. Cu alte cuvinte, cam ceea ce am descris în răspunsul meu de mai sus.

@Simon Am aceeași problemă. Un alt motiv pentru care ai putea dori să încarci este atunci când ai un job în lot de imagini pe care vrei să le atașezi la diferite postări și nu vrei să faci asta manual.

@hitautodestruct: Absolut, fac asta adesea când migrez date de pe site-uri existente, sisteme vechi, exporturi de baze de date etc. Ideea este că ar trebui să încerci întotdeauna să profiți de funcționalitățile de bază ale WordPress pentru a realiza acest lucru, în loc să scrii propriul script care plasează imaginile în locația corectă (ceea ce, într-o oarecare măsură, am perceput că era întrebarea).
