今回の記事では、カスタムフィールドで、複数枚の画像のアップロード機能を実装する方法を解説します。
サンプルコードも用意しましたので、実際の要件と共に理解を深めていただきましたら幸いです。

要件

固定ページでメインビジュアル画像3枚の登録機能を実装してほしい

実装

いつも通り、結論から先に知りたい方のためにコードを共有します。

<?php
function add_custom_media_fields() {
    add_meta_box(
        'main_visual_image_id',
        'メインビジュアル画像の登録',
        'media_custom_fields',
        'page',
        'side',
        'default',
    );
}

function media_custom_fields()
{
    $main_visual_images = array();
    

    for ($i=0; $i < 3; $i++) {
        $main_visual_images[] = get_post_custom( $post->ID, 'main_visual_image_'.$i, true );
    } ?>
    <div>
        <?php for ( $i=0; $i < 3; $i++ ):?>
            <div class="form-field">
                <p scope="row" style="font-size: ;">メインビジュアル画像<?php echo $i + 1;?>枚目 : </p>
                <div>
                    <input type="hidden" id="main_visual_image_<?php echo $i; ?>" name="main_visual_image_<?php echo $i; ?>" value="<?php echo $main_visual_images[$i] ? $main_visual_images[$i] : '' ?>">
                    <div id="image-wrapper_<?php echo $i?>">
                    <?php if ( $main_visual_images[$i] ) {
                        $main_visual = wp_get_attachment_image_src ( intval($main_visual_images[$i]["main_visual_image_$i"][0]), 'thumbnail' );
                        ?>
                        <img src="<?php echo $main_visual[0] ?>" width="<?php echo $main_visual[1]; ?>" height="<?php echo $main_visual[2]; ?>" class="custom_media_image">
                    <?php } ?>
                    </div>
                    <p><input type="button" class="button button-secondary media_button" name="media_button" value="追加・変更" id="media-button_<?php echo $i?>" />
                    <input type="button" class="button button-secondary media_remove" name="media_remove" value="削除" id="media-remove_<?php echo $i?>"/></p>
                </div>
            </div>
        <?php endfor;?>
    </div>
    <?php
}

add_action( 'admin_enqueue_scripts', 'add_api' );
function add_api() {
    wp_enqueue_media();
}


add_action( 'admin_footer', 'add_script' );
function add_script() {
    ?>
    <script>
    jQuery(document).ready(
        function($) {
            let _custom_media = true,
            _orig_send_attachment = wp.media.editor.send.attachment;

            // 画像の登録
            $( '.media_button' ).each(function(index) {
                $(this).on("click", function(){
                    let send_attachment_bkp = wp.media.editor.send.attachment;
                    wp.media.editor.send.attachment = function(props, attachment){
                        if ( _custom_media ) {
                            $('#main_visual_image_'+index).val(attachment.id);
                            $('#image-wrapper_'+index).html('<img class="custom_media_image" src="' + attachment.sizes.thumbnail.url + '" height="' + attachment.sizes.thumbnail.height + '" width="' + attachment.sizes.thumbnail.width + '">');
                        } else {
                            return _orig_send_attachment.apply( $(this).id, [props, attachment] );
                        }
                    }
                    wp.media.editor.open($(this));
                    return false;
                });
            });

            // 削除
            $( '.media_remove').each(function(index) {
                $(this).on("click", function(){
                    $('#main_visual_image_'+index).val('');
                    $('#image-wrapper_' + index + ' .custom_media_image').remove();
                });
            });
        });
    </script>
    <?php
}

add_action( 'save_post', 'save_main_visual_images' );
function save_main_visual_images( $post_id ) {
    for ( $i=0; $i < 3; $i++ ) {
        // 画像の保存
        if( isset( $_POST['main_visual_image_' . $i] ) ) {
			if( $_POST['main_visual_image_' . $i] !== '' ) {
				update_post_meta( $post_id, 'main_visual_image_' . $i, $_POST['main_visual_image_' . $i] );
			} else {
				delete_post_meta( $post_id, 'main_visual_image_'.$i );
			}
        }
    }
}


解説

処理の全体像としては、下記の4つの手順で進んでいきます。
それぞれのフェーズを解説していきます。

  • カスタムフィールドの追加
  • 画像登録画面のHTMLを用意
  • 画像選択のホップアップの表示
  • 投稿の更新と同時に画像を保存

カスタムフィールドの追加

<?php
function add_custom_media_fields() {
    add_meta_box(
        'main_visual_image_id',
        'メインビジュアル画像の登録',
        'media_custom_fields',
        'page',
        'side',
        'default',
    );
}

こちらは、これまでの記事で解説してきたカスタムフィールドの追加なので、解説は割愛します。

画像登録画面のHTMLを用意

<?php
function media_custom_fields()
{
    $main_visual_images = array();
    

    for ($i=0; $i < 3; $i++) {
        $main_visual_images[] = get_post_custom( $post->ID, 'main_visual_image_'.$i, true );
    } ?>
    <div>
        <?php for ( $i=0; $i < 3; $i++ ):?>
            <div class="form-field">
                <p scope="row" style="font-size: ;">メインビジュアル画像<?php echo $i + 1;?>枚目 : </p>
                <div>
                    <input type="hidden" id="main_visual_image_<?php echo $i; ?>" name="main_visual_image_<?php echo $i; ?>" value="<?php echo $main_visual_images[$i] ? $main_visual_images[$i] : '' ?>">
                    <div id="image-wrapper_<?php echo $i?>">
                    <?php if ( $main_visual_images[$i] ) {
                        $main_visual = wp_get_attachment_image_src ( intval($main_visual_images[$i]["main_visual_image_$i"][0]), 'thumbnail' );
                        ?>
                        <img src="<?php echo $main_visual[0] ?>" width="<?php echo $main_visual[1]; ?>" height="<?php echo $main_visual[2]; ?>" class="custom_media_image">
                    <?php } ?>
                    </div>
                    <p><input type="button" class="button button-secondary media_button" name="media_button" value="追加・変更" id="media-button_<?php echo $i?>" />
                    <input type="button" class="button button-secondary media_remove" name="media_remove" value="削除" id="media-remove_<?php echo $i?>"/></p>
                </div>
            </div>
        <?php endfor;?>
    </div>
    <?php
}

こちらはadd_meta_boxで指定されたコールバック関数になり、画像登録用のHTMLを描画します。
画像を3枚登録するので、for分のループで3回まで描画処理を実行しています。

$main_visual_images = array();で画像の配列を作成していますが、
すでに画像が登録済みである場合、value属性に値を格納するために用意しています。
get_post_custom( $post->ID, ‘main_visual_image_’.$i, true );でカスタムフィールドの保存先から、
name属性に紐づくデータを取得しているのはそのためです。

画像選択のホップアップの表示

<?php
add_action( 'admin_enqueue_scripts', 'add_api' );

function add_api() {
    wp_enqueue_media();
}

add_action( 'admin_footer', 'add_script' );
function add_script() {
    ?>
    <script>
    jQuery(document).ready(
        function($) {
            let _custom_media = true,
            _orig_send_attachment = wp.media.editor.send.attachment;

            // 画像の登録
            $( '.media_button' ).each(function(index) {
                $(this).on("click", function(){
                    let send_attachment_bkp = wp.media.editor.send.attachment;
                    wp.media.editor.send.attachment = function(props, attachment){
                        if ( _custom_media ) {
                            $('#main_visual_image_'+index).val(attachment.id);
                            $('#image-wrapper_'+index).html('<img class="custom_media_image" src="' + attachment.sizes.thumbnail.url + '" height="' + attachment.sizes.thumbnail.height + '" width="' + attachment.sizes.thumbnail.width + '">');
                        } else {
                            return _orig_send_attachment.apply( $(this).id, [props, attachment] );
                        }
                    }
                    wp.media.editor.open($(this));
                    return false;
                });
            });

            // 削除
            $( '.media_remove').each(function(index) {
                $(this).on("click", function(){
                    $('#main_visual_image_'+index).val('');
                    $('#image-wrapper_' + index + ' .custom_media_image').remove();
                });
            });
        });
    </script>
    <?php
}

WordPressには、メディアアップローダーを呼び出すための処理が用意されています。
wp_enqueue_media()関数を実装して、メディアアップローダーの読み込みに必要なライブラリを準備します。

その後に定義されているadd_script()関数では、「画像の登録」「画像の削除」が実行された際の処理を記述しています。
少し長々と記述がありますが、やっていることは非常にシンプルです。

実際の保存処理は、投稿が更新されたタイミングで実行されるので、
ここでは、メディアアップローダーを表示させ、そこで選択された画像のIDを、valueに格納
+ その画像をimg要素で表示させる処理を行なっています。

「削除」ボタンがクリックされたタイミングでは、value属性とimg要素のデータを空にするように処理がされています。

投稿の更新と同時に画像を保存

<?php
function save_main_visual_images( $post_id ) {
    for ( $i=0; $i < 3; $i++ ) {
        if( isset( $_POST['main_visual_image_' . $i] ) ) {
			if( $_POST['main_visual_image_' . $i] !== '' ) {
				update_post_meta( $post_id, 'main_visual_image_' . $i, $_POST['main_visual_image_' . $i] );
			} else {
				delete_post_meta( $post_id, 'main_visual_image_'.$i );
			}
        }
    }
}

これまで解説してきたカスタムフィールドの保存処理と同様に、投稿の更新と同時にデータの有無をチェックします。
update_post_meta()関数とdelete_post_meta()関数を使用して、データの登録 or データの破棄を行なっています。

複数の登録フィールドを用意する場合には、add_meta_boxのコールバック関数で実行するHTMLのname属性、value属性に、正確に値が割り当てられるように実装する必要があります。

カテゴリー: WordPress