wordpress投稿の編集画面にカスタムフィールドを追加

よく忘れるのでまとめ。
以下の方法で,カスタムフィールドを投稿およびカスタム投稿へ追加できる。

add_meta_box()関数をadmin_menuにフック,
add_post_meta()関数,delete_post_meta()関数,update_post_meta()関数をsave_postにフック,wp_enqueue_script()関数をadmin_initにフックする。

(テンプレートディレクトリ)/function.php

/**
 * 投稿の編集画面にカスタムフィールドを追加する
 */
function add_posttype_customfields() {
	 
	// 投稿編集画面にメタボックス追加
	add_meta_box(
		'CustomDiv',	// メタボックスのHTML-ID
		'その他の項目',   // メタボックスのラベル
		'html_my_custom',   // HTML出力コールバック
		'post', // 追加する投稿タイプ名(カスタム投稿も可)
		'normal',   // 配置場所(normal, advanced, side)
		'low'   // 順序(high, core, default, low)
	);
}
add_action('admin_menu', 'add_posttype_customfields');
/**
 * HTML出力コールバック
 */
function html_my_custom($post) {
	 
	// nonce設定
	wp_nonce_field(wp_create_nonce(__FILE__), 'custom_fields_nonce');
	 
	// HTML出力(text)
	$value = get_post_meta(
		$post->ID,   // 投稿ID
		'link', // カスタムフィールドキー
		true	// true:単一文字列, false:複数配列
	);
	echo '
'; echo '
'; echo ''; echo '
'; echo '
'; echo ''; echo '

リンク先URLを入力してください。

'; echo '
'; echo '
'; // HTML出力(textarea) $value = get_post_meta( $post->ID, // 投稿ID 'memo', // カスタムフィールドキー true // true:単一文字列, false:複数配列 ); echo '
'; echo '
'; echo ''; echo '
'; echo '
'; echo ''; echo '

リンク先のメモを入力してください。

'; echo '
'; echo '
'; // HTML出力(wysiwyg) $value = get_post_meta( $post->ID, // 投稿ID 'note', // カスタムフィールドキー true // true:単一文字列, false:複数配列 ); echo '
'; echo '
'; echo ''; echo '
'; echo '
'; wp_editor($value, 'note'); echo '
'; echo '
'; // HTML出力(checkbox単数) $value = get_post_meta( $post->ID, // 投稿ID 'popup', // カスタムフィールドキー true // true:単一文字列, false:複数配列 ); echo '
'; echo '
'; echo 'リンク後のウィンドウ'; echo '
'; echo '
'; echo ''; echo ''; echo '
'; echo '
'; // HTML出力(checkbox複数) $value = get_post_meta( $post->ID, // 投稿ID 'browser', // カスタムフィールドキー false // true:単一文字列, false:複数配列 ); $list = array( 1 => 'IE', 2 => 'Chrome', 3 => 'Safari', 4 => 'FireFox', 5 => 'Opera' ); echo '
'; echo '
'; echo '対応ブラウザ'; echo '
'; echo '
'; echo '
    '; foreach ($list as $_id => $_name) { echo '
  • '; echo ''; echo '
  • '; } echo '
'; echo '
'; echo '
'; // HTML出力(radio) $value = get_post_meta( $post->ID, // 投稿ID 'os', // カスタムフィールドキー true // true:単一文字列, false:複数配列 ); $list = array( 1 => 'windows', 2 => 'mac', 3 => 'linux', ); echo '
'; echo '
'; echo '対応OS'; echo '
'; echo '
'; echo ''; echo '
    '; foreach ($list as $_id => $_name) { echo '
  • '; echo ''; echo '
  • '; } echo '
'; echo '
'; echo '
'; // HTML出力(select) $value = get_post_meta( $post->ID, // 投稿ID 'pagetype', // カスタムフィールドキー true // true:単一文字列, false:複数配列 ); $list = array( 0 => '-----', 1 => 'news', 2 => 'blog', 3 => 'shop', 3 => 'business', ); echo '
'; echo '
'; echo ''; echo '
'; echo '
'; echo ''; echo '
'; echo '
'; // HTML出力(file) $value = get_post_meta( $post->ID, // 投稿ID 'pdf_url', // カスタムフィールドキー true // true:単一文字列, false:複数配列 ); echo '
'; echo '
'; echo ''; echo '
'; echo '
'; echo ''; echo ''; echo ''; echo '
'; echo '
'; } /** * カスタムフィールドの保存処理 */ function save_posttype_customfields($post_id) { // nonceが一致しない場合は終了 if (!wp_verify_nonce( @$_POST['custom_fields_nonce'], wp_create_nonce(__FILE__) )) { return $post_id; } // 自動保存の場合は終了 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; } // 投稿権限がない場合は終了 if (!current_user_can('edit_post', $post_id)) { return $post_id; } // 保存処理 switch (get_post_type($post_id)) { case 'post': // クイック編集の場合 if (@$_POST['quick_edit']) { $post_keys = array( // true:単一文字列, false:複数配列 'link' => true, 'popup' => true, ); // 普通の編集の場合 } else { $post_keys = array( // true:単一文字列, false:複数配列 'link' => true, 'memo' => true, 'popup' => true, 'browser' => false, 'os' => true, 'pagetype' => true, 'pdf_url' => true, ); } foreach (@$post_keys as $post_key => $unique) { // 単数 if ($unique) { update_post_meta( $post_id, // 投稿ID $post_key, // カスタムフィールドキー @$_POST[$post_key] // 値 ); // 複数 } else { $input_vals = (array)@$_POST[$post_key]; $save_vals = get_post_meta( $post_id, // 投稿ID $post_key, // カスタムフィールドキー false // true:単一文字列, false:複数配列 ); foreach (@$input_vals as $input_val) { if (!in_array($input_val, $save_vals)) { add_post_meta( $post_id, // 投稿ID $post_key, // カスタムフィールドキー $input_val, // 値 false // true:単一文字列, false:複数配列 ); } } foreach ($save_vals as $save_val) { if (!in_array($save_val, $input_vals)) { delete_post_meta( $post_id, // 投稿ID $post_key, // カスタムフィールドキー $save_val // 値 ); } } } } break; default: } } add_action('save_post', 'save_posttype_customfields'); /** * カスタムフィールドでメディアアップローダーを使う */ function js_posttype_customfields() { // カスタムJS wp_enqueue_script( 'customfield_uploader', // ハンドル get_bloginfo('template_url') .'/posttype_customfield_uploader.js', // JSファイル array('jquery'), // 先にロードされるべきハンドル filemtime(dirname( __FILE__ ).'/posttype_customfield_uploader.js'), // バージョン // (※数字を指定してもよいが更新日時を取得すると楽) false // true: 直前, false: 内 ); } add_action('admin_init', 'js_posttype_customfields'); /** * wp.mediaを使用する */ function load_wp_media_files() { wp_enqueue_media(); } add_action('admin_enqueue_scripts', 'load_wp_media_files');

(テンプレートディレクトリ)/posttype_customfield_uploader.js

/**
 * カスタムフィールドでメディアアップローダを使用する
 */
jQuery(function($){
	
	// 初期準備
	var WpMedia; // アップローダ
	
	// ファイル追加イベント
	$('.file_add').on('click', function(e){
		
		// デフォルトイベントの制御
		e.preventDefault();	// クリックイベントストップ
		e.stopPropagation();	// 親要素へのイベント伝搬ストップ
		
		// 対象取得
		var match = $(this).attr('class').match(/name-(\S+)/);
		var $target = match ? $('input[name='+match[1]+']') : null;
		
		// アップローダがある場合起動
		if (WpMedia) {
			WpMedia.open();
			return;
		}
		
		// アップローダ作成
		WpMedia = wp.media({
			title: 'メディアライブラリ',
			button: {
				text: '選択'
			},
			multiple: false	// true: 複数, false: 単数
		}); // wp は wordpressが用意
		WpMedia.on('select', function(){
			var media = WpMedia.state().get('selection');
			media.each(function(file){
				if ($target) {
					$target.val(file.toJSON().url);
				}
			});
		});
		
		// 起動
		WpMedia.open();
});
	
// ファイル削除イベント
$('.file_del').on('click', function(e){
		
	// デフォルトイベントの制御
	e.preventDefault();	// クリックイベントストップ
		e.stopPropagation();	// 親要素へのイベント伝搬ストップ
		
		// 対象取得
		var match = $(this).attr('class').match(/name-(\S+)/);
		var $target = match ? $('input[name='+match[1]+']') : null;
		
		// 削除実行
		if ($target) {
			$target.val();
		}
		
	});
	
});