以前、管理画面から画像をアップロードするコードをただ載せただけで、このブログにしては反響があった。
しかしこのコードは旧版のメディアアップローダーを利用したもので、機能するものの最新のWPと統一感が取れていない。
そこで、例によって別の記事の受け売りだが、最新版のアップローダーに対応したコードを紹介しようと思う。
準備作業:オプションページを作る
ここはどんな管理ページでも同じだ。例えば、以下のようなコードで管理ページを作成
add_action( 'admin_menu', 'register_media_selector_settings_page' ); function register_media_selector_settings_page() { add_submenu_page( 'options-general.php', 'Media Selector', 'Media Selector', 'manage_options', 'media-selector', 'media_selector_settings_page_callback' ); }
フォームを作る
既存のフォームに組み込むのなら不要。
また、enctype=”multipart/form-data”などは必要ない。というのは、画像のアップロードはこのフォームを通して行われるわけではなく、WP内部のアップローダを通して行われるからだ。
function media_selector_settings_page_callback() { ?> <form method="post"> <div class="image-preview-wrapper"> <img id="image-preview" src="<?php echo wp_get_attachment_url( get_option("image_attachment_id"))?>" height="100"> </div> <input id="upload_image_button" class="button" type="button" value="<?php _e( 'Upload image' ); ?>"> <input id="image_attachment_id" name="image_attachment_id" type="hidden" value="<?php echo get_option("image_attachment_id"))?> > <input class="button-primary" name="submit_image_selector" type="submit" value="Save"></div> </form> <?php }
必要なjsなどをインクルード
ここが実にあっけない。wp_enqueue_media()
という関数一発で、必要なファイルをインクルードしてくれる。WPも便利になったものだ。
このコマンド内で何をしているか気になる人はここを見て欲しい。実に周到に準備をしている事が分かる。
結果、コードはこうなる。
function media_selector_settings_page_callback() { wp_enqueue_media(); //略 ?> }
アップローダと仲だちするスクリプトを読み込む
ここが一番要の部分だ。
実は今の時点ではあまりコードを読み解けていない。ただ、アップローダ内からIDをかっさらって来る部分は旧版と同じ仕組みだ。
add_action( 'admin_footer', 'media_selector_print_scripts' ); function media_selector_print_scripts() { $my_saved_attachment_post_id = get_option( 'media_selector_attachment_id', 0 ); ?> jQuery( document ).ready( function( $ ) { // Uploading files var file_frame; var wp_media_post_id = wp.media.model.settings.post.id; // Store the old id var set_to_post_id = <?php echo $my_saved_attachment_post_id; ?>; // Set this jQuery('#upload_image_button').on('click', function( event ){ event.preventDefault(); // If the media frame already exists, reopen it. if ( file_frame ) { // Set the post ID to what we want file_frame.uploader.uploader.param( 'post_id', set_to_post_id ); // Open frame file_frame.open(); return; } else { // Set the wp.media post id so the uploader grabs the ID we want when initialised wp.media.model.settings.post.id = set_to_post_id; } // Create the media frame. file_frame = wp.media.frames.file_frame = wp.media({ title: 'Select a image to upload', button: { text: 'Use this image', }, multiple: false // Set to true to allow multiple files to be selected }); // When an image is selected, run a callback. file_frame.on( 'select', function() { // We set multiple to false so only get one image from the uploader attachment = file_frame.state().get('selection').first().toJSON(); // Do something with attachment.id and/or attachment.url here $( '#image-preview' ).attr( 'src', attachment.url ).css( 'width', 'auto' ); $( '#image_attachment_id' ).val( attachment.id ); // Restore the main post ID wp.media.model.settings.post.id = wp_media_post_id; }); // Finally, open the modal file_frame.open(); }); // Restore the main ID when the add media button is pressed jQuery( 'a.add_media' ).on( 'click', function() { wp.media.model.settings.post.id = wp_media_post_id; }); });
読み解くにはアップローダjsの仕様を理解する必要がありそうだ。それにしても
// Finally, open the modal
file_frame.open();
と最後にモーダルを開いているのはなぜだろう??
画像IDを保存する部分を作成
フォームの目的はアップロードされた画像のID(もしくはURL)を保存する事なので、これを保存・表示する部分が必要になる。
普通のhiddenフィールドだ。
フォームの部分はこうなる。
function media_selector_settings_page_callback() { // Save attachment ID if ( isset( $_POST['submit_image_selector'] ) && isset( $_POST['image_attachment_id'] ) ) : update_option( 'media_selector_attachment_id', absint( $_POST['image_attachment_id'] ) ); endif; wp_enqueue_media(); ?> <form method="post"> <div class="image-preview-wrapper"> <img id="image-preview" src="<?php echo wp_get_attachment_url( get_option( " height="100"> <input id="upload_image_button" class="button" type="button" value="<?php _e( 'Upload image' ); ?>"> <input id="image_attachment_id" name="image_attachment_id" type="hidden" value="<?php echo get_option(image_attachment_id);?>"> <input class="button-primary" name="submit_image_selector" type="submit" value="Save"></div> </form> <? }
これで出来上がりだ。
これで上手く行かなかったら、原文を読みに行った方が良いかも知れない。
それでも分からなかったら、さらにその原文へ・・・という風に辿ってみましょう。
追記・備考
このサンプルは「シングル・インスタンス」専用です。つまり1ページに1個しか置けません。
マルチにするには幾つかの点を改造する必要があります。
それほど難しくは無いですが、要点は
- それぞれのオプション名をユニークにする(連番等)
- フォームのIDの部分はclassに変え、スクリプト中もそれに合わせる
- スクリプトの改造:押されたボタンthisを基準に充填するフォームを指定。jQueryを知っていれば誰でも出来ます
コメント