Verifica aggiornamenti vs nuovo post sull'azione save_post


21

È possibile nell'ambito dell'azione save_post determinare se si tratta di un nuovo post in fase di creazione o di un post esistente in fase di aggiornamento?


Non penso sia possibile. Vedi il mio commento sotto la risposta di @ moraleida. Perché devi sapere se si tratta di un nuovo post o di un aggiornamento? Potrebbe esserci un approccio alternativo o alternativo.
Stephen Harris,

Risposte:


16

Dalla versione 3.7 di WordPress. - IIRC - l' save_posthook - ulteriori informazioni sull'hook e sul suo utilizzo in Codice di riferimento:save_post e Codice:save_post - ha un terzo parametro $updateche può essere utilizzato per determinare proprio questo.

@param int $ post_ID ID post.
@param WP_Post $ post Oggetto post.
@param bool $ update Se questo è un post esistente in fase di aggiornamento o meno.


Nota:

$updatenon è sempre true- puoi vederlo e testarlo tu stesso con il codice seguente. Tuttavia, non è ben documentato, probabilmente lontano dal nome ottimale, e quindi crea aspettative fuorvianti. Sotto il codice può essere usato per alcuni debug, gioca con quando intercettare l'esecuzione del codice, perché altrimenti non vedrai le informazioni / i 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 che ciò meriti un Biglietto Trac , quindi non ne ho aperto uno, se lo pensi, segui il link e fallo da solo. A parte questo, come indicato nei commenti, se hai un problema specifico, pubblica 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';

  //conditions
  if( ! $update && $post->post_status == "auto-draft" ) {
    // applies to new post
    echo ' && $post->post_status == "auto-draft"';
    //die();
  } else if ( ! $update ) {
    // applies basically to the (auto saved) revision 
    //die();
  } else {
    // applies to updating a published post
    // when there is a revision, which is normally the case, 
    // standard behavior of WordPress, then it is considered 
    // an update, which is where the confusion sets in
    // there are other methods, like checking time or post status
    // depending on your use case it might be more appropriate 
    // to use one of those alternatives 
    //die();
  }

  echo '</pre>';
  //die();
}

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

@SolomonClosson Se dai un'occhiata wp_publish_post, allora sì. Ma questo non è vero per il suo utilizzo in wp_insert_post. Ho scritto una funzione di debug, la aggiungo alla risposta.
Nicolai,

@SolomonClosson Se hai un problema concreto, fai una nuova domanda. Dai una spiegazione alle revisioni della funzione di debug.
Nicolai,

L' save_posthook ha un terzo parametro che è sempre impostato su TRUE, quindi non sono sicuro di cosa abbia a che fare con altri hook, non parlando di altri hook. Sto parlando del gancio nella tua risposta. Questo non è corretto
Solomon Closson,

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

11

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

function check_new_vs_update( $post_id ){
    $myPost        = get_post($post_id);
    $post_created  = new DateTime( $myPost->post_date_gmt );
    $post_modified = new DateTime( $myPost->post_modified_gmt );

    if( abs( $post_created->diff( $post_modified )->s ) <= 1 ){
        // New post
    }else{
        // Updated post
    }
}
add_action('save_post', 'check_new_vs_update' );

Questo funziona perché anche al momento della creazione al post è associata una data "modificata", che è esattamente la stessa della data "creata", ma consentiamo una variazione di 1 secondo in entrambi i casi nel caso in cui un secondo ticchetti durante la creazione di il post.


1
Qualche volta post_date_gmtè 2019-03-12 01:31:30e post_modified_gmtè 2019-03-12 01:31:31. :(
He Yifei

1
@HeYifei 何 一 非 buon punto, se l'elaborazione inizia alla fine di un dato secondo, questo potrebbe accadere. Ho aggiornato la mia risposta, grazie
James Cushing del

Ragazzi, solo un'informazione. L'hook viene attivato per ripristinare ed eliminare un post.
Melvin

6

Ho finito per verificare 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 != '') {
    // it's a new record
    $termid = 'update';
  } else {
    // it's an existing record
  }
  update_post_meta($post_id, '_termid', $termid);
}
add_action('save_post', 'attributes_save_postdata');

Perché questo funzioni, devi prima creare il campo personalizzato usando add_post_meta?
MF1

Secondo il Codice: [update_post_meta] può essere usato al posto della funzione add_post_meta (). codex.wordpress.org/Function_Reference/update_post_meta
hereswhatidid

Ciò potrebbe non riuscire se i post sono stati creati prima che l'hook del codice venga abilitato tramite l'attivazione di un plug-in. I post più vecchi non hanno il meta set, quindi il primo aggiornamento per loro sarà considerato come nuovo.
Vasu Chawla,

4

Esempio di risposta ialocin con paremetro "aggiornamento":

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

   if($update == false) {
     // do something if its first time publish
   } else {
     // Do something if its update
   }
}

add_action( 'save_post', 'save_func', 10, 3 );

2
Un modo migliore per strutturare questo sarebbe quello di mettere prima il blocco di aggiornamento, consentendo di fare semplicemente if($update)o mantenere il nuovo blocco per primo ma usando if( ! $update ). Quest'ultimo porterà OP in una migliore pratica ed è preferito al tuo metodo dagli standard di codifica di WordPress in casi come l' operatore ternario
James Cushing,

1

È possibile utilizzare l'hook di azioni pre_post_update per il codice di aggiornamento e save_post per il nuovo codice postale. Funziona prima che un post venga aggiornato.


4
save_postl'hook viene attivato sia quando un post viene creato e aggiornato (dopo che WordPress lo ha salvato nel database). pre_post_updateviene attivato quando un post viene aggiornato, ma prima che il post venga aggiornato, questo può essere importante.
Stephen Harris,

1

Come ha suggerito Darshan Thanki (e Stephen Harris ha ulteriormente elaborato), puoi sfruttarlo pre_post_updatea 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 usato i globali è perché function is_new_post() use ( &$new_post )non è valido in PHP (scioccante ...), quindi il pull in quella variabile nell'ambito della funzione non funziona - da qui il globale.

Si noti che questo può davvero essere utilizzato in modo affidabile solo all'interno / dopo l' save_postevento (che di solito è sufficiente, almeno per quello che stiamo facendo con esso).


0

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

function f4553265_check_post() {

    if (!get_posts($post_id)) {
    // if this is a new post get_posts($post_id) should return null
    } else {
    // $post_id already exists on the database
    }
}
add_action('save_post','f4553265_check_post');

questo non è testato, però. =)


3
Quando arrivi al save_postpost stesso sarebbe già stato salvato nel database, quindi get_postsrestituirebbe il post corrente.
Stephen Harris,

È vero, l'ho appena verificato nel Codice. Grazie per il testa a testa.
moraleida,

0

Un altro approccio che utilizza una funzione integrata e nessuna aggiunta al database comporterebbe get_post_status().

$post_status = get_post_status();
if ( $post_status != 'draft' ) {
    //draft
} else { 
    //not a draft: can be published, pending, etc. 
}

Tieni presente, tuttavia, che potrebbe non essere appropriato se prevedi di reimpostare lo stato su "bozza": le istruzioni verranno ripetute al successivo aggiornamento del post. A seconda del contesto, è possibile prendere in considerazione le varie stringhe che possono essere restituite get_post_status()per creare uno scenario più appropriato.

Vedi Codex per get_post_status () e Post Status

I valori possibili sono:

  • "pubblica": un post o una pagina pubblicati
  • 'in sospeso': il post è in attesa di revisione
  • "bozza": un post nello stato bozza
  • "bozza automatica": un post appena creato, senza contenuto
  • 'futuro' - un post da pubblicare in futuro
  • "privato": non visibile agli utenti che non hanno effettuato l'accesso
  • 'eredita' - una revisione. vedi get_children.
  • 'cestino': la posta è nel cestino. aggiunto con la versione 2.9.

Non penso che questo faccia quello che è stato chiesto. Se creo un nuovo post e poi premo "Pubblica", save_post()viene eseguito per la prima volta, ma durante tale esecuzione get_post_status()restituisce già "pubblica" e non "bozza", anche se è solo in fase di pubblicazione.
cgogolin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.