Cum să ștergi corect postările cu meta date și atașamente în WordPress
Am o listă cu postări personalizate. Acestea au taxonomii personalizate și de asemenea un fișier atașat.
În lista mea trebuie să ofer linkuri pentru ștergerea acestor intrări. Împreună cu aceasta, trebuie să șterg și fișierul atașat și meta datele.
Am folosit acest cod:
if ( !current_user_can( 'delete_bkroadkill', $post->ID ) )
return;
$link = "<a href='" . wp_nonce_url( get_bloginfo('url') . "/wp-admin/post.php?action=delete&post=" . $post->ID, 'delete-post_' . $post->ID) . "'>".$link."</a>";
echo $before . $link . $after;
Am găsit Delete Post Link to delete post, its meta and attachments dar nu există nicio soluție oferită acolo.
Acest cod va șterge doar postarea, nu și celelalte elemente. Care este metoda corectă de a face acest lucru?
Folosesc această funcție pentru a șterge media asociată unui articol. Dacă dorești să testezi pentru un anumit tip de articol, poți include variabila global $post_type
. Practic, funcția obține toate atașamentele și le șterge una câte una. Referință
function delete_associated_media( $id ) {
$media = get_children( array(
'post_parent' => $id,
'post_type' => 'attachment'
) );
if( empty( $media ) ) {
return;
}
foreach( $media as $file ) {
wp_delete_attachment( $file->ID );
}
}
add_action( 'before_delete_post', 'delete_associated_media' );

Deși funcționează, aș sugera să creezi un array de ID-uri pentru ștergere, apoi să construiești o interogare personalizată și să o execuți. Răspunsul tău va rula mai multe interogări pentru a șterge atașamentele; poate nu este o problemă pentru 3 sau 4, dar dacă ai 100 de atașamente, acest lucru ar putea încetini considerabil procesul.

Acest cod nu rulează mai multe interogări decât al tău. Interoghează o dată pentru a obține atașamentele, apoi 1 interogare pentru a le șterge, toate prin WordPress în loc de orice SQL personalizat.

Incorect. Tu interoghezi baza de date o dată pentru a obține toate atașamentele și apoi o dată pentru fiecare atașament când le ștergi; 10 atașamente = 11 interogări în total. Eu interoghez o dată pentru a obține toate atașamentele și o dată pentru a șterge toate postările asociate; 10 atașamente = 2 interogări. Trebuie menționat, totuși, că codul tău șterge și fișierul, în timp ce al meu doar elimină rândul problematic din baza de date. Presupun că este o preferință personală, dar din punct de vedere al performanței, aș face-o în felul meu și apoi aș rula niște operațiuni de întreținere pentru a elimina atașamentele neasociate (un simplu plugin ar putea gestiona acest lucru).

Înțeleg ce spui. Am crezut că ideea era să eliminați complet atașamentele atunci când un articol este șters.

@s_ha_dum sugerează că meta datele postării vor fi șterse automat. Prin urmare, deoarece reputația lui sugerează că știe despre ce vorbește, această soluție se ocupă doar de atașamentele postării.
Aș sugera să consultați documentația pentru hook-ul before_delete_post(), deoarece este foarte util să poți verifica ce tip de postare este șters, etc.
add_action('before_delete_post', 'delete_post_attachments');
function delete_post_attachments($post_id){
global $post_type;
if($post_type !== 'my_custom_post_type') return;
global $wpdb;
$args = array(
'post_type' => 'attachment',
'post_status' => 'any',
'posts_per_page' => -1,
'post_parent' => $post_id
);
$attachments = new WP_Query($args);
$attachment_ids = array();
if($attachments->have_posts()) : while($attachments->have_posts()) : $attachments->the_post();
$attachment_ids[] = get_the_id();
endwhile;
endif;
wp_reset_postdata();
if(!empty($attachment_ids)) :
$delete_attachments_query = $wpdb->prepare('DELETE FROM %1$s WHERE %1$s.ID IN (%2$s)', $wpdb->posts, join(',', $attachment_ids));
$wpdb->query($delete_attachments_query);
endif;
}
O observație importantă din documentația menționată mai sus -
Este important de reținut că hook-ul rulează doar când utilizatorul WordPress golește Coșul de gunoi. Dacă utilizați acest hook, rețineți că nu se va declanșa dacă utilizatorul șterge un Atașament, deoarece atașamentele sunt șterse definitiv, adică nu sunt trimise în Coșul de gunoi. În schimb, utilizați hook-ul delete_post().
O altă observație
Ar trebui să menționez că, deși codul din acest răspuns va șterge toate rândurile din baza de date legate de atașamentele postării, nu va șterge efectiv atașamentele în sine.
Motivul meu pentru aceasta este performanța. În funcție de numărul de atașamente pe care le aveți, ștergerea lor unul câte unul ar putea dura ceva timp. Sugerez că este mai bine să ștergeți doar intrările din baza de date pentru toate atașamentele inițial pentru a îmbunătăți experiența utilizatorului, iar apoi să rulați o întreținere separată la un moment ulterior pentru a șterge atașamentele reale (este destul de ușor să căutați și să ștergeți fișierele neasociate). Practic, mai puține interogări + mai puțină muncă în timpul experienței utilizatorului = mai puțin timp.

Am actualizat răspunsul meu (evident, înlocuiește my_custom_post_type
cu tipul de postare relevant). De asemenea, verifică link-ul din postare pentru hook-ul before_delete_post(), este explicat în detaliu acolo.
