Cum să validezi câmpuri personalizate în tipuri de postare personalizate în WordPress

28 aug. 2012, 23:15:25
Vizualizări: 18.8K
Voturi: 9

Am scris un plugin care creează un tip de postare personalizat cu câmpuri personalizate. Pentru a preveni utilizatorii să introducă informații incorecte, cum pot valida datele?

Am presupus că funcția hook save_post ar procesa validarea câmpurilor, dar nu găsesc o metodă directă care să afișeze erorile utilizatorului.

Există o funcție/trăsătură încorporată în WordPress pentru asta? Care este tehnica generală pentru validarea câmpurilor personalizate?

0
Toate răspunsurile la întrebare 5
9

Ești pe drumul cel bun. Testez câmpurile în callback-ul save_post, apoi folosesc notificări admin pentru a afișa erorile utilizatorului când un câmp nu trece de validare. Acestea apar într-o casetă evidențiată în partea de sus a paginii, exact ca orice erori/mesaje generate de WordPress însuși.

Iată un exemplu simplu de creare a unei notificări admin:

function my_admin_notice()
{
    ?>

    <div class="updated">
       <p>Aenean eros ante, porta commodo lacinia.</p>
    </div>

    <?php
}
add_action( 'admin_notices', 'my_admin_notice' );

Totuși, acest lucru nu este foarte practic. Într-o astfel de situație, ai nevoie de o funcție căreia să-i poți transmite un mesaj. Ceva de genul:

if( $pizza != 'warm' )
    $notices->enqueue( 'Pizza nu este caldă', 'error' );

Așadar, poți scrie singur funcția enqueue() (împreună cu o funcție pentru afișarea notificărilor), sau poți include o bibliotecă precum IDAdminNotices.

Iată un exemplu din un plugin pe care l-am scris. Acesta folosește funcții de adăugare/afișare a notificărilor care sunt integrate în clasa în sine, în loc să includă o bibliotecă externă.

public function saveCustomFields( $postID )
{
    // ...

    if( filter_var( $_POST[ self::PREFIX . 'zIndex'], FILTER_VALIDATE_INT ) === FALSE )
    {
        update_post_meta( $post->ID, self::PREFIX . 'zIndex', 0 );
        $this->enqueueMessage( 'Ordinea de suprapunere trebuie să fie un număr întreg.', 'error' );
    }   
    else
        update_post_meta( $post->ID, self::PREFIX . 'zIndex', $_POST[ self::PREFIX . 'zIndex'] );

    // ...
}
add_action( 'save_post',    array( $this, 'saveCustomFields' );
29 aug. 2012 00:21:14
Comentarii

Nu sunt foarte sigur în privința asta...codul exemplu necesită cod de la terți sau va funcționa în WordPress așa cum este?

Force Flow Force Flow
29 aug. 2012 03:52:44

Am adăugat mai multe detalii în răspuns.

Ian Dunn Ian Dunn
29 aug. 2012 04:37:58

Aceasta pare să funcționeze doar când pagina este încărcată pentru prima dată. Dacă se apasă butonul "Actualizează/Publică", nu sunt afișate notificări.

Force Flow Force Flow
30 aug. 2012 19:32:08

Ambele abordări funcționează pentru mine. Poți să postezi un link către codul complet?

Ian Dunn Ian Dunn
30 aug. 2012 22:43:27

Exemplu de cod: http://pastebin.com/vTxv9cw1

Force Flow Force Flow
30 aug. 2012 23:51:16

Cred că problema este că folosești o variabilă globală în loc să salvezi notificările în baza de date. Datele din variabile nu persistă între cereri. Deci, notificarea este adăugată în $bh_errorMessages la momentul salvării, apoi WordPress redirecționează înapoi la ecranul Editare Postare (care este o nouă cerere), iar toate variabilele sunt resetate. Vezi http://en.wikipedia.org/wiki/Post/Redirect/Get. Analizează mai atent IDAdminNotices și asigură-te că faci tot ce face acesta.

Ian Dunn Ian Dunn
31 aug. 2012 19:09:56

Nu sunt foarte sigur ce folosești pentru a permite variabilelor să persiste între cereri. Este vorba despre includerea variabilei $instance? Sau este una dintre declarațiile add_action? Sau ambele? Altceva?

Force Flow Force Flow
4 sept. 2012 16:38:14

ok, cred că am înțeles. Magia se întâmplă cu funcțiile WordPress add_option și get_option pentru a stoca și prelua variabila, iar hook-ul shutdown este util pentru a apela funcția add_option doar o dată per sesiune după ce totul s-a finalizat.

Force Flow Force Flow
4 sept. 2012 17:40:38

Da, exact așa este :)

Ian Dunn Ian Dunn
4 sept. 2012 21:48:10
Arată celelalte 4 comentarii
0

Am scris un mic plugin care nu doar validează câmpurile de intrare pe tipurile personalizate de postări, dar și elimină notificarea implicită din administrare, fără a folosi Javascript.

Iată o parte din cod

/ Filtre de validare

$title = $album->post_title;
if ( ! $title ) {
    $errors['title'] = "Titlul este obligatoriu";
}

// dacă avem erori, să configurăm niște mesaje
if (! empty($errors)) {

    // trebuie să eliminăm această acțiune altfel va intra într-o buclă infinită
    remove_action('save_post', 'album_save_post');

    // salvăm erorile ca opțiune
    update_option('album_errors', $errors);

    // Schimbăm starea postării din publicat în ciornă
    $album->post_status = 'draft';

    // actualizăm postarea
    wp_update_post( $album );

    // trebuie să readăugăm această acțiune
    add_action('save_post', 'album_save_post');

    // admin_notice este creat de un $_GET['message'] cu un număr pe care WordPress îl folosește pentru a
    // afișa mesajul de administrare, așa că vom adăuga un filtru pentru a înlocui mesajul implicit cu o redirecționare
    add_filter( 'redirect_post_location', 'album_post_redirect_filter' );
}

Puteți vedea tutorialul complet aici

31 mar. 2013 13:59:03
0

Când acțiunea save_post rulează, postarea a fost deja salvată în baza de date.

Dacă utilizați ACF, acesta are validare încorporată.

Cu toate acestea, dacă trebuie să validați elemente în afara ACF, cum ar fi post_title, lucrurile devin puțin mai complicate.

Analizând codul WordPress, mai exact funcția update_post() din wp-includes/post.php, nu există nicio metodă încorporată de a intercepta o cerere înainte de a fi salvată în baza de date.

Totuși, putem utiliza hook-ul pre_post_update și funcțiile header() și get_post_edit_link() pentru a preveni salvarea postării.

<?php

/**
*   Efectuează validare personalizată pentru tipul de postare personalizat "Site"
*/
function custom_post_site_save($post_id, $post_data) {
    # Dacă aceasta este doar o revizie, nu face nimic.
    if (wp_is_post_revision($post_id))
        return;

    if ($post_data['post_type'] == 'site') {
        # În acest exemplu, vom genera o eroare pentru titluri de postare cu mai puțin de 5 caractere
        if (strlen($post_data['post_title']) < 5) {
            # Adaugă o notificare
            update_option('my_notifications', json_encode(array('error', 'Titlul postării nu poate avea mai puțin de 5 caractere.')));
            # Și redirecționează
            header('Location: '.get_edit_post_link($post_id, 'redirect'));
            exit;
        }
    }
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);

/**
*   Afișează notificări personalizate în panoul de administrare WordPress
*/
function my_notification() {
    $notifications = get_option('my_notifications');

    if (!empty($notifications)) {
        $notifications = json_decode($notifications);
        #notifications[0] = (string) Tipul notificării: error, updated sau update-nag
        #notifications[1] = (string) Mesajul
        #notifications[2] = (boolean) este dismissable?
        switch ($notifications[0]) {
            case 'error': # roșu
            case 'updated': # verde
            case 'update-nag': # ?
                $class = $notifications[0];
                break;
            default:
                # Implicit la error pentru orice eventualitate
                $class = 'error';
                break;
        }

        $is_dismissable = '';
        if (isset($notifications[2]) && $notifications[2] == true)
            $is_dismissable = 'is_dismissable';

        echo '<div class="'.$class.' notice '.$is_dismissable.'">';
           echo '<p>'.$notifications[1].'</p>';
        echo '</div>';

        # Resetează notificarea
        update_option('my_notifications', false);
    }
}
add_action( 'admin_notices', 'my_notification' );
30 iul. 2018 01:24:03
1

Vreau să adaug la excelentul răspuns al lui @Lucas Bustamante că valoarea câmpurilor personalizate poate fi accesată prin variabila globală $_POST.

Astfel, răspunsul lui @Lucas Bustamante este valabil și dacă validarea se referă la un câmp personalizat. De exemplu:

<?php

/**
*   Efectuează validare personalizată pentru tipul de postare "Site"
*/
function custom_post_site_save($post_id, $post_data) {
    # Dacă aceasta este doar o revizie, nu face nimic.
    if (wp_is_post_revision($post_id))
        return;

    if ($post_data['post_type'] == 'site') {
        # În acest exemplu, vom genera o eroare pentru titlurile de postare cu mai puțin de 5 caractere
        if (strlen($_POST['zip_code']) < 5) {
            # Adaugă o notificare
            update_option('my_notifications', json_encode(array('error', 'Codul poștal nu poate avea mai puțin de 5 caractere.')));
            # Și redirecționează
            header('Location: '.get_edit_post_link($post_id, 'redirect'));
            exit;
        }
    }
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);

/**
*   Afișează notificări personalizate în panoul de administrare WordPress
*/
function my_notification() {
    $notifications = get_option('my_notifications');

    if (!empty($notifications)) {
        $notifications = json_decode($notifications);
        #notifications[0] = (string) Tipul notificării: error, updated sau update-nag
        #notifications[1] = (string) Mesajul
        #notifications[2] = (boolean) is_dismissible?
        switch ($notifications[0]) {
            case 'error': # roșu
            case 'updated': # verde
            case 'update-nag': # ?
                $class = $notifications[0];
                break;
            default:
                # Implicit, consideră eroare pentru orice eventualitate
                $class = 'error';
                break;
        }

        $is_dismissable = '';
        if (isset($notifications[2]) && $notifications[2] == true)
            $is_dismissable = 'is_dismissable';

        echo '<div class="'.$class.' notice '.$is_dismissable.'">';
           echo '<p>'.$notifications[1].'</p>';
        echo '</div>';

        # Resetează notificarea
        update_option('my_notifications', false);
    }
}
add_action( 'admin_notices', 'my_notification' );
``
23 nov. 2019 00:22:31
Comentarii

Redirecționarea nu este cea mai bună opțiune, deoarece pierzi toate datele introduse din cauza unui singur câmp.

Picard Picard
13 oct. 2021 16:19:00
0

poți folosi filtrul "wp_insert_post_data" pentru a modifica sau verifica datele înainte să fie introduse în baza de date

add_filter( 'wp_insert_post_data', 'validate_posttypes' );
function wpb_custom_excerpt($data) {
    str_starts_with($data['post_title'],'wp')?$data['post_title']='wp'.$data['post_title']:null;
    return $data;
}
7 mai 2021 17:20:26