Come validare i campi personalizzati in un custom post type?

28 ago 2012, 23:15:25
Visualizzazioni: 18.8K
Voti: 9

Ho sviluppato un plugin che crea un custom post type con campi personalizzati. Per evitare che gli utenti inseriscano informazioni errate, come posso validare i dati?

Pensavo che la funzione dell'hook save_post potesse gestire la validazione dei campi, ma non riesco a trovare un metodo semplice per mostrare gli errori all'utente.

Esiste una funzione integrata in WordPress per questo? Qual è la tecnica generalmente usata per implementare la validazione dei campi personalizzati?

0
Tutte le risposte alla domanda 5
9

Stai procedendo nella giusta direzione. Testo i campi nel callback save_post e poi uso avvisi di amministrazione per mostrare gli errori all'utente quando un campo non supera la validazione. Appaiono in una casella evidenziata nella parte superiore della pagina, proprio come qualsiasi errore/messaggio generato da WordPress stesso.

Ecco un semplice esempio di creazione di un avviso di amministrazione:

function my_admin_notice()
{
    ?>

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

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

Non è molto pratico, però. In una situazione come questa, vorresti semplicemente una funzione a cui puoi passare un messaggio. Qualcosa tipo,

if( $pizza != 'warm' )
    $notices->enqueue( 'La pizza non è calda', 'error' );

Quindi, puoi scrivere tu stesso la funzione enqueue() (insieme a una funzione per stampare gli avvisi), oppure puoi includere una libreria come IDAdminNotices.

Ecco un esempio tratto da un plugin che ho scritto. Questo utilizza funzioni di accodamento/stampa degli avvisi integrate nella classe stessa, anziché includere una libreria esterna.

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( 'L\'ordine di sovrapposizione deve essere un numero intero.', 'error' );
    }   
    else
        update_post_meta( $post->ID, self::PREFIX . 'zIndex', $_POST[ self::PREFIX . 'zIndex'] );

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

Non sono del tutto chiaro su questo... il tuo codice di esempio richiede codice di terze parti, o funzionerà in WordPress così com'è?

Force Flow Force Flow
29 ago 2012 03:52:44

Ho aggiunto maggiori dettagli alla risposta.

Ian Dunn Ian Dunn
29 ago 2012 04:37:58

Sembra funzionare solo quando la pagina viene caricata per la prima volta. Se si clicca il pulsante "Aggiorna/Pubblica", non vengono visualizzati avvisi.

Force Flow Force Flow
30 ago 2012 19:32:08

Entrambi gli approcci funzionano per me. Puoi pubblicare un link al codice completo?

Ian Dunn Ian Dunn
30 ago 2012 22:43:27

Codice di esempio: http://pastebin.com/vTxv9cw1

Force Flow Force Flow
30 ago 2012 23:51:16

Penso che il problema sia che stai usando una variabile globale invece di salvare gli avvisi nel database. I dati nelle variabili non persistono tra le richieste. Quindi, l'avviso viene aggiunto a $bh_errorMessages durante la richiesta di salvataggio, poi WordPress reindirizza nuovamente alla schermata di modifica dell'articolo (che è una nuova richiesta), e tutte le variabili vengono reimpostate. Vedi http://en.wikipedia.org/wiki/Post/Redirect/Get. Dai un'occhiata più da vicino a IDAdminNotices e assicurati di fare tutto ciò che fa.

Ian Dunn Ian Dunn
31 ago 2012 19:09:56

Non sono del tutto chiaro su cosa stai usando per permettere alle variabili di persistere tra le richieste. È l'inclusione della variabile $instance? O è uno degli statement add_action? O entrambi? Qualcos'altro?

Force Flow Force Flow
4 set 2012 16:38:14

ok, penso di aver capito. La magia sta nelle funzioni WordPress add_option e get_option per memorizzare e recuperare la variabile, e l'hook shutdown è utile per chiamare la funzione add_option solo una volta per sessione dopo che tutto è stato fatto.

Force Flow Force Flow
4 set 2012 17:40:38

Sì, esattamente :)

Ian Dunn Ian Dunn
4 set 2012 21:48:10
Mostra i restanti 4 commenti
0

Ho scritto un piccolo plugin che non solo valida i campi di input sui custom post type, ma rimuove anche il messaggio predefinito di amministrazione, senza l'uso di Javascript.

ecco parte del codice

/ Filtri di validazione

$title = $album->post_title;
if ( ! $title ) {
    $errors['title'] = "Il titolo è obbligatorio";
}

// se abbiamo errori impostiamo alcuni messaggi
if (! empty($errors)) {

    // dobbiamo rimuovere questa azione altrimenti entrerà in loop infinito
    remove_action('save_post', 'album_save_post');

    // salviamo gli errori come opzione
    update_option('album_errors', $errors);

    // Cambiamo lo stato del post da pubblicato a bozza
    $album->post_status = 'draft';

    // aggiorniamo il post
    wp_update_post( $album );

    // dobbiamo riaggiungere questa azione
    add_action('save_post', 'album_save_post');

    // admin_notice viene creato da un $_GET['message'] con un numero che WordPress usa per
    // mostrare il messaggio di amministrazione, quindi aggiungeremo un filtro per sostituire il messaggio predefinito con un reindirizzamento
    add_filter( 'redirect_post_location', 'album_post_redirect_filter' );
}

Puoi vedere il tutorial completo qui

31 mar 2013 13:59:03
0

Quando save_post viene eseguito, il post è già stato salvato nel database.

Se stai utilizzando ACF, ha una validazione integrata.

Tuttavia, se hai bisogno di validare elementi al di fuori di ACF, come post_title, le cose diventano un po' più complicate.

Analizzando il codice core di WordPress, più precisamente la funzione update_post() in wp-includes/post.php, non esiste un modo integrato per intercettare una richiesta prima che venga salvata nel database.

Tuttavia, possiamo agganciarci a pre_post_update e utilizzare header() e get_post_edit_link() per impedire il salvataggio del post.

<?php

/**
*   Esegue una validazione personalizzata sul custom post type "Site"
*/
function custom_post_site_save($post_id, $post_data) {
    # Se si tratta solo di una revisione, non fare nulla.
    if (wp_is_post_revision($post_id))
        return;

    if ($post_data['post_type'] == 'site') {
        # In questo esempio, genereremo un errore per i titoli dei post con meno di 5 caratteri
        if (strlen($post_data['post_title']) < 5) {
            # Aggiungi una notifica
            update_option('my_notifications', json_encode(array('error', 'Il titolo del post non può essere inferiore a 5 caratteri.')));
            # E reindirizza
            header('Location: '.get_edit_post_link($post_id, 'redirect'));
            exit;
        }
    }
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);

/**
*   Mostra notifiche personalizzate nel pannello di amministrazione di WordPress
*/
function my_notification() {
    $notifications = get_option('my_notifications');

    if (!empty($notifications)) {
        $notifications = json_decode($notifications);
        #notifications[0] = (string) Tipo di notifica: error, updated o update-nag
        #notifications[1] = (string) Messaggio
        #notifications[2] = (boolean) è dismissibile?
        switch ($notifications[0]) {
            case 'error': # rosso
            case 'updated': # verde
            case 'update-nag': # ?
                $class = $notifications[0];
                break;
            default:
                # Di default imposta error per sicurezza
                $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>';

        # Resetta la notifica
        update_option('my_notifications', false);
    }
}
add_action( 'admin_notices', 'my_notification' );
30 lug 2018 01:24:03
1

Vorrei solo aggiungere all'eccellente risposta di @Lucas Bustamante che il valore dei campi personalizzati può essere accessibile tramite la variabile globale $_POST.

Quindi, la risposta di @Lucas Bustamante è valida anche se la validazione si riferisce a un campo personalizzato. Ad esempio:

<?php

/**
*   Esegue una validazione personalizzata sul custom post type "Site"
*/
function custom_post_site_save($post_id, $post_data) {
    # Se si tratta solo di una revisione, non fare nulla.
    if (wp_is_post_revision($post_id))
        return;

    if ($post_data['post_type'] == 'site') {
        # In questo esempio, genereremo un errore per i titoli dei post con meno di 5 caratteri
        if (strlen($_POST['zip_code']) < 5) {
            # Aggiungi una notifica
            update_option('my_notifications', json_encode(array('error', 'Il codice postale non può essere inferiore a 5 caratteri.')));
            # E reindirizza
            header('Location: '.get_edit_post_link($post_id, 'redirect'));
            exit;
        }
    }
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);

/**
*   Mostra notifiche personalizzate nel pannello di amministrazione di WordPress
*/
function my_notification() {
    $notifications = get_option('my_notifications');

    if (!empty($notifications)) {
        $notifications = json_decode($notifications);
        #notifications[0] = (string) Tipo di notifica: error, updated o update-nag
        #notifications[1] = (string) Messaggio
        #notifications[2] = (boolean) è chiudibile?
        switch ($notifications[0]) {
            case 'error': # rosso
            case 'updated': # verde
            case 'update-nag': # ?
                $class = $notifications[0];
                break;
            default:
                # Imposta error come default per sicurezza
                $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>';

        # Resetta la notifica
        update_option('my_notifications', false);
    }
}
add_action( 'admin_notices', 'my_notification' );
23 nov 2019 00:22:31
Commenti

Il reindirizzamento non è l'opzione migliore poiché si perdono tutti i dati inseriti a causa di un solo campo.

Picard Picard
13 ott 2021 16:19:00
0

puoi utilizzare il filtro "wp_insert_post_data" per modificare o verificare i dati prima che vengano inseriti nel database

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 mag 2021 17:20:26