WEBOPIXEL

WordPressの画像カスタムフィールドにメディアIDで保存してプレビューする方法

Posted: 2013.07.05 / Category: WordPress 

WordPressでカスタムフィールドを実装するときは「WPAlchemy」というライブラリを使用しているのですが、これは画像のカスタムフィールドだと画像のURLがそのまま保存されてしまうため、キャプションや他のサイズの画像を取得する場合不便です。
そこでちょっと改造してメディアIDで保存する方法をご紹介します。

Sponsored Link

WordPress3.5
WPAlchemy 1.5.2
を使用します。

「WPAlchemy」の基本的な使い方

「WPAlchemy」の基本的な使い方は下記を参考にしてください。

WordPressでカスタムフィールドをお手軽に実装できるクラスライブラリ「WPAlchemy MetaBox」
WordPressで数を変更できてドラッグで並び替もできるカスタムフィールドを実装する方法

ダウンロード先が変わってました。

farinspace/wpalchemy

セットアップ

「wp-content」にダウンロードした「wpalchemy」を入れる。

現在使用してるテーマに「metaboxes」フォルダを作成して、下記の内容で「setup.php」「post-meta.php」というPHPファイルを作成する。

setup.php

    <?php
	include_once WP_CONTENT_DIR . '/wpalchemy/MetaBox.php';
	include_once WP_CONTENT_DIR . '/wpalchemy/MediaAccess.php';
	$wpalchemy_media_access = new WPAlchemy_MediaAccess();
	
	function add_meta_scripts() {
		wp_enqueue_style('wpalchemy-metabox', get_stylesheet_directory_uri() . '/metaboxes/meta.css');
		wp_enqueue_script('wpalchemy-metabox-js', get_stylesheet_directory_uri() . '/metaboxes/meta.js');
	}
	if (is_admin()) add_action( 'init', 'add_meta_scripts' );
	
	$custom_metabox = $simple_mb = new WPAlchemy_MetaBox(array
	(
		'id' => '_custom_meta',
		'title' => '画像',
		'types' => array('post'),
		'template' => get_stylesheet_directory() . '/metaboxes/post-meta.php'
	));
    

post-meta.php

    <?php global $wpalchemy_media_access; ?>
	<?php $mb->the_field('imgurl'); ?>
	<?php $wpalchemy_media_access->setGroupName('nn')->setInsertButtonLabel('追加'); ?>
	<div class="media-box">
		<div class="pre-image">
		<?php if ($mb->get_the_value()): ?>
			<?php echo wp_get_attachment_image($mb->get_the_value()); ?>
		<?php else: ?>
			<img src="<?php echo get_stylesheet_directory_uri() . '/metaboxes/no-image.png' ?>" />
		<?php endif; ?>
			<div class="img-edit">
				<a href="<?php echo $wpalchemy_media_access->getButtonLink(); ?>" class="mediabutton-nn thickbox {label:'追加'}">編集</a>
			</div>
		</div>
		<?php echo $wpalchemy_media_access->getField(array('name' => $mb->get_the_name(), 'value' => $mb->get_the_value())); ?>
	</div>
    

今回は管理画面でプレビューを表示したかったので「no-image.png」という空だったときの画像を用意しました。

「setup.php」で「meta.css」を読み込む設定をしたので、下記のように作成します。

meta.css

    #_custom_meta_metabox input[type='text'] {
		display: none;
	}
	#_custom_meta_metabox .pre-image {
		position: relative;
		width: 200px;
		border: solid 5px #ccc;
	}
	#_custom_meta_metabox .pre-image img {
		width: 100%;
		vertical-align: bottom;
		cursor: move;
	}
	#_custom_meta_metabox .pre-image .img-edit {
		background-color: #666;
		padding: 5px;
		position: absolute;
		right: 5px;
		bottom: 5px;
		color: #fff;
		display: none;
	}
	#_custom_meta_metabox .pre-image:hover .img-edit {
		display: block;
	}
	#_custom_meta_metabox .pre-image .img-edit a {
		color: #fff;
		text-decoration: none;
	}
	#_custom_meta_metabox .pre-image .img-edit a:hover {
		color: #eee;
	}
    

これで画像のカスタムフィールドが作成されます。

画像カスタムフィールド

マウスオーバーで編集ボタンが表示され、クリックするとメディアライブラリが立ち上がりますが、まだ画像の切り替えをすることはできません。

メディアIDで追加できるようにする

「MediaAccess.php」を編集して画像URLの部分をIDに変更してみます。
329行目あたりの「send_to_editor」の「if (wpalchemy_mediafield)」の中を下記のようにします。

MediaAccess.php

	if (wpalchemy_mediafield)
	{
		var src = html.match(/src=['|"](.*?)['|"] alt=/i);
		src = (src && src[1]) ? src[1] : '' ;

		//Media ID で取得
		var mediaId = html.match(/wp-image-[0-9]+/i);
		mediaId = mediaId[0].replace(/wp-image-/,"");
		wpalchemy_mediafield.val(mediaId);

		// プレビュー画像変更
		wpalchemy_mediafield.prev().find('img').attr('src',src);

		// reset insert button label
		setInsertButtonLabel(wpalchemy_insert_button_label);

		wpalchemy_mediafield = null;
	}
	

同時に、管理画面の画像も切り替わる処理をしています。
これで編集ボタンのあどメディアライブラリで追加を押すと、カスタムフィールドの画像が差し替わるはずです。

メディアIDから画像を表示する

無事保存できたと思うので、今度はテンプレートで表示してみます。
とりあえず画像を表示したいときは「single.php」だったら下記のようにします。

single.php

		$meta = get_post_meta(get_the_ID(), $custom_metabox->get_the_id(), TRUE);
		if (!empty($meta)) echo wp_get_attachment_image($meta['img_id']);
		

「wp_get_attachment_image」はデフォルトではサムネイルが表示されます。
他のサイズを表示したい場合引数に「medium」や「thumbnail」を指定します。
フルサイズの画像は「null」を指定します。

		wp_get_attachment_image($meta['img_id'], null);
		

画像パスだけを取得する

「wp_get_attachment_image」は画像表示までしてくれて便利な機能ですが、クラス名やサイズなどコントロールしたいときパスだけ取得できたらなと思うことがあります。
その場合には「wp_get_attachment_image_src」を使用します。

		$meta = get_post_meta(get_the_ID(), $custom_metabox->get_the_id(), TRUE);
    	print_r(wp_get_attachment_image_src($meta['img_id']));
		

結果は画像サイズを含めた配列で取得します。

あとは「wp_get_attachment_metadata」を使用するとすべての画像サイズをまとめて取得することができます。

		wp_get_attachment_metadata($meta['img_id'])
		

画像の情報を取得する

画像情報入力欄

「$wp_get_attachment_metadata」で「caption」の配列があるのでこれでキャプションも表示できそうなんですが、なぜか空になっているので「get_post」を使用します。

		$attachment = get_post($meta['img_id']);
        echo 'URL: '.esc_html($attachment->guid);
        echo 'キャプション: '.esc_html($attachment->post_excerpt);
        echo '画像の説明: '.esc_html($attachment->post_content);
        echo '代替テキスト: ' . get_post_meta($meta['img_id'], '_wp_attachment_image_alt', true);
		

基本「get_post」にメディアIDを指定すれば画像の情報は取得できますが、代替テキストだけ入っていないので「get_post_meta」を使用します。

可変の複数の画像カスタムフィールド

だいたい前回の通りですが、新たにプレビュー画像にあわせた形にちょこっと編集してみます。

まず「post-meta.php」を下記に置き換え。
画像の枚数を自由に変更できるようにするので、「追加」「削除」ボタンを追加してます。もっとスマートに書けそうですが、参考程度ということで!

post-meta.php

	<?php global $wpalchemy_media_access; ?>
	<div class="media-box">
		<ul id="meta-img-list">
			<?php while($mb->have_fields_and_multi('docs')): ?>
			<?php $mb->the_group_open(); ?>
			<?php $mb->the_field('img_id'); ?>
			<?php $wpalchemy_media_access->setGroupName('img-n'. $mb->get_the_index())->setInsertButtonLabel('追加'); ?>
			<li class="media-item">
				<div class="pre-image">
				<?php if ($mb->get_the_value()): ?>
					<?php echo wp_get_attachment_image($mb->get_the_value()); ?>
				<?php else: ?>
					<img src="<?php echo get_stylesheet_directory_uri() . '/metaboxes/no-image.png' ?>" />
				<?php endif; ?>
					<div class="img-edit">
						<a href="<?php echo $wpalchemy_media_access->getButtonLink(); ?>" class="<?php echo $wpalchemy_media_access->getButtonClass(); ?> {label:'追加'}">編集</a>
						|
						<a href="#" class="dodelete">削除</a>
					</div>
				</div>
				<?php echo $wpalchemy_media_access->getField(array('name' => $mb->get_the_name(), 'value' => $mb->get_the_value())); ?>
			</li>
			<?php $mb->the_group_close(); ?>
			<?php endwhile; ?>
		</ul>
		<p class="docopy-docs"><a href="#" class="button">項目の追加</a></p>
	</div>
	

cssもデザインの部分になるのでご自由に。

meta.css

	#_custom_meta_metabox #meta-img-list li {
		float: left;
		margin-right: 7px;
		margin-bottom: 7px;
	}
	#_custom_meta_metabox .docopy-docs {
		clear: both;
	}
	

あとは画像を並び替えするためのjsを設置して完成。

meta.js

	(function($) {
		$(function() {
			if($('#meta-img-list').size() > 0){
				$('#meta-img-list').sortable({
					items: '.media-item'
				});
			}
		});
	})(jQuery); 
	

完成イメージ。

画像情報入力欄

複数の画像をテンプレートで出力

管理画面でループさせたので多次元配列で返ってきます。
メディアIDだけの配列を作ってから「get_posts」とかで表示してます。

single.php

		<?php
		$meta = get_post_meta(get_the_ID(), $custom_metabox->get_the_id(), TRUE);
		if ($meta):
			$media_ids = array();
			foreach( $meta['docs'] as $value ) array_push($media_ids, intval($value['img_id']));
			$media_args = array(
				'post_type' => 'attachment',
				'post_mime_type' => 'image',
				'post__in' => $media_ids,
				'orderby' => 'post__in'
			);
			$attachments = get_posts($media_args);
			?>
			<div class="img-list cf">
				<?php foreach( $attachments as $key => $value ): ?>
					<div><img src="<?php echo esc_attr($value->guid) ?>" alt="<?php echo esc_attr($value->post_excerpt) ?>"/><br /><?php echo nl2br(esc_html($value->post_excerpt)) ?></div>
				<?php endforeach; ?>
			</div>
		<?php endif; ?>
		

というわけでメディタIDで保存しておけば、キャプションとか他の画像サイズとかの取得が簡単にできるようになります。(URLからメディアIDを取得する方法もあった気がしますが)
カスタムフィールドに関しては他のプラグインならもとからIDのタイプもあるとおもいます。

参考サイト:WordPress › Support » Get Title, Alt, or Caption from Media Library and insert into theme
写真素材:PAKUTASO/ぱくたそ

COMMENTS

困りました 2013-12-24 12:05 

始めまして。質問をさせていただきたいのですが、
メディアIDで保存した画像をテンプレートで表示させようとすると下記エラーがでて表示がされません。

Warning: Illegal string offset ‘img_id’

投稿画面で画像が切り替わり、IDで切り替わり保存がされるところまでは大丈夫なのですが…。

お忙しいところ大変申し訳ありませんが、解決方法等ありましたらご教授下さい。
よろしくお願いいたします。

困りました 2013-12-24 14:21 

すみません。自己解決しました。
追加でご質問なのですが、複数追加する場合はどうしたらいいでしょうか?

複数というのは画像をグループ化させるのではなく、別々の項目にするという意味です。
(説明下手すみません。)

the_field(‘imgurl’); ?>

the_field(‘imgurl2’); ?>

みたいな感じで別々にすればいけるかなと思ったんですが、編集を押してメディアアップローダーが立ち上がって画像を選択し、追加ボタンを押してもメディアアップローダーが表示されたまま固まってしまいます。

お忙しいところ大変申し訳ありませんが、よろしくお願いいたします。

webOpixel 2013-12-27 10:04 

すみません。複数のフィールドは考えてなかったですね。
jQueryの部分がidで指定しているので、その部分も2つ作るとかclassに置き換えないとダメかもしれません。

keith69 2015-02-19 03:23 

始めまして。いつも参考にさせていただいております。
WordPressのいくつかのバージョンで試してみたのですが、WordPress 3.5.2までは動作を確認できたのですが、WordPress 3.5.3以降は上記の方法では画像がフィールドにセットされないようです。

現象としては、アップローダーから画像を挿入する時点で画面が白くなり、フィールドに値もセットされない状態です。
「MediaAccess.php」の部分がうまく動いてないのかと、色々試してみても自力では解決出来ませんでした。

かなり重宝していた機能なので、なにか解決方法があればと質問させていただきます。

よろしくお願いいたします。

hirapi 2015-10-07 20:43 

はじめまして。
私も「keith69」さんとまったく同じです。調べているうちにこちらに辿り着きました。
何か解決方法があれば教えていただきたいと思い、私からもお願いさせてください。

webOpixel 2015-10-10 08:50 

このライブラリ自体の更新が止まっていることもあって、最近は他のプラグインを使用することをお勧めします。
http://pods.io/
は簡単に画像のリピート&並び替えもできますよ。

http://www.webopixel.net/wordpress/950.html

LEAVE A REPLY

コードを書く場合は<pre>で囲んでください。