web-dev-qa-db-fra.com

Champs répétitifs Metabox - les boutons radio ne sont pas enregistrés correctement

J'ai plusieurs boutons radio configurés à l'intérieur d'une metabox dans un type de message personnalisé. J'ai créé le metabox comme suit:

    add_action('admin_init', 'add_meta_boxes', 1);
    function add_meta_boxes() {
        add_meta_box( 'repeatable_fields', 'Top 10 Movie List', 'repeatable_meta_box_display', 'cpt_top_ten_list', 'normal', 'default');
    }

    function repeatable_meta_box_display() {
        global $post;
        $repeatable_fields = get_post_meta($post->ID, 'repeatable_fields', true);
        wp_nonce_field( 'repeatable_meta_box_nonce', 'repeatable_meta_box_nonce' );

     if ( $repeatable_fields ) :

    // set a variable so we can append it to each row
    $num = 0;
    $second_num = 0;

    foreach ( $repeatable_fields as $field ) {
    $num++;

<div class=" playbackformat-holder-<?php echo $num; ?> playbackformat-holder">
    <form id="playback-form-<?php echo $num; ?>">
        <label for="dvd-<?php echo $num; ?>">
        <input type="radio" class="playbackformat-holder-radiobutton" value="dvd" name="playback_format[<?php echo $second_num; ?>]" id="dvd-<?php echo $num; ?>" <?php if($field['playback_format'] == 'dvd') { echo 'checked'; } ?>>DVD
        </label>

        <label for="bluray-<?php echo $num; ?>">
        <input type="radio" class="playbackformat-holder-radiobutton" value="bluray" name="playback_format[<?php echo $second_num; ?>]" id="bluray-<?php echo $num; ?>" <?php if($field['playback_format'] == 'bluray') { echo 'checked'; } ?>>Bluray
        </label><br>    

        <label for="3d-<?php echo $num; ?>">
        <input type="radio" class="playbackformat-holder-radiobutton" value="3d" name="playback_format[<?php echo $second_num; ?>]" id="3d-<?php echo $num; ?>" <?php if($field['playback_format'] == '3d') { echo 'checked'; } ?>>3d
        </label><br />
    </form>     
</div>
second_num++;
}

Et voici ma fonction de sauvegarde pour stocker les données dans un tableau.

add_action('save_post', 'repeatable_meta_box_save', 10, 2);
function repeatable_meta_box_save($post_id) {

    if ( ! isset( $_POST['repeatable_meta_box_nonce'] ) ||
    !wp_verify_nonce( $_POST['repeatable_meta_box_nonce'], 'repeatable_meta_box_nonce' ) )
    return;

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
    return;

    if (!current_user_can('edit_post', $post_id))
    return;

    $old = get_post_meta($post_id, 'repeatable_fields', true);
    $new = array();

    $playbackFormats = $_POST['playback_format'];


    $count = count( $names ) - 1;

    for ( $i = 0; $i < $count; $i++ ) {

    // currently only storing the last stored radio value
    $new[$i]['playback_format'] = $playbackFormats[$i];

    // save movie description
     // and however you want to sanitize
    if ( !empty( $new ) && $new != $old ) {
        update_post_meta( $post_id, 'repeatable_fields', $new );
    } elseif ( empty($new) ) {
        delete_post_meta( $post_id, 'repeatable_fields', $old );
    }

}

Le problème auquel je suis confronté est que, disons que j'ai trois rangées. Si je règle le premier sur DVD, le second sur flou et le troisième sur 3D, seule la dernière valeur est enregistrée en 3D. Tous les autres ['playback_format'] stockent comme 'null'.

Dans ma configuration, il semble que les choses devraient être sauvegardées correctement. Ceci est une version allégée. J'ai des champs de saisie qui stockent correctement, mais les boutons radio ont été un problème majeur.

Il semble que ma fonction de sauvegarde devrait stocker chaque ['playback_format'] à sa place appropriée dans le tableau. Mais un seul magasins. Je l'ai eu pour stocker la même valeur pour les trois lignes, mais je ne peux pas obtenir une valeur unique pour chaque ligne et je ne sais pas pourquoi.

Toute aide serait la bienvenue, car c’est la dernière pièce du puzzle!

Merci! (Capture d'écran ci-dessous pour une aide visuelle)

repeatable rows - visual aid

Voici la valeur de var_dump($field); après le stockage des données dans la capture d'écran ci-dessus.

array(4) { 
 ["name"]=> string(116) "http://onecinephile.staging.wpengine.com/wp-content/uploads/2014/01/lon-chaney-phantom-hunchback-penalty-300x280.jpg" 
 ["select"]=> string(14) "Test #2" 
 ["url"]=> string(35) "Testing movie description #2" 
 ["playback_format"]=> string(3) "dvd" 
} 

array(4) { 
 ["name"]=> string(103) "http://onecinephile.staging.wpengine.com/wp-content/uploads/2014/01/spencer-tracy-boys-town-300x225.jpg" 
 ["select"]=> string(14) "Test #1" 
 ["url"]=> string(35) "Testing movie description #1" 
 ["playback_format"]=> NULL 
} 

array(4) { 
 ["name"]=> string(100) "http://onecinephile.staging.wpengine.com/wp-content/uploads/2014/01/Ronald-and-Madeleine-225x300.jpg" ["select"]=> string(14) "Test #3
 ["url"]=> string(35) "Testing movie description #3" 
 ["playback_format"]=> NULL 
}
3
EHerman

Je suis donc revenu à cette pratique après avoir implémenté une partie de la configuration d’Alchemy, ce qui signifie que toutes les entrées portent des noms tels que name="_movies[3][title]", où 3 est l’itération à laquelle nous participons.

Créer le Metabox

// metaboxes should be registered on the add_meta_boxes hook
add_action('add_meta_boxes', 'add_meta_boxes' );
function add_meta_boxes() {
    add_meta_box( 'repeatable_fields', 'Top 10 Movie List', 'repeatable_meta_box_display', 'cpt_top_ten_list', 'normal', 'default');
}


function repeatable_meta_box_display( $post ) { 

$repeatable_fields = get_post_meta($post->ID, 'repeatable_fields', true); 

if ( empty( $repeatable_fields ) ){
    $repeatable_fields[] = array ( 
                                'image' => '',
                                'title' => '',
                                'playback_format' => 'dvd',
                                'description' => '' );
}

wp_nonce_field( 'hhs_repeatable_meta_box_nonce', 'hhs_repeatable_meta_box_nonce' ); 
?> 

<table id="repeatable-fieldset-one" class="widefat fixed" cellspacing="0" style="width:100%;"> 
<thead> 
<tr> 
<th style="width:25px;" scope="col">Rank</th> 
<th style="width:170px;" scope="col">Image</th> 
<th width="145px" scope="col">Movie Title</th> 
<th width="300px" scope="col">Movie Description</th> 
<th width="8%" scope="col">Re-Order</th> 
</tr> 
</thead> 
<tbody> 


<?php 

// set a variable so we can append it to each row 
$i = 1; 

foreach ( $repeatable_fields as $field ) { ?>

<tr class="single-movie-row ui-state-default"> 

    <td> 
    <label for="_movies[<?php echo $i;?>][rank]"> 
    <input name="_movies[<?php echo $i;?>][rank]" id="_movies[<?php echo $i;?>][rank]" class="movie_rank_number" disabled="disabled" type="text" value="# <?php echo $i;?>" /> 
    </label>    
    </td> 

    <td> 
    <label for="_movies[<?php echo $i;?>][image]"> 
    <input name="_movies[<?php echo $i;?>][image]" class="upload_image" id="_movies[<?php echo $i;?>][image]" type="text" size="36" value="<?php echo esc_attr( $field['image'] );?>" /> 
    <input class="upload_image_button" id="_movies[<?php echo $i;?>][upload_image_button]" type="button" value="Upload Image" /> 
    </label> 
    </td> 

    <td> 
    <!-- title field --> 
    <textarea name="_movies[<?php echo $i;?>][title]" id="_movies[<?php echo $i;?>][title]" class="title_tinymce_editor"><?php echo esc_html( $field['title'] );?></textarea> 

    <div class="playbackformat-holder"> 

    <label for="_movies[<?php echo $i;?>][playback_format][dvd]"> 
    <input type="radio" id="_movies[<?php echo $i;?>][playback_format][dvd]" name="_movies[<?php echo $i;?>][playback_format]" value="dvd" <?php checked( $field['playback_format'], 'dvd' ); ?> />DVD 
    </label> 
    <label for="_movies[<?php echo $i;?>][playback_format][bluray]"> 
    <input type="radio" id="_movies[<?php echo $i;?>][playback_format][bluray]" name="_movies[<?php echo $i;?>][playback_format]" value="bluray" <?php checked( $field['playback_format'], 'bluray' ); ?> />Bluray 
    </label><br>    
    <label for="_movies[<?php echo $i;?>][playback_format][3d]"> 
    <input type="radio" id="_movies[<?php echo $i;?>][playback_format][3d]" name="_movies[<?php echo $i;?>][playback_format]" value="3d" <?php checked( $field['playback_format'], '3d' ); ?> />3d 
    </label><br />  

    </div> 

    </td> 

    <td>
    <textarea id="_movies[<?php echo $i;?>][description]" name="_movies[<?php echo $i;?>][description]" class="movie_description_editor_hidden"><?php echo esc_html( $field['description'] );?></textarea>
    </td> 

    <td>
    <a class="button remove-row" href="#">Remove Row</a><img src="<?php echo get_template_directory_uri() ?>/images/draggable-icon.png" alt="sortable icon" class="jQuerySortableIcon">
    </td> 

</tr> 

<?php $i++; } ?>


<!-- empty hidden one for jQuery --> 
<tr class="empty-row screen-reader-text single-movie-row"> 

    <td> 
    <label for="_movies[%s][rank]"> 
    <input name="_movies[%s][rank]" id="_movies[%s][rank]" class="movie_rank_number" disabled="disabled" type="text" value="" /> 
    </label>    
    </td> 

    <td> 
    <label for="_movies[%s][image]"> 
    <input name="_movies[%s][image]" class="upload_image" id="_movies[%s][image]" type="text" size="36" value="" /> 
    <input class="upload_image_button" id="_movies[<?php echo $i;?>][upload_image_button]" type="button" value="Upload Image" /> 
    </label> 
    </td> 

    <td> 
    <!-- title field --> 
    <textarea name="_movies[%s][title]" id="_movies[%s][title]" class="title_tinymce_editor"></textarea> 

    <div class="playbackformat-holder"> 

    <label for="_movies[%s][playback_format][dvd]"> 
    <input type="radio" id="_movies[%s][playback_format][dvd]" name="_movies[%s][playback_format]" value="dvd" <?php checked( 'dvd', 'dvd' ); ?> />DVD 
    </label> 
    <label for="_movies[%s][playback_format][bluray]"> 
    <input type="radio" id="_movies[%s][playback_format][bluray]" name="_movies[%s][playback_format]" value="bluray" />Bluray 
    </label><br>    
    <label for="_movies[%s][playback_format][3d]"> 
    <input type="radio" id="_movies[%s][playback_format][3d]" name="_movies[%s][playback_format]" value="3d" />3d 
    </label><br />  

    </div> 

    <!-- drop down or checkbox's with release formats --> 
    </td> 

    <td>
    <textarea id="_movies[%s][description]" name="_movies[%s][description]" class="movie_description_editor_hidden"></textarea>
    </td> 


    <td>
    <a class="button remove-row" href="#">Remove Row</a><img src="<?php echo get_template_directory_uri() ?>/images/draggable-icon.png" alt="sortable icon" class="jQuerySortableIcon">
    </td> 

</tr> 

</tbody> 
</table> 

<p id="add-row-p-holder"><a id="add-row" class="btn btn-small btn-success" href="#">Insert Another Row</a></p> 
<?php 
}

Sauvez la méta

La sauvegarde est maintenant relativement facile car les tableaux dans les noms nous le configurent:

add_action('save_post', 'hhs_repeatable_meta_box_save', 10, 2); 
function hhs_repeatable_meta_box_save($post_id) { 

if ( ! isset( $_POST['hhs_repeatable_meta_box_nonce'] ) || 
!wp_verify_nonce( $_POST['hhs_repeatable_meta_box_nonce'], 'hhs_repeatable_meta_box_nonce' ) ) 
return; 

if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) 
return; 

if (!current_user_can('edit_post', $post_id)) 
return; 

$clean = array(); 

if  ( isset ( $_POST['_movies'] ) && is_array( $_POST['_movies'] ) ) :

    foreach ( $_POST['_movies'] as $i => $movie ){

    // skip the hidden "to copy" div
    if( $i == '%s' ){ 
        continue;
    }

$playback_formats = array ( 'dvd', 'bluray', '3d' );

    $clean[] = array( 
        'image' => isset( $movie['image'] ) ? sanitize_text_field( $movie['image'] ) : null,
        'title' => isset( $movie['title'] ) ? sanitize_text_field( $movie['title'] ) : null,
        'playback_format' => isset( $movie['playback_format'] ) && in_array( $movie['playback_format'], $playback_formats ) ? $movie['playback_format'] : null,
        'description' => isset( $movie['description'] ) ? sanitize_text_field( $movie['description'] ) : null,
        );

}

endif;

// save movie data 
if ( ! empty( $clean ) ) { 
    update_post_meta( $post_id, 'repeatable_fields', $clean ); 
} else
    delete_post_meta( $post_id, 'repeatable_fields' ); 
}

Je vais dis que j'ai rencontré le même problème que celui dont nous avons parlé dans le chat ... Je me suis retourné quand, après tout cela, je rencontrais encore les deuxième et troisième radios de "lecture_format" qui n'étaient pas en soirée . Mais finalement, j'ai remarqué que vous enveloppiez les radios dans un élément <form>. Je suis convaincu que c'est le problème car dès que je m'en suis débarrassé, cela a fonctionné.

Je vous suggérerais d'essayer de supprimer d'abord ce <Form> supplémentaire de votre code pour voir si cela résout le problème. Cela pourrait être le reste de votre code fonctionne. Si ce n’est pas le cas, alors je suis à peu près sûr que le mien le fait maintenant ... cependant, j’ai changé certains noms et certains identifiants, ce qui affectera probablement le reste du travail qui en dépend.

Et enfin, en raison de la façon dont j'ai tout changé, je devais modifier votre JS add-row. Il est simplifié ici car je ne voulais pas traiter avec les éditeurs tinyMCE, je viens donc de quitter la zone de texte à des fins de test.

Duplicate Row avec Javascript

/*********************** Add Row Button Click *****************************/ 

$( '#add-row' ).click(function() { 
var rowCount = $('#repeatable-fieldset-one').find('.single-movie-row').not(':last-child').size(); 
var newRowCount = rowCount + 1;

var row = $( '.empty-row.screen-reader-text' ).clone(true); 

// Loop through all inputs
row.find('input, textarea, label').each(function(){ 

    if ( !! $(this).attr('id') )
        $(this).attr('id',  $(this).attr('id').replace('[%s]', '[' + newRowCount + ']') );  // Replace for

    if ( !! $(this).attr('name') )
        $(this).attr('name',  $(this).attr('name').replace('[%s]', '[' + newRowCount + ']') );  // Replace for

    if ( !! $(this).attr('for') )
        $(this).attr('for',  $(this).attr('for').replace('[%s]', '[' + newRowCount + ']') );  // Replace for

});

row.removeClass( 'empty-row screen-reader-text' ).find('.movie_rank_number').val('# '+newRowCount);
row.insertBefore( '.empty-row' ); 

// if row count hits 10, hide the add row button 
if ( newRowCount == 10 ) { 
jQuery('#add-row').fadeOut(); 
} 

return false; 
});
4
helgatheviking