Verifica aggiornamento vs nuovo post nell'azione save_post

11 apr 2012, 22:43:16
Visualizzazioni: 42K
Voti: 25

È possibile all'interno dell'azione save_post determinare se si tratta di un nuovo post in fase di creazione o di un post esistente che viene aggiornato?

1
Commenti

Non penso che sia possibile. Vedi il mio commento sotto la risposta di @moraleida. Perché hai bisogno di sapere se è un nuovo post o un aggiornamento? Potrebbe esserci una soluzione alternativa o un approccio diverso.

Stephen Harris Stephen Harris
12 apr 2012 21:28:38
Tutte le risposte alla domanda 13
7
20

Dalla versione 3.7 di WordPress - se non ricordo male - l'hook save_post - maggiori informazioni sull'hook e il suo utilizzo su Code Reference: save_post e Codex: save_post - include un terzo parametro $update che può essere utilizzato proprio per determinare questo.

@param     int               $post_ID     ID del post.
@param     WP_Post     $post          Oggetto post.
@param     bool            $update     Indica se si tratta di un post esistente in fase di aggiornamento o meno.


Nota:

$update non è sempre true – puoi verificarlo e testarlo tu stesso con il codice qui sotto. Tuttavia, non è ben documentato, probabilmente il nome non è ottimale e quindi crea aspettative fuorvianti. Il codice seguente può essere utilizzato per eseguire qualche debug, gioca con i punti in cui interrompere l'esecuzione del codice, altrimenti non vedrai le informazioni/messaggi. Penso che il colpevole del comportamento ingannevole sia la gestione delle revisioni e dei salvataggi automatici – che potrebbero essere disabilitati, ma non lo consiglio e non l'ho testato. Non sono sicuro se questo meriti un Trac Ticket, quindi non ne ho aperto uno, se pensi di sì, segui il link e fallo tu. A parte questo, come detto nei commenti, se hai un problema specifico, apri una nuova domanda.

add_action( 'save_post', 'debug_save_post_update', 10, 3 );
function debug_save_post_update( $ID, $post, $update ) {

  echo '<pre>';
  print_r( $post ); echo '<br>';
  echo '$update == ';
  echo $update ? 'true' : 'false';

  //condizioni
  if( ! $update && $post->post_status == "auto-draft" ) {
    // si applica ai nuovi post
    echo ' && $post->post_status == "auto-draft"';
    //die();
  } else if ( ! $update ) {
    // si applica fondamentalmente alla revisione (salvata automaticamente)
    //die();
  } else {
    // si applica all'aggiornamento di un post pubblicato
    // quando c'è una revisione, che normalmente è il caso,
    // comportamento standard di WordPress, allora viene considerato
    // un aggiornamento, ed è qui che nasce la confusione
    // ci sono altri metodi, come controllare il tempo o lo stato del post
    // a seconda del tuo caso d'uso potrebbe essere più appropriato
    // utilizzare una di queste alternative
    //die();
  }

  echo '</pre>';
  //die();
}
1 mag 2015 00:13:02
Commenti

Il parametro $update è SEMPRE vero anche quando si tratta di un nuovo post. Quindi questo parametro è inutile. Non sono sicuro se abbia mai funzionato, ma di sicuro non funziona come documentato nell'ultima versione di WordPress 4.8.

Solomon Closson Solomon Closson
20 lug 2017 23:32:34

@SolomonClosson Se guardi wp_publish_post, allora sì. Ma questo non è vero per il suo utilizzo in wp_insert_post. Ho scritto una funzione di debug, l'ho aggiunta alla risposta.

Nicolai Grossherr Nicolai Grossherr
21 lug 2017 03:11:55

@SolomonClosson Se hai un problema concreto, per favore fai una nuova domanda. Dai un'occhiata alle revisioni per la funzione di debug e una spiegazione.

Nicolai Grossherr Nicolai Grossherr
21 lug 2017 03:34:11

L'hook save_post ha un terzo parametro che è sempre impostato su TRUE, quindi non sono sicuro di cosa c'entri con altri hook, senza parlare di altri hook. Sto parlando dell'hook nella tua risposta. Questo è incorretto.

Solomon Closson Solomon Closson
24 lug 2017 02:42:42

@SolomonClosson Come ho detto, l'hook si verifica due volte: wp_insert_post(), wp_publish_post(). Quest'ultimo riguarda solo i post futuri, lì $update è impostato per essere sempre true. Altrimenti, per quanto riguarda wp_insert_post(), $update non è sempre true.

Nicolai Grossherr Nicolai Grossherr
24 lug 2017 16:08:09

Arrivo in ritardo alla festa, ma ehi, perché no, @Nicolai, quello che dici è ciò che ci si aspetterebbe accadesse, ma non riesco a ottenere che $update sia false anche quando mi collego a 'wp_insert_post'. Non importa dove lo collego, è sempre true. Non capisco perché questo non sia stato risolto.

Caio Mar Caio Mar
2 feb 2019 16:33:08

Ragazzi, solo un'informazione. L'hook viene attivato sia durante il ripristino che durante l'eliminazione di un post.

melvin melvin
9 mag 2019 14:39:48
Mostra i restanti 2 commenti
6
13

Il modo in cui eseguo questo controllo (all'interno di una funzione agganciata) è confrontare la data di pubblicazione e la data di modifica (in GMT per standardizzazione)

function check_new_vs_update( $post_id ){
    $myPost     = get_post($post_id);
    $created    = new DateTime( $myPost->post_date_gmt );
    $modified   = new DateTime( $myPost->post_modified_gmt );
    $diff       = $created->diff( $modified );
    $seconds_difference = ((($diff->y * 365.25 + $diff->m * 30 + $diff->d) * 24 + $diff->h) * 60 + $diff->i)*60 + $diff->s;

    if( $seconds_difference <= 1 ){
        // Nuovo post
    }else{
        // Post aggiornato
    }
}
add_action('save_post', 'check_new_vs_update' );

Questo funziona perché anche alla creazione il post ha una data di 'modifica' associata, che è esattamente uguale alla data di 'creazione', ma permettiamo una variazione di 1 secondo in caso il secondo cambi durante la creazione del post.

10 feb 2015 15:51:45
Commenti

A volte il post_date_gmt è 2019-03-12 01:31:30 e il post_modified_gmt è 2019-03-12 01:31:31. :(

He Yifei 何一非 He Yifei 何一非
12 mar 2019 06:06:47

@HeYifei何一非 ottimo punto, se l'elaborazione inizia alla fine di un determinato secondo, ciò potrebbe accadere. Ho aggiornato la mia risposta, grazie

Cush Cush
12 mar 2019 15:04:13

Ragazzi, solo un'informazione. L'hook viene attivato durante il ripristino e l'eliminazione di un post.

melvin melvin
9 mag 2019 14:39:53

Buono a sapersi @melvin, grazie

Cush Cush
17 ago 2020 20:43:30

Non posso credere che debba essere così complicato. WordPress non smette mai di stupirmi.

amarinediary amarinediary
4 gen 2021 15:29:19

Per essere onesti con loro, hanno letteralmente milioni di utenti ed è un progetto open-source. Purtroppo non possono includere ogni funzionalità e questa probabilmente non è una delle più utilizzate. Negli ultimi anni cose come migliorare l'editor e la sicurezza sono state prioritarie e questo è positivo! Voglio dire, persino jQuery viene aggiornato solo ora! Fino alla versione attuale era rimasto alla 1.x!

Cush Cush
21 gen 2021 15:26:35
Mostra i restanti 1 commenti
4

Alla fine ho semplicemente verificato l'esistenza di un valore personalizzato prima di impostarlo. In questo modo, se si tratta di un post appena creato, il valore personalizzato non esisterebbe ancora.

function attributes_save_postdata($post_id) {
  if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
  if (!wp_verify_nonce($_POST['_attributes_noncename'], plugin_basename(__FILE__))) return;
  if ('page' == $_POST['post_type']) {
    if (!current_user_can('edit_page', $post_id)) return;
  } else {
    if (!current_user_can('edit_post', $post_id)) return;
  }
  $termid = get_post_meta($post_id, '_termid', true);
  if ($termid != '') {
    // è un nuovo record
    $termid = 'update';
  } else {
    // è un record esistente
  }
  update_post_meta($post_id, '_termid', $termid);
}
add_action('save_post', 'attributes_save_postdata');
18 apr 2012 00:50:50
Commenti

Per farlo funzionare, devi prima creare il campo personalizzato usando add_post_meta?

MF1 MF1
9 apr 2013 05:03:17

Secondo il Codex: [update_post_meta] può essere utilizzato al posto della funzione add_post_meta(). http://codex.wordpress.org/Function_Reference/update_post_meta

hereswhatidid hereswhatidid
20 gen 2014 23:46:08

Questo potrebbe fallire, se i post sono stati creati prima che l'hook del codice venga abilitato tramite l'attivazione di un plugin. I post più vecchi non hanno il meta impostato, quindi il primo aggiornamento per loro sarà considerato come nuovo.

Vasu Chawla Vasu Chawla
5 mag 2018 22:13:01

@VasuChawla quindi in quel caso forse è più affidabile verificare l'esistenza isset() (per esempio) di quel termine meta specifico invece che controllare se è vero o falso. Come terza condizione. (if, elseif, ...else)

Viktor Borítás Viktor Borítás
1 ago 2020 20:03:44
1

Esempio di risposta a ialocin con il parametro "update":

function save_func($ID, $post,$update) {

   if($update == false) {
     // fai qualcosa se è la prima pubblicazione
   } else {
     // Fai qualcosa se è un aggiornamento
   }
}

add_action( 'save_post', 'save_func', 10, 3 );
1 dic 2015 19:53:53
Commenti

Un modo migliore per strutturare questo codice sarebbe posizionare prima il blocco di aggiornamento, permettendo di usare semplicemente if($update), oppure mantenere prima il nuovo blocco ma usando if( ! $update ). Quest'ultimo approccio porterà OP verso una pratica migliore ed è preferito rispetto al tuo metodo dagli standard di codifica WordPress in casi come l'operatore ternario

Cush Cush
17 nov 2016 13:38:30
0

Ho appena incontrato l'azione save_post riguardo la creazione e l'aggiornamento. Dopo aver letto il codice sorgente per comprenderne il flusso, ho scoperto che il seguente metodo potrebbe essere utile. Dato che non è stato ancora menzionato prima, vedo se può essere utile a qualcuno. (Il test è stato fatto su Core 5.3.3)

Il flusso di creazione di un Post è approssimativamente:

  1. Dopo aver premuto "Aggiungi nuovo" (Post)
  2. Viene chiamato $post = get_default_post_to_edit( $post_type, true ); dove
  3. get_default_post_to_edit() riceve l'argomento $create_in_db = true
  4. Quindi wp_insert_post() viene chiamato immediatamente, viene creato un post auto-draft, anche se non è salvato. Ogni volta che si clicca su "Aggiungi nuovo", viene creato un auto-draft
  5. $update è sempre true per "Pubblica". Quindi quando si pubblica un nuovo post, è true.

Confrontando l'oggetto $_POST per un nuovo post e per l'aggiornamento o ripubblicazione di un post, la differenza principale è il valore _wp_http_referer: per un nuovo post è /wp-admin/post-new.php

Assunzione: si assume che il post sia pubblicato/aggiunto dall'interfaccia utente. Se viene fatto tramite altri meccanismi o codice personalizzato, è necessario adattare i controlli.

add_action( 'save_post', 'test_save_post_check', 0, 3 );
function test_save_post_check( $post_ID, $post, $update ) {
    // altri test + questo
    // controlla la presenza di 'post-new' nel '_wp_http_referer'
    if( strpos( wp_get_raw_referer(), 'post-new' ) > 0 ) {
        // nuovo
    } else {
        // aggiornamento
    }
}
3 mag 2020 18:14:40
0

Ecco un codice funzionale che ho testato e utilizzato nel mio sito web, che risolve i seguenti due problemi associati all'azione save_post:

  1. Problema nel distinguere tra aggiornamento o inserimento

  2. Problema del doppio inserimento causato dall'azione save_post

    function save_annonces_callback($post_ID, $post, $update){
    
            $post_type = get_post_type($post_ID);
    
            if ( $post_type === 'annonces' ){
    
                //questo previene il doppio inserimento dall'azione save_post :)
                if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
                    return;
                } else {
    
                    //controlla se è un nuovo post per l'inserimento
                    if( strpos( wp_get_raw_referer(), 'post-new' ) > 0 ){
    
                        //esegui inserimento
    
                    }else{
    
                        //esegui aggiornamento
                    }
    
                }
    
            }
        }add_action('save_post','save_annonces_callback', 10, 3);
    
14 lug 2021 19:34:25
1

Puoi utilizzare l'hook pre_post_update per il codice di aggiornamento e save_post per il codice del nuovo articolo. Funziona prima che un articolo venga aggiornato.

6 ago 2012 15:08:44
Commenti

L'hook save_post viene attivato sia quando un articolo viene creato che quando viene aggiornato (dopo che WordPress lo ha salvato nel database). pre_post_update viene attivato quando un articolo viene aggiornato, ma prima che l'articolo venga effettivamente aggiornato - questo può essere importante.

Stephen Harris Stephen Harris
12 ago 2012 21:59:39
0

Come ha suggerito Darshan Thanki (e Stephen Harris ha ulteriormente approfondito), puoi utilizzare pre_post_update a tuo vantaggio.

global $___new_post;
$___new_post = true;

add_action(
  'pre_post_update',
  function() {
    global $___new_post;
    $___new_post = false;
  },
  0
);

function is_new_post() {
  global $___new_post;
  return $___new_post;
}

Il motivo per cui ho utilizzato le variabili globali è perché function is_new_post() use ( &$new_post ) non è valido in PHP (sorprendente...) quindi includere quella variabile nello scope della funzione non funziona -- da qui la soluzione con global.

Nota che questo approccio può essere utilizzato in modo affidabile solo all'interno/dopo l'evento save_post (il che è solitamente sufficiente, almeno per quello che stiamo facendo con esso).

6 gen 2015 22:49:27
3

Quando save_post viene attivato, tutte le informazioni su quel post sono già disponibili, quindi in teoria potresti usare

function f4553265_check_post() {

    if (!get_posts($post_id)) {
    // se questo è un nuovo post, get_posts($post_id) dovrebbe restituire null
    } else {
    // $post_id esiste già nel database
    }
}
add_action('save_post','f4553265_check_post');

però non è testato. =)

12 apr 2012 07:27:21
Commenti

Quando arrivi a save_post il post stesso sarebbe già stato salvato nel database - quindi get_posts restituirebbe il post corrente.

Stephen Harris Stephen Harris
12 apr 2012 21:25:41

Vero, ho appena verificato nel Codex. Grazie per la segnalazione.

moraleida moraleida
12 apr 2012 21:59:38

Questo non funziona con get_posts ma funziona con get_post.

Gavin Gavin
18 ago 2020 05:28:49
1

Un altro approccio che utilizza una funzione integrata senza aggiungere dati al database sarebbe usare get_post_status().

$post_status = get_post_status();
if ( $post_status != 'draft' ) {
    //bozza
} else { 
    //non è una bozza: può essere pubblicato, in attesa, ecc. 
}

Tuttavia, nota che potrebbe non essere appropriato se hai intenzione di reimpostare successivamente lo stato su "bozza" – le tue istruzioni verrebbero ripetute la prossima volta che aggiornerai il post. A seconda del contesto, potresti voler considerare le varie stringhe che possono essere restituite da get_post_status() per costruire uno scenario più adatto.

Vedi il Codex per get_post_status() e Stato del Post

I valori possibili sono:

  • 'publish' - Un post o pagina pubblicato
  • 'pending' - post in attesa di revisione
  • 'draft' - un post in stato di bozza
  • 'auto-draft' - un post appena creato, senza contenuto
  • 'future' - un post programmato per pubblicazione futura
  • 'private' - non visibile agli utenti non loggati
  • 'inherit' - una revisione. vedi get_children.
  • 'trash' - post nel cestino. aggiunto dalla Versione 2.9.
12 dic 2014 04:15:22
Commenti

Non credo che questo faccia ciò che è stato richiesto. Se creo un nuovo articolo e poi premo 'Pubblica', save_post() viene eseguito per la prima volta, ma durante quella esecuzione get_post_status() restituisce già 'publish' e non 'draft', anche se è solo in fase di pubblicazione.

cgogolin cgogolin
25 nov 2017 20:39:01
0

Dato che il parametro $update è inutile, questo è il metodo più veloce che ho testato:

function wpse48678_check_is_post_new($post_id, $post, $update)
{
    if (false !== strpos($_POST['_wp_http_referer'], 'post-new.php')) {
        return true; // Oppure fai qualcos'altro.
    } else {
        return false; // Oppure fai qualcos'altro.
    }
}
add_action('save_post_{$post_type}', 'wpse48678_check_is_post_new', 10, 3);
9 set 2020 23:26:12
0

Ho passato ore su questo

Sto attualmente sviluppando un plugin e volevo inviare una notifica a tutti gli autori quando una pagina veniva "Creata" sul sito della mia Web Design Company.

Inizialmente ho provato a usare il seguente codice:

add_action('save_post_page', function($post_id, $post, $update) {
    if(!$update){
        echo("È un nuovo post!");
    }else{
        echo("È un vecchio post!");
    }
}

Continuava a mostrare "È un vecchio post!". Ma perché??? Dopo alcune ricerche ho scoperto che dopo aver cliccato il pulsante "Aggiungi nuova pagina" WordPress crea immediatamente una bozza automatica che imposta la variabile $update a true. Molto utile.

Dopo ore di ricerca ho finalmente trovato la seguente soluzione che funziona:

// Si attiva quando un post cambia "stato" ad esempio da bozza a in sospeso, da pubblicato a programmato.
add_action('transition_post_status', function($new_status, $old_status, $post) {
    // Controlla se il post passa da bozza automatica a qualsiasi altro stato (bozza, in sospeso, pubblicato, ecc.)
    if ('auto-draft' === $old_status && $new_status !== 'auto-draft'){
        echo("È un nuovo post!");
    }else{
        echo("È un vecchio post!");
    }
}

Nota: In WordPress, "bozza" (draft) e "bozza automatica" (auto-draft) sono diversi. Uno stato "bozza" è un post che un utente imposta manualmente come bozza, indicando che è un lavoro in corso. Una "bozza automatica", invece, viene assegnata automaticamente a un post quando viene creato ma non ancora pubblicato. Praticamente un modo diverso per dire salvataggio automatico.

Spero che questo aiuti alcune persone... Ora vado a passare altre 4 ore su un altro problema haha.

12 dic 2024 22:45:17
0

Questo dovrebbe funzionare ragazzi

add_action( 'wp_after_insert_post', 'clearCDNCache', 10, 4);       
 
public function clearCDNCache($post_id, $post, $update, $post_before){
        
        if ( ! empty($_POST['_wpnonce']) ) {
            // Esegui la funzione personalizzata solo una volta
        }
    
        // Aggiungi nuova modalità
        if (!empty($_POST['_wp_http_referer']) && $_POST['_wp_http_referer'] == '/wp-admin/post-new.php') { 

        } else {
            // Modalità aggiornamento
        }
       
    }
27 feb 2025 11:12:21