【WordPress】管理画面に画像アップローダーを複数設置する方法【プラグイン無し】

久々の投稿になります。コースケです。
以前、ワードプレスの自作管理画面をプラグイン無しでカスタマイズする案件があったのですが、
「複数の画像アップローダーをプラグインを使わずに設置する」という作業に結構苦戦したので、
備忘録としてその方法を掲載しておきます。

まずはfunction.phpの内容です。
肝のjs(Jquery)部分はその次に掲載します。


```function.php
 //-----------------------------------------------------
 //管理画面に独自のcssとjsを読み込む
 //-----------------------------------------------------
 function add_admin_style(){
   $path_css = get_template_directory_uri().'/css/admin.css';
   wp_enqueue_style('admin_style', $path_css);
 }
 add_action('admin_enqueue_scripts', 'add_admin_style');
 
 function my_admin_scripts() {
   	$path_js = get_template_directory_uri().'/js/admin.js';
     wp_enqueue_script( 'admin_js',$path_js );
  
 }
 add_action( 'admin_enqueue_scripts', 'my_admin_scripts' ); 
 
 //-----------------------------------------------------
 //メディアアップローダーAPIを管理画面へ読み込ませる
 //-----------------------------------------------------
 add_action('admin_print_scripts', 'my_add_setting_media_api_scripts');
 function my_add_setting_media_api_scripts() {
   wp_enqueue_media();
 }
 
 function create_custom_fields()
 {
   add_meta_box(
     'custom_field_1', //セクションのID
     '情報入力欄', //セクションのタイトル
     'insert_custom_fields', //フォーム部分を指定する関数
     'case', //投稿タイプ名
     'normal', //セクションの表示場所
     'default'  //優先度
   );
 }
 add_action('admin_menu', 'create_custom_fields');
 
 //-----------------------------------------------------
 // 見た目（フォーム部分）の指定
 //-----------------------------------------------------
 function insert_custom_fields($post)
 {
  //nounceフィールドの追加
  wp_nonce_field('custom_field_save_meta_box_data', 'custom_field_meta_box_nonce');
  
   $const_before = get_post_meta($post->ID, 'const_before', true);
   $const_after = get_post_meta($post->ID, 'const_after', true);
   
 ?>
 <form method="post" action="admin.php?page=site_settings">
 <section class="l-custom">
 <h3>作業前後写真</h3>
 <div class="l-item mediaBox">
 		<label for="const_before">作業前写真<span class="red">(必須)</span></label>
 	    <input id="case_media01" class="media-value" name="const_before" type="text" value="<?php echo $const_before; ?>" required/>
 	    <input type="button" name="case_media01_select" class="media-btn" value="画像選択"/>
 	    <input type="button" name="case_media01_clear"class="media-clear-btn"  value="削除"/>
 	    <div id="case_media01_thumb" class="media_thumb">
 	        <img src="<?php echo $const_before; ?>" alt="">
 	    </div>
 </div>
 <div class="l-item mediaBox">
 		<label for="const_after">作業後写真<span class="red">(必須)</span></label>
 	    <input id="case_media02" class="media-value" name="const_after" type="text" value="<?php echo $const_after; ?>" required/>
 	    <input type="button" name="case_media02_select" class="media-btn" value="画像選択" />
 	    <input type="button" name="case_media02_clear"class="media-clear-btn"  value="削除"/>
 	    <div id="case_media02_thumb" class="media_thumb">
 	        <img src="<?php echo $const_after; ?>" alt="">
 	    </div>
 </div>
 </section>
 </form>
 <?php
 }
 function save_custom_fields($post_id)
 {
   //nounceがセットされているか確認
   if (!isset($_POST['custom_field_meta_box_nonce'])) {
     return;
   }
 
   //nounceが正しいか検証
   if (!wp_verify_nonce($_POST['custom_field_meta_box_nonce'], 'custom_field_save_meta_box_data')) {
     return;
   }
   
   //const_beforeデータを保存
   if (isset($_POST['const_before'])) {
     $data = sanitize_text_field($_POST['const_before']);
     update_post_meta($post_id, 'const_before', $data);
   }	
   //const_afterデータを保存
   if (isset($_POST['const_after'])) {
     $data = sanitize_text_field($_POST['const_after']);
     update_post_meta($post_id, 'const_after', $data);
   }
   }
   add_action('save_post', 'save_custom_fields');
```

基本的な管理画面作成の方法は同じですが、今回は画像アップロード部分を２つ設置しています。

```function.php
<!--一部-->
<form method="post" action="admin.php?page=site_settings">
 <section class="l-custom">
 <h3>施工前後写真</h3>
 <div class="l-item mediaBox">
 		<label for="const_before">施工前写真<span class="red">(必須)</span></label>
 	    <input id="case_media01" class="media-value" name="const_before" type="text" value="<?php echo $const_before; ?>" required/>
 	    <input type="button" name="case_media01_select" class="media-btn" value="画像選択"/>
 	    <input type="button" name="case_media01_clear"class="media-clear-btn"  value="削除"/>
 	    <div id="case_media01_thumb" class="media_thumb">
 	        <img src="<?php echo $const_before; ?>" alt="">
 	    </div>
 </div>
 <div class="l-item mediaBox">
 		<label for="const_after">施工後写真<span class="red">(必須)</span></label>
 	    <input id="case_media02" class="media-value" name="const_after" type="text" value="<?php echo $const_after; ?>" required/>
 	    <input type="button" name="case_media02_select" class="media-btn" value="画像選択" />
 	    <input type="button" name="case_media02_clear"class="media-clear-btn"  value="削除"/>
 	    <div id="case_media02_thumb" class="media_thumb">
 	        <img src="<?php echo $const_after; ?>" alt="">
 	    </div>
 </div>
 </section>
 </form>
```
もちろん、制作の際は画像アップローダー部分以外の入力欄と共に記述します。
注意点としては私の場合、画像アップロード部分ごとにformタグで囲っていたのが原因で、
あれやこれやと試しても動きませんでした・・・初歩的な部分は気をつけたいですね。
追加する入力欄全てを一括でformタグで囲うのが正解でした。
<br>
次にjs(Jquery)部分です。

```admin.js
//uploader
 jQuery(document).ready(function($){
 	var custom_uploader;
 	var target_input;
 	var target_display;
 	$('.media-btn').click(function(e) {
 		target_input = $(this).parent().find('.media-value').attr('id');
 		target_display = $(this).parent().find('.media_thumb').attr('id');
 		e.preventDefault();
 		
 		if (custom_uploader) {
 			custom_uploader.open();
 			return;
 		}
 		
 		custom_uploader = wp.media.frames.file_frame = wp.media({
 			title: "画像を選択", //タイトルのテキストラベル
 			button: {
 				text: "画像を設定" //ボタンのテキストラベル
 			},
 			multiple: false //選択できる画像を1つだけにする。
 		});
 		
 		custom_uploader.on('select', function() {
 			attachment = custom_uploader.state().get('selection').first().toJSON();
            $( '#' + target_input ).val(""); //テキストフォームをクリア
            $( '#' + target_display ).empty(); //id mediaタグの中身をクリア
 		   $( '#' + target_input ).val(attachment.url);
            $( '#' + target_display ).append('<img src="'+attachment.url+'" />'); 
            //プレビュー用にメディアアップローダーで選択した画像を表示させる
 		});
 		custom_uploader.open();
 	});
 });
 
 //clear-btn
 jQuery(document).ready(function($){
 	var clear_input;
 	var clear_display;
  	$(".media-clear-btn").click(function() {
 	 	clear_input = $(this).parent().find('.media-value').attr('id');
 	 	clear_display = $(this).parent().find('.media_thumb').attr('id');
      	$( '#' + clear_input ).val(""); //テキストフォームをクリア
      	$( "#" + clear_display ).empty(); //id mediaタグの中身をクリア
  	});
 });
```

基本的なワードプレスの画像アップローダー実装のjsをカスタマイズしたものになります。
肝心な部分は割と単純で、下記の部分になります。

```admin.js
$('.media-btn').click(function(e) {
    target_input = $(this).parent().find('.media-value').attr('id');
 	target_display = $(this).parent().find('.media_thumb').attr('id');
```
.media-btnをクリックすると、その親要素を参照し、さらにその中の指定したclassを探します。
要するにクリックしたグループの.media-value（値入力欄）と.media_thumb(入力した画像のサムネイル表示部分)を指定し、それぞれのidの値を出力します。
後はこのidを使ってグループごとに後半部分に記述されているカスタムアップローダーの処理が行われるようにします。

これで画像アップローダーを５個でも１０個でもいくらでも設置できるようになります。

元々参照した記事があるのですが今では見つからず・・・そこでは.next()や.prev()が使われていたのですが、.parent().find('特定のクラス')を使った方が綺麗かと思い、上記のようにしています。

クリアボタンに関しても同様の方法になります。

いかがでしょうか。
備忘録ということで色々はしょっていますが、ワードプレスでプラグインなしで複数の画像アップローダーを設置する方法の記事がなかなか無いのでとりあえず掲載しておきました。