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.