web-dev-qa-db-ger.com

Metabox-Wiederholungsfelder - Optionsfelder werden nicht korrekt gespeichert

Ich habe mehrere Optionsfelder in einer Metabox in einem benutzerdefinierten Beitragstyp eingerichtet. Ich habe die Metabox so erstellt:

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

Und hier ist meine Speicherfunktion, um die Daten in einem Array zu speichern.

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

}

Das Problem, vor dem ich stehe, ist, dass ich beispielsweise drei Zeilen habe. Wenn ich das erste auf DVD setze, das zweite auf Weichzeichnen und das dritte auf 3D, wird nur der letzte Wert als 3D gespeichert. Alle anderen ['playback_format'] speichern als 'null'.

So wie ich die Dinge eingerichtet habe, sieht es so aus, als ob die Dinge richtig gespeichert werden sollten. Dies ist eine abgespeckte Version. Ich habe Eingabefelder, die korrekt gespeichert werden, aber die Optionsfelder waren ein großes Problem.

Es sieht so aus, als ob meine Speicherfunktion jeden ['playback_format'] an der richtigen Stelle im Array speichern sollte. Aber nur eine Filiale. Ich habe dafür gesorgt, dass für alle drei Zeilen derselbe Wert gespeichert wird, kann aber nicht für jede Zeile einen eindeutigen Wert erhalten und weiß nicht, warum.

Jede Hilfe wäre dankbar, da dies das letzte Puzzleteil ist!

Vielen Dank! (Screenshot unten als visuelle Hilfe)

repeatable rows - visual aid

Hier ist der Wert von var_dump($field); nach dem Speichern der Daten im obigen Screenshot.

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

Also bin ich nach dem Üben darauf zurückgekommen und habe einige der Alchemy-Einstellungen implementiert, was bedeutet, dass alle Eingaben Namen wie name="_movies[3][title]" haben, wobei 3 die Iteration ist, auf der wir uns in der Schleife befinden.

Erstellen Sie die 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 
}

Speichern Sie das Meta

Das Speichern ist jetzt relativ einfach, da die Arrays in den Namen es für uns einrichten:

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

Ich werde sage, dass ich auf dasselbe Problem gestoßen bin, über das wir im Chat gesprochen haben ... Ich habe mich gewendet, als ich immer noch auf das zweite und dritte 'Playback_Format'-Radio gestoßen bin, was nicht der Fall war Abendposting. Aber schließlich habe ich festgestellt, dass Sie die Funkgeräte in ein <form> -Element einwickeln. Ich bin überzeugt, dass dies das Problem ist, denn sobald ich es losgeworden bin, hat es funktioniert.

Ich würde vorschlagen, dass Sie versuchen, diesen zusätzlichen <Form> zuerst aus Ihrem Code zu entfernen, um zu sehen, ob dies das Problem löst. Es könnte sein, dass der Rest Ihres Codes funktioniert. Wenn nicht, dann bin ich mir ziemlich sicher, dass ich es jetzt tue ... Ich habe jedoch einige Namen und einige IDs geändert, so dass sich dies wahrscheinlich auf den Rest der Arbeit auswirken wird, die darauf beruht.

Und schließlich musste ich, nachdem ich alles geändert hatte, Ihre Add-Row-JS modifizieren. Es ist hier vereinfacht, da ich mich nicht mit den tinyMCE-Editoren befassen wollte, also habe ich die Textbereiche nur für meine Testzwecke verlassen.

Zeile mit Javascript duplizieren

/*********************** 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