web-dev-qa-db-ja.com

メタボックスの繰り返しフィールド - ラジオボタンが正しく保存されない

カスタム投稿タイプのメタボックス内に複数のラジオボタンを設定しました。私はそのようにメタボックスを作成しました:

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

そして、これがデータを配列に保存するための私のsave関数です。

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

}

私が直面している問題は、3行あるとしましょう。最初の値をDVD、2番目の値をブルーレイ、3番目の値を3Dに設定すると、最後の値だけが3Dとして格納されます。他のすべての['playback_format']は 'null'として格納されます。

私が物事を設定する方法は、物事が適切に保存されるべきであるように見えます。これは縮小版です。正しく保存されている入力フィールドがありますが、ラジオボタンが大きな問題になっています。

私のsave関数はそれぞれの['playback_format']を配列の適切な場所に格納しているはずです。しかし1つだけの店。 3行すべてに同じ値を格納するようにしましたが、各行に固有の値を取得することはできず、理由はわかりません。

これがパズルの最後のピースであるので、どんな助けでも評価されるでしょう!

ありがとうございます。 (下のスクリーンショットは視覚的な補助のため)

repeatable rows - visual aid

上記のスクリーンショットにデータを保存した後のvar_dump($field);の値は次のとおりです。

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

それで私は練習の後でこれに戻り、Alchemyのセットアップのいくつかを実装しました。つまり、すべての入力はname="_movies[3][title]"のような名前を持ちます。ここで3はループ内の反復です。

メタボックスを作成する

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

メタを保存する

名前の配列が私たちのためにそれを設定するので、保存は比較的簡単です。

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

私はwill私は私達がチャットで話したのと同じ問題に出くわしたと言っています....私はこれがやっぱり2番目と3番目の 'playback_format'ラジオに出くわしたとき夕方の投稿ではありませんでした。しかし最後に、私はあなたがラジオを<form>要素で包んでいることに気づきました。私がそれを取り除くとすぐに、それがうまくいったので、私はこれが問題であると確信しています。

最初にコードから余分な<Form>を削除して解決するかどうかを確認することをお勧めします。それはあなたのコードの残りの部分でうまくいくかもしれません。もしそうでなければ、私は今確実にしていると思います...しかし、私はいくつかの名前といくつかのIDを変更したので、これはおそらくこれに依存する残りの作業に影響を与えるでしょう。

そして最後に、私がすべてを変更した方法のB/Cは、私はあなたの追加行のJSを変更する必要がありました。私はtinyMCEエディタを扱いたくなかったので、ここでは単純化されています、それで私は私のテスト目的のためにテキストエリアを残しました。

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