save_post în WordPress

Hooks folosite des WordPress 1.5.0

Acțiunea care rulează după ce un articol, o pagină sau alt tip de conținut a fost salvat; o folosești pentru câmpuri personalizate.

Sintaxă
do_action( 'save_post', int $post_id, WP_Post $post, bool $update )
do_action( "save_post_{$post->post_type}", int $post_id, WP_Post $post, bool $update )

Ce face save_post

save_post rulează de fiecare dată când un articol este creat sau actualizat: din editor, editare rapidă, import, wp_insert_post(), wp_update_post(). Primește ID-ul, obiectul WP_Post și $update (true dacă articolul exista deja). Ca să primești toate trei, adaugă funcția cu 10, 3.

Din WordPress 3.7.0 există și varianta pentru un singur tip: save_post_{$post->post_type} (de exemplu save_post_page sau save_post_dex_meniu). Este mai potrivită când lucrezi cu un singur tip, pentru că funcția nu mai rulează degeaba la celelalte. Ea rulează înaintea lui save_post.

Hook-ul rulează și la salvările automate (autosave), la revizii și chiar la „Adaugă nou”, când WordPress creează o ciornă automată (auto-draft). Când salvezi date din formular, verifică nonce-ul și drepturile utilizatorului.

Parametri

Parametru Descriere
$post_id ID-ul articolului salvat.
$post Obiectul WP_Post al articolului.
$update true dacă se actualizează un articol existent, false la creare.

Exemple

Exemplul 1: Salvarea prețului dintr-un meta box

Meta box-ul afișează câmpul dex_pret și un nonce (wp_nonce_field( 'dex_salveaza_pret', 'dex_pret_nonce' )). La salvare, ignorăm autosave-ul, verificăm nonce-ul și dreptul edit_post, apoi curățăm valoarea.

add_action( 'save_post_dex_meniu', 'dex_salveaza_pret' );

function dex_salveaza_pret( $post_id ) {
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }
    if ( ! isset( $_POST['dex_pret_nonce'] )
        || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['dex_pret_nonce'] ) ), 'dex_salveaza_pret' ) ) {
        return;
    }
    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }
    if ( isset( $_POST['dex_pret'] ) ) {
        update_post_meta( $post_id, '_dex_pret', sanitize_text_field( wp_unslash( $_POST['dex_pret'] ) ) );
    }
}

Exemplul 2: Doar articolele noi, fără revizii și ciorne automate

Cu 10, 3 primim și $update. Sărim peste revizii, autosave și ciornele automate, apoi scriem în debug.log doar la creare.

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

function dex_articol_nou( $post_id, $post, $update ) {
    if ( $update || wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
        return;
    }
    if ( 'auto-draft' === $post->post_status ) {
        return;
    }
    error_log( "Articol nou: {$post->post_title} (ID {$post_id})" );
}

Rezultat

[25-Oct-2026 11:02:47 UTC] Articol nou: Program de sărbători (ID 58)

Exemplul 3: Fără buclă infinită când actualizezi articolul

wp_update_post() declanșează din nou save_post. Scoatem funcția înainte de actualizare și o adăugăm la loc după, cum arată documentația.

add_action( 'save_post', 'dex_privat_daca_e_intern' );

function dex_privat_daca_e_intern( $post_id ) {
    if ( wp_is_post_revision( $post_id ) || ! has_category( 'intern', $post_id ) ) {
        return;
    }
    remove_action( 'save_post', 'dex_privat_daca_e_intern' );
    wp_update_post( array( 'ID' => $post_id, 'post_status' => 'private' ) );
    add_action( 'save_post', 'dex_privat_daca_e_intern' );
}

Greșeli frecvente

  • wp_update_post() în propria funcție save_post fără remove_action() înainte: funcția se apelează pe ea însăși la nesfârșit.
  • Fără nonce și current_user_can(): oricine poate trimite o cerere care îți schimbă câmpurile. Verifică întotdeauna ambele înainte de update_post_meta().
  • Ai uitat 10, 3 și folosești $post sau $update: funcția primește doar ID-ul și PHP oprește execuția cu ArgumentCountError.
  • Nu ignori autosave-ul și reviziile: codul (de exemplu un e-mail de notificare) rulează de mai multe ori pentru aceeași salvare.

Comenzi înrudite

  • add_action: Leagă o funcție de o acțiune WordPress, ca să ruleze automat când WordPress ajunge în acel punct.
  • get_post_meta / update_post_meta: Citește, salvează, adaugă și șterge câmpuri personalizate (post meta) ale unui articol: preț, oraș, cod produs.
  • wp_insert_post: Creează un articol (sau îl actualizează, dacă dai ID) din cod; wp_update_post() modifică doar câmpurile date.
  • wp_nonce_field: Adaugă într-un formular un câmp ascuns cu un nonce, un cod care dovedește că cererea pornește chiar de pe site-ul tău.
  • current_user_can: Verifică dacă utilizatorul conectat are un anumit drept (capability), de exemplu manage_options sau edit_post pentru un articol.
  • sanitize_text_field: Curăță textul de pe o singură linie primit de la utilizator: elimină HTML-ul, rândurile noi, tab-urile și spațiile în plus.