Verifică actualizarea vs postare nouă în acțiunea save_post

11 apr. 2012, 22:43:16
Vizualizări: 42K
Voturi: 25

Este posibil ca în cadrul acțiunii save_post să determini dacă este vorba despre o postare nouă în curs de creare sau despre o postare existentă care este actualizată?

1
Comentarii

Nu cred că acest lucru este posibil. Vezi comentariul meu de mai jos la răspunsul lui @moraleida. De ce ai nevoie să știi dacă este o postare nouă sau este actualizată? Poate exista o soluție alternativă sau o abordare diferită.

Stephen Harris Stephen Harris
12 apr. 2012 21:28:38
Toate răspunsurile la întrebare 13
7
20

Începând cu versiunea 3.7 a WordPress - dacă îmi amintesc corect - hook-ul save_post - mai multe informații despre acest hook și utilizarea lui la Code Reference: save_post și Codex: save_post - are un al treilea parametru $update care poate fi folosit pentru a determina exact acest lucru.

@param     int               $post_ID     ID-ul postului.
@param     WP_Post     $post          Obiectul post.
@param     bool            $update     Indică dacă acesta este un post existent care este actualizat sau nu.


Notă:

$update nu este întotdeauna true – puteți vedea și testa acest lucru singur cu codul de mai jos. Totuși, acest lucru nu este bine documentat, poate denumit departe de a fi optim și, prin urmare, creează așteptări înșelătoare. Codul de mai jos poate fi folosit pentru depanare, experimentați cu momentul în care să interceptați execuția codului, altfel nu veți vedea informațiile/mesajele. Cred că problema în comportamentul înșelător este gestionarea reviziilor și salvărilor automate – care ar putea fi dezactivate, dar nu recomand acest lucru și nu l-am testat. Nu sunt sigur dacă acest lucru merită un Trac Ticket, așa că nu am deschis unul, dacă credeți că da, vă rugăm să accesați linkul și să faceți-o voi înșivă. În afară de asta, așa cum se menționează în comentarii, dacă aveți o problemă specifică, postați o nouă întrebare.

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

  //condiții
  if( ! $update && $post->post_status == "auto-draft" ) {
    // se aplică la un post nou
    echo ' && $post->post_status == "auto-draft"';
    //die();
  } else if ( ! $update ) {
    // se aplică în principiu la revizia (salvată automat) 
    //die();
  } else {
    // se aplică la actualizarea unui post publicat
    // când există o revizie, ceea ce este în mod normal cazul, 
    // comportamentul standard al WordPress, atunci este considerată 
    // o actualizare, ceea ce este punctul în care apare confuzia
    // există alte metode, cum ar fi verificarea timpului sau a stării postului
    // în funcție de cazul dumneavoastră specific, ar putea fi mai potrivit 
    // să folosiți una dintre acele alternative 
    //die();
  }

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

Parametrul $update este ÎNTOTDEAUNA adevărat chiar și atunci când este un post nou. Deci acest parametru este inutil. Nu sunt sigur dacă a funcționat vreodată, dar cu siguranță nu funcționează așa cum este documentat în cea mai recentă versiune de WordPress 4.8.

Solomon Closson Solomon Closson
20 iul. 2017 23:32:34

@SolomonClosson Dacă te uiți la wp_publish_post, atunci da. Dar acest lucru nu este valabil pentru utilizarea sa în wp_insert_post. Am scris o funcție de depanare, o adaug în răspuns.

Nicolai Grossherr Nicolai Grossherr
21 iul. 2017 03:11:55

@SolomonClosson Dacă ai o problemă concretă actuală, te rog să pui o nouă întrebare. Aruncă o privire la reviziile pentru funcția de depanare pentru o explicație.

Nicolai Grossherr Nicolai Grossherr
21 iul. 2017 03:34:11

Hook-ul save_post are un al treilea parametru care este întotdeauna setat la TRUE, deci nu sunt sigur ce legătură are cu alte hook-uri, fără să vorbim despre alte hook-uri. Mă refer la hook-ul din răspunsul tău. Acest lucru este incorect.

Solomon Closson Solomon Closson
24 iul. 2017 02:42:42

@SolomonClosson După cum am spus, hook-ul apare de două ori: wp_insert_post(), wp_publish_post(). Ultimul este doar pentru postări programate, acolo $update este întotdeauna setat la true. În ceea ce privește wp_insert_post(), $update nu este întotdeauna true.

Nicolai Grossherr Nicolai Grossherr
24 iul. 2017 16:08:09

Am întârziat la petrecere, dar hei, de ce nu, @Nicolai, ceea ce spui este ceea ce s-ar aștepta să se întâmple, dar nu pot obține ca $update să fie false chiar și atunci când mă conectez la 'wp_insert_post'. Indiferent unde mă conectez, este întotdeauna true. Nu înțeleg de ce nu este rezolvat acest lucru.

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

Băieți, doar o informație. Hook-ul este declanșat la restaurarea și ștergerea unui articol.

melvin melvin
9 mai 2019 14:39:48
Arată celelalte 2 comentarii
6
13

Modul în care efectuez această verificare (în cadrul unei funcții hook) este să compar data postării cu data modificării (în GMT pentru standardizare)

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 ){
        // Postare nouă
    }else{
        // Postare actualizată
    }
}
add_action('save_post', 'check_new_vs_update' );

Această metodă funcționează deoarece chiar și la creare, postarea are o dată 'modificată' atașată, care este exact aceeași cu data 'creării', dar permitem o variație de 1 secundă în cazul în care o secundă trece în timpul creării postării.

10 feb. 2015 15:51:45
Comentarii

Uneori post_date_gmt este 2019-03-12 01:31:30 iar post_modified_gmt este 2019-03-12 01:31:31. :(

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

@HeYifei何一非 bun punct, dacă procesarea începe la sfârșitul unei anumite secunde, acest lucru s-ar putea întâmpla. Am actualizat răspunsul meu, mulțumesc

Cush Cush
12 mar. 2019 15:04:13

Băieți, doar o informație. Hook-ul este declanșat la restaurarea și ștergerea unui post.

melvin melvin
9 mai 2019 14:39:53

Bine de știut @melvin, mulțumesc

Cush Cush
17 aug. 2020 20:43:30

Nu pot să cred că trebuie să fie atât de complicat. WordPress nu încetează să mă uimească.

amarinediary amarinediary
4 ian. 2021 15:29:19

Ca să fim corecți, ei au literalmente milioane de utilizatori și este un proiect open-source. Din păcate, nu pot include fiecare funcționalitate și aceasta probabil nu este una dintre cele mai utilizate. În ultimii ani, lucruri precum îmbunătățirea editorului și securitatea au fost prioritizate și asta e bine! Adică, până și jQuery abia acum este actualizat! Până la versiunea actuală, rulează încă 1.x!

Cush Cush
21 ian. 2021 15:26:35
Arată celelalte 1 comentarii
4

Am ales să verific pur și simplu existența unei valori personalizate înainte de a o seta. În acest fel, dacă este un post nou creat, valoarea personalizată nu ar exista încă.

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 != '') {
    // este o înregistrare nouă
    $termid = 'update';
  } else {
    // este o înregistrare existentă
  }
  update_post_meta($post_id, '_termid', $termid);
}
add_action('save_post', 'attributes_save_postdata');
18 apr. 2012 00:50:50
Comentarii

Pentru ca aceasta să funcționeze, trebuie mai întâi să creezi câmpul personalizat folosind add_post_meta?

MF1 MF1
9 apr. 2013 05:03:17

Conform Codex: [update_post_meta] poate fi folosit în locul funcției add_post_meta(). http://codex.wordpress.org/Function_Reference/update_post_meta

hereswhatidid hereswhatidid
20 ian. 2014 23:46:08

Aceasta ar putea eșua dacă postările au fost create înainte ca codul să fie activat prin intermediul unei activări de plugin. Postările mai vechi nu au meta setat, deci prima actualizare pentru ele va fi considerată ca una nouă.

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

@VasuChawla deci în acest caz poate este mai sigur să verifici existența isset() (de exemplu) a acelui termen meta specific în loc să verifici dacă este adevărat sau fals. Ca o a treia condiție. (if, elseif, ...else)

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

Exemplu de răspuns pentru ialocin cu parametrul "update":

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

   if($update == false) {
     // faci ceva dacă este prima publicare
   } else {
     // Faci ceva dacă este o actualizare
   }
}

add_action( 'save_post', 'save_func', 10, 3 );
1 dec. 2015 19:53:53
Comentarii

O modalitate mai bună de a structura acest lucru ar fi fie să plasați blocul de actualizare primul, permițând să faceți doar if($update), fie să păstrați blocul nou primul, dar folosind if( ! $update ). Ultima variantă va încuraja practici mai bune și este preferată în locul metodei dumneavoastră conform standardelor de codare WordPress în cazuri precum operatorul ternar

Cush Cush
17 nov. 2016 13:38:30
0

Am întâlnit recent hook-ul save_post legat de crearea și actualizarea postărilor. După ce am citit codul sursă pentru a înțelege fluxul, am descoperit că următoarea metodă ar putea fi utilă. Deoarece nu a fost menționată anterior, o împărtășesc în caz că ar fi de folos cuiva. (Testat pe versiunea WordPress 5.3.3)

Fluxul de creare a unei postări este aproximativ:

  1. După apăsarea butonului "Adaugă nou" (Postare)
  2. Se apelează $post = get_default_post_to_edit( $post_type, true ); unde
  3. get_default_post_to_edit() primește argumentul $create_in_db = true
  4. astfel wp_insert_post() este apelat imediat, se creează o postare auto-draft, chiar dacă nu este salvată. De fiecare dată când se apasă Adaugă nou, se creează un auto-draft
  5. $update este întotdeauna true pentru publicare. Deci, când se publică o postare nouă, valoarea este true.

Comparând obiectul $_POST pentru o postare nouă și una actualizată sau republicată, diferența evidentă este valoarea _wp_http_referer. Pentru postările noi, valoarea este /wp-admin/post-new.php.

Presupunere: se presupune că postarea este publicată/adaugată din interfața de utilizator. Dacă acest lucru se face prin alte mecanisme sau cod personalizat, verificarea trebuie ajustată corespunzător.

add_action( 'save_post', 'test_save_post_check', 0, 3 );
function test_save_post_check( $post_ID, $post, $update ) {
    // alte verificări + aceasta
    // verificarea prezenței 'post-new' în '_wp_http_referer'
    if( strpos( wp_get_raw_referer(), 'post-new' ) > 0 ) {
        // postare nouă
    } else {
        // actualizare
    }
}
3 mai 2020 18:14:40
0

aici este un cod funcțional pe care l-am testat și l-am folosit pe site-ul meu, care rezolvă următoarele două probleme asociate cu acțiunea save_post:

  1. problema de a verifica între actualizare sau inserare

  2. problema inserării de două ori prin acțiunea save_post

    function save_annonces_callback($post_ID, $post, $update){
    
            $post_type = get_post_type($post_ID);
    
            if ( $post_type === 'annonces' ){
    
                //acest lucru previne inserarea de două ori prin acțiunea save_post :)
                if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
                    return;
                } else {
    
                    //verifică dacă este un post nou, deci inserează
                    if( strpos( wp_get_raw_referer(), 'post-new' ) > 0 ){
    
                        //efectuează inserarea
    
                    }else{
    
                        //efectuează actualizarea
                    }
    
                }
    
            }
        }add_action('save_post','save_annonces_callback', 10, 3);
    
14 iul. 2021 19:34:25
1

Puteți utiliza acțiunea (hook) `pre_post_update` pentru codul de actualizare și `save_post` pentru codul de postare nouă. Acesta funcționează înainte ca un articol să fie actualizat.

6 aug. 2012 15:08:44
Comentarii

Hook-ul save_post este declanșat atât când un articol este creat, cât și când este actualizat (după ce WordPress l-a salvat în baza de date). Hook-ul pre_post_update este declanșat când un articol este actualizat, dar înainte ca articolul să fie actualizat - acest lucru poate fi important.

Stephen Harris Stephen Harris
12 aug. 2012 21:59:39
0

După cum a sugerat Darshan Thanki (și Stephen Harris a dezvoltat în continuare), puteți utiliza pre_post_update în avantajul vostru.

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

Motivul pentru care am folosit variabile globale este pentru că function is_new_post() use ( &$new_post ) nu este valid în PHP (șocant...) așa că includerea acelei variabile în scope-ul funcției nu funcționează -- de aceea am folosit global.

Rețineți că această soluție poate fi folosită în mod fiabil doar în cadrul sau după evenimentul save_post (ceea ce este de obicei suficient, cel puțin pentru ceea ce facem noi cu ea).

6 ian. 2015 22:49:27
3

Când acțiunea save_post este declanșată, toate informațiile despre acel articol sunt deja disponibile, așa că teoretic ai putea folosi

function f4553265_check_post() {

    if (!get_posts($post_id)) {
    // dacă acesta este un articol nou, get_posts($post_id) ar trebui să returneze null
    } else {
    // $post_id există deja în baza de date
    }
}
add_action('save_post','f4553265_check_post');

această soluție nu a fost testată, totuși. =)

12 apr. 2012 07:27:21
Comentarii

Până când ajungi la save_post, postarea în sine ar fi deja salvată în baza de date - deci get_posts ar returna postarea curentă.

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

Adevărat, tocmai am verificat în Codex. Mulțumesc pentru informație.

moraleida moraleida
12 apr. 2012 21:59:38

Aceasta nu funcționează cu get_posts dar funcționează cu get_post.

Gavin Gavin
18 aug. 2020 05:28:49
1

O altă abordare care folosește o funcție încorporată și nu necesită adăugări în baza de date ar implica get_post_status().

$post_status = get_post_status();
if ( $post_status != 'draft' ) {
    //schiță
} else { 
    //nu este o schiță: poate fi publicat, în așteptare, etc.
}

Totuși, rețineți că poate să nu fie potrivit dacă intenționați să setați ulterior starea înapoi la "draft" - instrucțiunile dvs. vor fi repetate data viitoare când veți actualiza postarea. În funcție de context, s-ar putea să doriți să luați în considerare diferitele șiruri returnate de get_post_status() pentru a construi un scenariu mai potrivit.

Consultați Codex pentru get_post_status() și Starea Postării

Valorile posibile sunt:

  • 'publish' - O postare sau pagină publicată
  • 'pending' - postarea așteaptă moderare
  • 'draft' - o postare în stadiu de schiță
  • 'auto-draft' - o postare nou creată, fără conținut
  • 'future' - o postare programată pentru publicare în viitor
  • 'private' - nu este vizibilă pentru utilizatorii nelogati
  • 'inherit' - o revizie. vezi get_children.
  • 'trash' - postarea este în coșul de gunoi. adăugat începând cu Versiunea 2.9.
12 dec. 2014 04:15:22
Comentarii

Nu cred că această funcționalitate face ceea ce s-a cerut. Dacă creez un articol nou și apoi apăs 'Publică', funcția save_post() este executată pentru prima dată, dar în timpul acelei execuții get_post_status() returnează deja 'publish' și nu 'draft', chiar dacă articolul este încă în procesul de publicare.

cgogolin cgogolin
25 nov. 2017 20:39:01
0

Deoarece parametrul $update este inutil, acesta este cel mai rapid mod pe care l-am testat:

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

Am petrecut ore întregi pe asta

În prezent sunt în procesul de dezvoltare a unui plugin și am vrut să trimit o notificare tuturor autorilor atunci când o pagină era "Creată" pe site-ul companiei mele de Web Design.

Inițial am încercat să folosesc următoarele:

add_action('save_post_page', function($post_id, $post, $update) {
    if(!$update){
        echo("Este un post nou!");
    }else{
        echo("Este un post vechi!");
    }
}

Continuam să afișeze "Este un post vechi!". Dar de ce??? După ce am cercetat, am aflat că după ce apeși butonul "Adaugă Pagină Nouă", WordPress creează instantaneu un auto-draft care setează variabila $update la true. Cât de util.

După ore de cercetare, am găsit în sfârșit următoarea soluție care funcționează:

// Se declanșează când un post își schimbă "statusul", de ex. din pending în draft, publicat în programat.
add_action('transition_post_status', function($new_status, $old_status, $post) {
    // Verifică dacă postul trece de la auto-draft la orice alt status (draft, pending, publish, etc.)
    if 'auto-draft' === $old_status && $new_status !== 'auto-draft'){
        echo("Este un post nou!");
    }else{
        echo("Este un post vechi!");
    }
}

Notă: În WordPress, "draft" și "auto-draft" sunt diferite. Un status "draft" este un post pe care utilizatorul îl setează manual ca draft, indicând faptul că este în lucru. Pe de altă parte, "auto-draft" este atribuit automat unui post atunci când este creat dar încă nepublicat. Practic, un alt mod de a spune auto-salvare.

Sper că acest lucru va ajuta câteva persoane... E timpul să mai petrec încă 4 ore pe o altă problemă haha.

12 dec. 2024 22:45:17
0

Ar trebui să funcționeze, băieți

add_action( 'wp_after_insert_post', 'clearCDNCache', 10, 4);       
 
public function clearCDNCache($post_id, $post, $update, $post_before){
        
        if ( ! empty($_POST['_wpnonce']) ) {
            // Execută funcția personalizată doar o dată
        }
    
        // Adaugă un nou mod
        if (!empty($_POST['_wp_http_referer']) && $_POST['_wp_http_referer'] == '/wp-admin/post-new.php') { 

        } else {
            // Modul de actualizare
        }
       
    }
27 feb. 2025 11:12:21