
🔒 4 Modi per annullare la pubblicazione di un post in WordPress in modo programmatico
Il sito è andato offline dopo l’aggiornamento di un plugin, devi nascondere urgentemente il post problematico prima che sia troppo tardi. E una settimana dopo, riportarlo online quando il bug è stato risolto. Oppure un cliente ti chiede di rimuovere un articolo obsoleto dai risultati di ricerca, ma senza eliminarlo definitivamente.
Cambiare manualmente lo stato dal pannello di amministrazione funziona per uno o due post. Ma quando sono decine o la logica deve scattare in automatico, serve un approccio programmatico. WordPress ti offre quattro modi per depubblicare un post via PHP: dalla bozza sicura fino all’eliminazione completa.
Qui sotto trovi ogni metodo con codice pronto all’uso, una spiegazione e un’indicazione su quando usarlo.
💡 Panoramica rapida:
- Trasformato un post in bozza con
wp_update_poste lo statodraft, il modo più sicuro e reversibile - Reso un post privato (
private), visibile solo ad amministratori ed editor - Mandato un post nel futuro tramite
post_date, il post scompare dai risultati di ricerca fino alla data indicata - Eliminato definitivamente un post con
wp_delete_post, ultima risorsa con avvisi e un backup
Step 1. Bozza: depubblicare un post senza perdere dati
Lo scenario più comune: devi nascondere temporaneamente un post ma conservare tutto il contenuto, l’URL e la possibilità di riportarlo online con un clic. Passare a bozza è l’opzione ideale.
Cambia solo il campo post_status nella tabella wp_posts. Il post in sé, i suoi meta field, gli allegati e l’URL restano intatti. Quando decidi di ripristinarlo, riporti lo stato a publish.
Codice per cambiare lo stato in draft. Aggiungilo al functions.php del tema child o tramite il plugin Code Snippets:
1 /** 2 * Converts a post to draft by ID. 3 * 4 * @param int $post_id ID of the post to unpublish. 5 */ 6 function sd_unpublish_to_draft( $post_id ) { 7 wp_update_post( array( 8 'ID' => $post_id, 9 'post_status' => 'draft', 10 ) ); 11 } 12 13 // Example call: unpublish post with ID = 42 14 sd_unpublish_to_draft( 42 );
wp_update_post() aggiorna un record nel database. Passiamo solo l’ID e il nuovo valore di post_status, WordPress gestisce tutto il resto da solo. Nessun altro campo viene modificato.
Quando usarlo: nascondere temporaneamente un post per revisione, disattivare automaticamente post con rilevanza scaduta (es. promozioni), moderazione programmatica di contenuti generati dagli utenti.
Step 2. Post privato: nascondi ai visitatori, conserva per gli editor
Lo stato privato è una via di mezzo tra pubblico e nascosto. Il post non è visibile ai visitatori normali ma è accessibile ad amministratori ed editor nel pannello di controllo. Utile per materiali interni: istruzioni per il team, bozze di contenuti per clienti, pagine riservate.
Differenza rispetto alla bozza: un post privato è tecnicamente «pubblicato» e può avere un suo URL, ma WordPress verifica i permessi dell’utente prima di mostrarlo. Un visitatore senza la capability read_private_posts vedrà un 404.
Il codice è simile al precedente, cambia solo lo stato:
1 /** 2 * Makes a post private — visible only to admins and editors. 3 * 4 * @param int $post_id Post ID. 5 */ 6 function sd_unpublish_to_private( $post_id ) { 7 wp_update_post( array( 8 'ID' => $post_id, 9 'post_status' => 'private', 10 ) ); 11 } 12 13 // Example call 14 sd_unpublish_to_private( 42 );
Nota: se il sito ha ruoli utente personalizzati con capability su misura, verificali prima di un uso massivo. Di default, i post privati sono visibili ai ruoli editor e administrator.
Quando usarlo: contenuti per abbonamenti premium (abbinato a plugin di membership), documentazione interna del team, nascondere post per una riapprovazione con il cliente prima di ripubblicare.
Step 3. Data futura: depubblicazione differita
Un trucco interessante: invece di cambiare lo stato, puoi «mandare un post nel futuro», impostare la data di pubblicazione all’anno 2050. Il post scompare immediatamente dai risultati di ricerca perché WordPress mostra solo i post con data ≤ al momento attuale.
Questo metodo non modifica post_status: il post resta publish. Semplicemente «non è ancora accaduto» dal punto di vista di WordPress. Un vantaggio: all’occorrenza puoi ripristinare la data reale e il post riapparirà.
Il codice usa i campi post_date e post_date_gmt:
1 /** 2 * Hides a post by setting its publication date far into the future. 3 * 4 * @param int $post_id Post ID. 5 */ 6 function sd_unpublish_to_future( $post_id ) { 7 $future_date = '2050-12-31 23:59:59'; 8 9 wp_update_post( array( 10 'ID' => $post_id, 11 'post_date' => $future_date, 12 'post_date_gmt' => get_gmt_from_date( $future_date ), 13 ) ); 14 } 15 16 // Example call 17 sd_unpublish_to_future( 42 );
get_gmt_from_date() converte l’ora locale in GMT, WordPress memorizza entrambe le versioni della data. Non trascurare il campo GMT: senza, il comportamento al cambio di fuso orario del sito diventa imprevedibile.
Quando usarlo: pubblicazione «programmata» di contenuti, nascondere temporaneamente notizie senza cambiare lo stato, scenari in cui post_status deve restare publish per retrocompatibilità con altri plugin.
Step 4. Eliminazione: quando il post non serve più
wp_delete_post() è un’operazione irreversibile. Il post viene eliminato dal database, insieme a tutti i suoi meta field, relazioni tassonomiche e (opzionalmente) allegati.
Non si tratta di «depubblicazione» in senso stretto. Ma nel contesto della gestione programmatica dei contenuti, l’eliminazione è il quarto strumento, il più drastico. E richiede misure di sicurezza.
Prima di eseguire, fai un backup completo del database. Lo script qui sotto produce prima un elenco di ciò che verrà eliminato e solo dopo la versione di produzione.
1 /** 2 * Deletes a post. First — dry-run with info output, then — actual deletion. 3 * 4 * WARNING: irreversible operation. Backup before running. 5 * 6 * @param int $post_id Post ID. 7 * @param bool $force_delete true — delete permanently (skip trash), false — move to trash. 8 */ 9 function sd_delete_post_safe( $post_id, $force_delete = false ) { 10 $post = get_post( $post_id ); 11 12 if ( ! $post ) { 13 error_log( "Post with ID {$post_id} not found." ); 14 return; 15 } 16 17 // Dry-run: output info without deleting 18 error_log( sprintf( 19 'READY TO DELETE: ID=%d, title="%s", status=%s, attachments=%d', 20 $post->ID, 21 $post->post_title, 22 $post->post_status, 23 count( get_attached_media( '', $post_id ) ) 24 ) ); 25 26 // Uncomment the following line for actual deletion: 27 // wp_delete_post( $post_id, $force_delete ); 28 } 29 30 // Dry-run: only outputs info 31 sd_delete_post_safe( 12341, false );
Il flag $force_delete:
false, il post va nel Cestino, può essere ripristinato entro 30 giorni.true, eliminazione permanente, non recuperabile nemmeno via database (senza un backup).
La funzione registra tramite error_log(), i messaggi appariranno in wp-content/debug.log quando WP_DEBUG è attivo. In produzione, sostituiscilo con un tuo meccanismo di notifica.
Quando usarlo: pulizia automatica di post spam, eliminazione di contenuti scaduti (offerte di lavoro, eventi), rotazione programmatica dei contenuti con rimozione completa dei vecchi articoli.
Confronto dei quattro metodi
Metodo | Stato del post | Reversibilità | Visibilità ai lettori | Visibilità in amministrazione | Quando usarlo |
|---|---|---|---|---|---|
Bozza |
| Completa | Nascosto | Tutti i ruoli con accesso ai post | Nascondere temporaneamente, revisione |
Privato |
| Completa | Nascosto | Amministratori ed editor | Contenuti interni, premium |
Data futura |
| Completa | Nascosto fino alla data | Tutti | Pubblicazione programmata, scaletta temporale |
Eliminazione | - | Solo dal Cestino (30 giorni) | - | Solo amministratori | Eliminazione completa, pulizia |
⁉️🤔 Domande frequenti
Che differenza c’è tra depubblicare ed eliminare?
Depubblicare (bozza/privato/futuro) mantiene il post nel database: contenuto, URL, allegati e cronologia SEO restano. L’eliminazione (
wp_delete_post) cancella il record completamente. Per nascondere temporaneamente, usa sempre una bozza, è sicura e reversibile in un secondo.
Quale metodo non richiede di cambiare post_status?
Mandare nel futuro tramite
post_date. Il post restapublish, ma WordPress lo considera «non ancora accaduto» e non lo mostra ai visitatori. Questo può essere importante se altri plugin o snippet dipendono dallo statopublish.
Posso depubblicare più post in una volta sola?
Sì, avvolgi la chiamata alla funzione in un ciclo su un array di ID. Aggiungi
wp_die()o un limite al numero di post per esecuzione per evitare di bloccare il sito durante un’operazione massiva:array_slice($post_ids, 0, 50)per un lotto da 50.
Devo svuotare la cache dopo un cambio di stato programmatico?
Assolutamente sì. WordPress svuota la cache interna dei post quando viene chiamato
wp_update_post(), ma la cache esterna (plugin come WP Rocket, cache server, CDN) va svuotata separatamente. Aggiungi una chiamata awp_cache_flush()o l’hookclean_post_cachedopo il cambio di stato.
È sicuro eseguire wp_delete_post in produzione?
Solo con misure di sicurezza. Prima di chiamare: (1) verifica
current_user_can('delete_posts'), (2) richiedi conferma tramite un token nonce separato, (3) registra ID e titolo del post in eliminazione. E soprattutto, un backup. Anche nel Cestino, un post vive 30 giorni, dopodiché WordPress lo elimina automaticamente.
Cosa usare nel tuo caso: in conclusione
I quattro metodi coprono quasi ogni scenario di gestione programmatica delle pubblicazioni. La scelta si riduce a una domanda: devi conservare il post?
- Se devi nascondere temporaneamente un post per revisione, vai di bozza (
draft). Un paio di righe, zero rischi. - Se il contenuto è per una cerchia ristretta di persone, stato privato (
private). Gli editor lo vedono, i visitatori no. - Se devi nascondere un post senza cambiarne lo stato, data futura (
post_dateimpostato al 2050). Un trucco ingegnoso ma funzionante. - Se il post non serve più, eliminazione (
wp_delete_post). Ma prima, una prova a secco e un backup completo.
Inizia con un wrapper in functions.php per un metodo, ad esempio la bozza. Una volta capita la logica di wp_update_post(), gli altri tre metodi si mettono a punto in cinque minuti.
E tu quale metodo usi per la gestione programmatica dei post? Scrivilo nei commenti, è interessante confrontare gli approcci.



