Überprüfe, ob ein Update oder ein neuer Beitrag in der Aktion save_post vorhanden ist

21

Kann innerhalb der Aktion save_post festgestellt werden, ob ein neuer Beitrag erstellt oder ein vorhandener Beitrag aktualisiert wird?

Hereswhatidid
quelle
Ich denke nicht, dass das möglich ist. Siehe meinen Kommentar unten @ moraleida Antwort. Warum musst du wissen, ob es sich um einen neuen Beitrag handelt oder ob er aktualisiert wird? Möglicherweise gibt es eine Problemumgehung oder einen alternativen Ansatz.
Stephen Harris

Antworten:

16

Seit WordPress Version 3.7. - IIRC - the save_posthook - Weitere Informationen zum Hook und seiner Verwendung unter Code Reference:save_post und Codex:save_post - Mit einem dritten Parameter $updatekann genau das bestimmt werden.

@param int $ post_ID Beitrags-ID.
@param WP_Post $ post Objekt posten.
@param bool $ update Gibt an, ob ein vorhandener Beitrag aktualisiert wird oder nicht.


Hinweis:

$updateist nicht immer true- Sie können es selbst mit dem folgenden Code sehen und testen. Es ist jedoch nicht gut dokumentiert, möglicherweise alles andere als optimal benannt, und führt daher zu irreführenden Erwartungen. Der folgende Code kann für einige Debugging-Vorgänge verwendet werden. Spielen Sie damit, wann die Codeausführung abgefangen werden soll, da sonst die Informationen / Meldungen nicht angezeigt werden. Ich denke, der Schuldige an betrügerischem Verhalten ist der Umgang mit Revisionen und automatischen Speichern - die deaktiviert werden könnten, aber ich empfehle es nicht und habe es nicht getestet. Ich bin mir nicht sicher, ob dies ein Trac-Ticket rechtfertigt. Daher habe ich kein Ticket geöffnet. Wenn Sie dies glauben, folgen Sie bitte dem Link und machen Sie es selbst. Außerdem sollten Sie, wie in den Kommentaren angegeben, eine neue Frage stellen, wenn Sie ein bestimmtes Problem haben.

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();
}
Nicolai
quelle
3
Der $updateParameter ist IMMER wahr, auch wenn es sich um einen neuen Beitrag handelt. Dieser Parameter ist also unbrauchbar. Ich bin mir nicht sicher, ob es jemals funktioniert hat, aber es funktioniert verdammt noch mal nicht so, wie es in der neuesten Version von WordPress 4.8 dokumentiert ist.
Solomon Closson
@SolomonClosson Wenn du dir das anschaust wp_publish_post, dann ja. Dies gilt jedoch nicht für die Verwendung in wp_insert_post. Ich habe eine Debug-Funktion geschrieben, die ich der Antwort hinzufüge.
Nicolai
@SolomonClosson Wenn Sie ein aktuelles konkretes Problem haben, stellen Sie bitte eine neue Frage. Schauen Sie sich die Revisionen für die Debug-Funktion an und erklären Sie diese.
Nicolai
Der save_postHook hat einen 3. Parameter, der immer auf TRUE gesetzt ist. Sie können sich also nicht sicher sein, was dies mit anderen Hooks zu tun hat, und sprechen nicht über andere Hooks. Ich spreche über den Haken in deiner Antwort. Das ist falsch.
Solomon Closson
@SolomonClosson Wie gesagt der Haken kommt zweimal vor: wp_insert_post(), wp_publish_post(). Letzteres sind nur zukünftige Posts, da $updatesoll es immer sein true. Ansonsten in Bezug auf wp_insert_post(), $updateist nicht immer true.
Nicolai
11

Die Art und Weise, wie ich diese Prüfung durchführe (innerhalb einer Hook-Funktion), ist das Vergleichen des Post-Datums und des Änderungsdatums (in GMT zur Standardisierung).

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' );

Dies funktioniert, da dem Beitrag bereits bei der Erstellung ein Änderungsdatum zugeordnet ist, das genau dem Erstellungsdatum entspricht. Wir lassen jedoch eine Abweichung von 1 Sekunde zu, falls eine Sekunde während der Erstellung von überschreitet die Post.

James Cushing
quelle
1
Manchmal post_date_gmtist das 2019-03-12 01:31:30und das post_modified_gmtist 2019-03-12 01:31:31. :(
He Yifei 何 何 非
1
@HeYifei 何 一 非 guter Punkt, wenn die Verarbeitung nach einer bestimmten Sekunde beginnt, kann dies passieren. Ich habe meine Antwort aktualisiert, danke
James Cushing
Leute, nur eine Info. Der Haken wird beim Wiederherstellen und Löschen eines Beitrags ausgelöst.
Melvin
6

Am Ende habe ich nur überprüft, ob ein benutzerdefinierter Wert vorhanden ist, bevor ich ihn einstelle. Auf diese Weise ist der benutzerdefinierte Wert noch nicht vorhanden, wenn es sich um einen neu erstellten Beitrag handelt.

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');
Hereswhatidid
quelle
Müssen Sie zuerst das benutzerdefinierte Feld mit add_post_meta erstellen, damit dies funktioniert?
MF1
Gemäß Codex: [update_post_meta] kann anstelle der Funktion add_post_meta () verwendet werden. codex.wordpress.org/Function_Reference/update_post_meta
hiereswhatidid
Dies kann fehlschlagen, wenn Posts erstellt wurden, bevor der Code-Hook über eine Plugin-Aktivierung aktiviert wurde. Ältere Posts haben kein Meta-Set, daher wird das erste Update für sie als neu betrachtet.
Vasu Chawla
4

Beispiel für die Antwort von ialocin mit dem Parameter "update":

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 );
Goran Jakovljevic
quelle
2
Eine bessere Möglichkeit, dies zu strukturieren, besteht darin, entweder den Aktualisierungsblock an die erste Stelle zu setzen, dies zuzulassen, if($update)oder den neuen Block an erster Stelle zu behalten, aber zu verwenden if( ! $update ). Letzteres wird OP zu einer besseren Übung machen und wird von WordPress-Codierungsstandards in Fällen wie dem ternären Operator
James Cushing,
1

Sie können den Aktions-Hook pre_post_update für den Aktualisierungscode und save_post für die neue Postleitzahl verwenden. Es funktioniert, bevor ein Beitrag aktualisiert wird.

Darshan Thanki
quelle
4
save_postHaken abgefeuert sowohl , wenn ein Post erstellt und aktualisiert wird (nach Wordpress es in der Datenbank gespeichert ist). pre_post_updatewird ausgelöst, wenn ein Beitrag aktualisiert wird, aber bevor der Beitrag aktualisiert wird - dies kann wichtig sein.
Stephen Harris
1

Wie Darshan Thanki andeutete (und Stephen Harris weiter ausarbeitete), können Sie pre_post_updatezu Ihrem Vorteil nutzen.

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;
}

Der Grund, warum ich Globals verwendet habe, ist weil function is_new_post() use ( &$new_post ) es in PHP nicht gültig ist (schockierend ...), also funktioniert es nicht, diese Variable in den Funktionsumfang zu ziehen - daher das Globale.

Beachten Sie, dass dies wirklich nur innerhalb / nach der save_postVeranstaltung zuverlässig genutzt werden kann (was in der Regel ausreicht, zumindest für das, was wir damit machen).

Qix
quelle
0

Wenn save_post ausgelöst wird, sind bereits alle Informationen zu diesem Beitrag verfügbar, sodass Sie theoretisch verwenden können

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');

Dies ist jedoch ungetestet. =)

moraleida
quelle
3
Zu dem Zeitpunkt, an save_postdem Sie den Beitrag selbst erhalten, wäre er bereits in der Datenbank gespeichert worden - also get_postswürde er den aktuellen Beitrag zurückgeben.
Stephen Harris
Stimmt, ich habe es gerade im Codex überprüft. Danke für das Heads-up.
Moraleida
0

Ein anderer Ansatz, bei dem eine integrierte Funktion verwendet wird und die Datenbank nicht erweitert wird, ist erforderlich get_post_status().

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

Beachten Sie jedoch, dass es möglicherweise nicht angebracht ist, den Status später auf "Entwurf" zurückzusetzen - Ihre Anweisungen werden beim nächsten Aktualisieren des Posts wiederholt. Je nach Kontext möchten Sie möglicherweise die verschiedenen Zeichenfolgen berücksichtigen, die von zurückgegeben werden könnenget_post_status() , um ein geeigneteres Szenario zu erstellen.

Siehe Codex für get_post_status () und Post Status

Mögliche Werte sind:

  • 'veröffentlichen' - Ein veröffentlichter Beitrag oder eine veröffentlichte Seite
  • 'ausstehend' - Überprüfung des Beitrags steht aus
  • 'Entwurf' - ein Beitrag im Entwurfsstatus
  • 'auto-draft' - ein neu erstellter Beitrag ohne Inhalt
  • 'future' - ein Beitrag, der in Zukunft veröffentlicht werden soll
  • 'privat' - nicht sichtbar für Benutzer, die nicht angemeldet sind
  • 'erben' - eine Überarbeitung. siehe get_children
  • 'Mülleimer' - Beitrag ist im Mülleimer. hinzugefügt mit Version 2.9.
John112
quelle
Ich glaube nicht, dass dies das tut, wonach gefragt wurde. Wenn ich einen neuen Beitrag erstelle und dann auf "Veröffentlichen" klicke, save_post()wird dieser zum ersten Mal ausgeführt, aber während dieser Ausführung wird get_post_status()bereits "Veröffentlichen" und nicht "Entwurf" zurückgegeben, obwohl er erst veröffentlicht wird.
cgogolin