wordpress 特定のページにだけメタボックスを追加する

2013年6月13日

編集画面にメタボックスを使って独自のカスタムフィールドの入力項目を追加することができるが、add_meta_box() の第4パラメータでは、ページの種類しか指定できず、特定の固定ページのみに表示することができない。

add_meta_box($id, $title, $callback, $page, $context, $priority, $callback_args )
パラメータ
$id (必須):メタボックスの ID(メタボックスである div タグの id 属性値)
$title (必須):メタボックスのタイトル(画面上に表示される)
$callback (必須): メタボックスの内容を表示する( HTML 出力する)関数名
$page (必須):メタボックスの表示先となるページの種類を指定 (post, page, link, dashboard, カスタムポストタイプ名)。
$context (オプション):編集画面での表示場所 (normal, advanced または side) 。
$priority (オプション):ボックスが表示される優先度 (high, core, default, low) 。
$callback_args (オプション):表示用関数のパラメータを指定。
戻り値: なし。
利用可能箇所:add_meta_boxes アクション(add_action)で使用

特定のページにだけメタボックスを追加

参考にしたサイト
How to Limit the Display of a WordPress Meta Box
  • 「投稿の編集」や「固定ページの編集」をクリックした場合は、$_GET[‘post’] で ID を取得。
  • 「更新」や「公開」をクリックした場合には、$_POST[‘post_ID’] で ID を取得。
  • isset() でリクエスト変数($_POST, $_GET)が設定されているかを確認。(ダッシュボードでの「Notice」エラーの回避)
  • 特定のページのIDを get_id_by_post_name(スラッグ) で取得し、それを現在のページと比較し、合致すれば add_meta_box() を実行。
  • get_id_by_post_name()を使用しない場合は、直接 ID を記述する。(例:$page_id = ’84’;)
  • 特定のテンプレートを使っているページに追加するには、get_post_meta($post_id,’_wp_page_template’,TRUE)で適用しているテンプレートを取得して、それを比較。
  • add_action(‘add_meta_boxes’, ~) で適用。
function add_my_box() {
  $post_id = '';
  if(isset($_GET['post']) || isset($_POST['post_ID'])) {
    $post_id = $_GET['post'] ? $_GET['post'] : $_POST['post_ID'] ;
  }

  $page_id = get_id_by_post_name('news');  //スラッグが「news」の固定ページの ID

  // ID を比較して、合致すればメタボックスを追加
  if ($post_id == $page_id)
  {
    add_meta_box('my_all_meta_1', 'My Custom Meta Box 1', 'my_meta_setup_1', 'page', 'normal', 'high');
  }

  //適用しているテンプレートを取得
  $template_file = get_post_meta($post_id,'_wp_page_template',TRUE);

  // テンプレートを比較して、合致すればメタボックスを追加
  if ($template_file == 'home.php')
  {
    add_meta_box('my_meta_2', 'My Custom Meta Box 2', 'my_meta_setup_2', 'page', 'normal', 'high');
  }

}
add_action('add_meta_boxes', 'add_my_box');

//投稿スラッグから投稿IDを取得する関数の定義
function get_id_by_post_name($post_name)
{
  global $wpdb;
  $id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_name = '".$post_name."'");
  return esc_html($id);
}

保存の処理を指定する際の注意

フィールドに入力した情報は、update_post_meta() を利用してカスタムフィールドのデータとしてデータベースに保存するが、その際には以下のような条件を使って保存する。(「更新」や「公開」をクリックした場合には、$_POST[‘post_ID’] で ID を取得して判定)

function my_box_save($post_id) {
  global $post;
  $my_nonce = isset($_POST['my_nonce']) ? $_POST['my_nonce'] : null;
  if(!wp_verify_nonce($my_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; }
  //get_id_by_post_name(上記で独自に定義した関数)を使用しない場合は、直接 ID を記述する。
  if ($_POST['post_ID'] == get_id_by_post_name('news')){
      update_post_meta($post->ID, 'posts_count', $_POST['posts_count']);
  }
}
add_action('save_post', 'my_box_save');

入力フィールドの追加など独自のカスタムフィールドの入力項目の追加についての詳細は「編集画面にメタボックスを使って独自のカスタムフィールドの入力項目を追加」を参照。

以下は、スラッグが「news」の固定ページにのみ独自のカスタムフィールドを追加する例。

//メタボックスの作成
function add_my_box() {
  $post_id = '';
  if(isset($_GET['post']) || isset($_POST['post_ID'])) {
    $post_id = $_GET['post'] ? $_GET['post'] : $_POST['post_ID'] ;
  }

  if ($post_id == get_id_by_post_name('news')){
    add_meta_box('news', 'News', 'news_form', 'page', 'normal', 'high');
  }
}
add_action('add_meta_boxes', 'add_my_box');

//メタボックスに入力フィールドの追加
function news_form() {
  global $post;
  wp_nonce_field(wp_create_nonce(__FILE__), 'my_nonce');
?>
  <div id="news">
    <p>最新情報のページで、1ページ当たりに表示する件数を入力してください。</p>
    <p><label>表示する件数:半角英数字で入力<br />
    <input type="text" name="posts_count" value="<?php echo esc_html(get_post_meta($post->ID, 'posts_count', true)); ?>"  style="width:80%" />
    </label></p> 
  </div>
<?php
}

//保存の処理を指定
function my_box_save($post_id) {
  global $post;
  $my_nonce = isset($_POST['my_nonce']) ? $_POST['my_nonce'] : null;
  if(!wp_verify_nonce($my_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; }
  //get_id_by_post_name(独自に定義した関数)を使用しない場合は、直接 ID を記述する。
  if ($_POST['post_ID'] == get_id_by_post_name('news')){
      update_post_meta($post->ID, 'posts_count', $_POST['posts_count']);
  }
}
add_action('save_post', 'my_box_save');

//投稿スラッグから投稿IDを取得する関数の定義
function get_id_by_post_name($post_name)
{
  global $wpdb;
  $id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_name = '".$post_name."'");
  return esc_html($id);
}