WordPress 独自カスタムフィールドをfunctions.phpに記述する方法

WordPressで独自のカスタムフィールドをfunctions.phpに記述する方法です。

WordPress 独自カスタムフィールドをfunctions.phpに記述する方法

カスタムフィールドを利用すれば、タイトル・本文以外の入力フィールドが追加できます。これから紹介する方法はプラグインなしで、PHPを書いてカスタムフィールドを追加しようというものです。ちょっと玄人向けの記事になりますかね。

カスタムフィールドを便利に使えるようにできるプラグインはたくさんあります。有名なのは「Advanced Custom Fields」ですね。筆者もよく使うプラグインです。

今回、この記事を書こうと思ったきっかけは、「All in One SEO」というプラグインを停止しようと思ったからです。「All in One SEO」は、とても高機能で優秀なプラグインではありますが、正直、バージョン4.0.0以降は使いにくくなったし、脆弱性も確認されたし、謎のログがテーブルに膨大に蓄積されるし、なんといっても遅いし。ならば停止して、独自実装してしまおうと考えました。なので「タイトル(title)」「説明(description)」「キーワード(keywords)」のカスタムフィールドで追加する方法がメインとなります。プラグインは使いません。

ここでは WordPressで独自のカスタムフィールドをfunctions.phpに記述する方法 を紹介します。


完成イメージ

完成イメージは下記のとおりです。SEO設定というボックス内に、「タイトル(title)」「説明(description)」「キーワード(keywords)」のカスタムフィールドが追加されます。

カスタムフィールド追加後の完成イメージ

見ての通り、デザインは「All in One SEO」プラグインを参考にしています。

カスタムフィールドを追加する

今回は、固定ページと投稿ページにカスタムフィールドの入力を追加します。

フィールドの定義

各フィールドの定義は下記のようになります。

  • タイトル:my_seo_title テキストボックス
  • 説明:my_seo_description テキストエリア
  • キーワード:my_seo_keywords テキストボックス

functions.php

下記のコードを「function.php」へコピペします。

/**
 * 投稿と固定ページにカスタムフィールドを追加
 */
add_action( 'admin_menu', 'add_my_custom_field' );
function add_my_custom_field() {
  $screens = array( 'post', 'page' );
  foreach ( $screens as $screen ) {
    add_meta_box( 'my_seo', 'SEO設定', 'add_my_seo_fields', $screen, 'normal' );
  }
}
// カスタムフィールドのHTMLを追加する時の処理
function add_my_seo_fields() {
  global $post;
  $title_name = "my_seo_title";
  $description_name = "my_seo_description";
  $keywords_name = "my_seo_keywords";
  // nonceの追加
  wp_nonce_field( 'action-'.$title_name, 'nonce-'.$title_name );
  wp_nonce_field( 'action-'.$description_name, 'nonce-'.$description_name );
  wp_nonce_field( 'action-'.$keywords_name, 'nonce-'.$keywords_name );
  // 値を取得
  $title_value = get_post_meta($post->ID, $title_name, true);
  $description_value = get_post_meta($post->ID, $description_name, true);
  $keywords_value = get_post_meta($post->ID, $keywords_name, true);
  // html作成
  $fields  = '<div class="myseo-content">';
  $fields .= ' <div class="myseo-settings-row myseo-row">';
  $fields .= '  <div class="myseo-col col-xs-12 col-md-3 text-xs-left">';
  $fields .= '   <div class="settings-name">';
  $fields .= '    <div class="name align">タイトル</div>';
  $fields .= '   </div>';
  $fields .= '  </div>';
  $fields .= '  <div class="myseo-col col-xs-12 col-md-9 text-xs-left">';
  $fields .= '   <div class="settings-content">';
  $fields .= '    <div class="myseo-input">';
  $fields .= '     <input type="text" class="medium" name="'.$title_name.'" value="'.$title_value.'">';
  $fields .= '    </div>';
  $fields .= '    <div class="myseo-description">ほとんどの検索エンジンのタイトルは最大 60 文字です。</div>';
  $fields .= '   </div>';
  $fields .= '  </div>';
  $fields .= ' </div>';
  $fields .= ' <div class="myseo-settings-row myseo-row">';
  $fields .= '  <div class="myseo-col col-xs-12 col-md-3 text-xs-left">';
  $fields .= '   <div class="settings-name">';
  $fields .= '    <div class="name align">説明</div>';
  $fields .= '   </div>';
  $fields .= '  </div>';
  $fields .= '  <div class="myseo-col col-xs-12 col-md-9 text-xs-left">';
  $fields .= '   <div class="settings-content">';
  $fields .= '    <div class="myseo-input">';
  $fields .= '     <textarea class="myseo-textarea" rows="5" cols="8" name="'.$description_name.'">'.$description_value.'</textarea>';
  $fields .= '    </div>';
  $fields .= '    <div class="myseo-description">ほとんどの検索エンジンの説明は最大 160 文字です。</div>';
  $fields .= '   </div>';
  $fields .= '  </div>';
  $fields .= ' </div>';
  $fields .= ' <div class="myseo-settings-row myseo-row">';
  $fields .= '  <div class="myseo-col col-xs-12 col-md-3 text-xs-left">';
  $fields .= '   <div class="settings-name">';
  $fields .= '    <div class="name align">キーワード</div>';
  $fields .= '   </div>';
  $fields .= '  </div>';
  $fields .= '  <div class="myseo-col col-xs-12 col-md-9 text-xs-left">';
  $fields .= '   <div class="settings-content">';
  $fields .= '    <div class="myseo-input">';
  $fields .= '     <input type="text" class="medium" name="'.$keywords_name.'" value="'.$keywords_value.'" placeholder="ホームページ,制作,墨田区,Webデザイン">';
  $fields .= '    </div>';
  $fields .= '    <div class="myseo-description">カンマ区切りで入力します。</div>';
  $fields .= '   </div>';
  $fields .= '  </div>';
  $fields .= ' </div>';
  $fields .= '</div>';
  echo $fields;
}
// カスタムフィールドの値を保存
add_action('save_post', 'save_seo_fields');
function save_seo_fields( $post_id ) {
  $fields = array('my_seo_title', 'my_seo_description', 'my_seo_keywords' );
  foreach( $fields as $field ) {
    if ( isset( $_POST['nonce-'.$field] ) && $_POST['nonce-'.$field] ) {
      // リクエストが有効な nonce を持っているかチェック
      if ( check_admin_referer( 'action-'.$field, 'nonce-'.$field ) ) {
        if ( isset( $_POST[$field] ) && $_POST[$field] )
          update_post_meta( $post_id, $field, $_POST[$field] );
        else
          delete_post_meta( $post_id, $field, get_post_meta( $post_id, $field, true ) );
      }
    }
  }
}
/**
 * 管理画面にCSSファイルを読み込む
 */
add_action( 'admin_enqueue_scripts', 'my_admin_style' );
function my_admin_style(){
  wp_enqueue_style( 'my_admin_style', get_template_directory_uri().'/css/seo.css' );
}

簡単に説明すると「add_meta_box」関数を使って独自のカスタムフィールドの追加し、callback関数でhtmlを出力しています。

add_meta_box( $id, $title, $callback, $screen, $context, $priority, $callback_args );

途中、「wp nonce field」関数にて、hiddenを追加する記述をしています。これは、不正なリクエストではないことを認証するために使われます。

wp_nonce_field( $action, $name, $referer, $echo );

保存前には「check_admin_referer」関数を使って、リクエストが有効かテストをおこない、テーブルへ保存します。

check_admin_referer( $action, $query_arg );

seo.css

下記のコードをCSSファイルに記述します。場所はどこでも構いません。PHP側の「my_admin_style」関数でパスを調整してください。

今回はテーマのルートにcssフォルダを作って、その中に「seo.css」というファイルを新規に作っています。

/*
 * 管理画面カスタムフィールド用
 */
.myseo-content {
  background: #fff;
  border-top: 0;
  padding: 15px;
}
.myseo-settings-row {
  margin-bottom: 16px;
  padding-bottom: 16px;
}
.myseo-row {
  box-sizing: border-box;
  display: flex;
  flex: 0 1 auto;
  flex-direction: row;
  flex-wrap: wrap;
  margin-right: -0.5rem;
  margin-left: -0.5rem;
}
.myseo-settings-row {
  margin-bottom: 22px;
  padding-bottom: 16px;
  border-bottom: 1px solid #E8E8EB;
}
.myseo-settings-row:last-of-type {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: 0;
}
@media only screen and (min-width: 912px) {
  .myseo-col.col-md, .myseo-col.col-md-1, .myseo-col.col-md-2, .myseo-col.col-md-3, .myseo-col.col-md-4, .myseo-col.col-md-5, .myseo-col.col-md-6, .myseo-col.col-md-7, .myseo-col.col-md-8, .myseo-col.col-md-9, .myseo-col.col-md-10, .myseo-col.col-md-11, .myseo-col.col-md-12, .myseo-col.col-md-offset-0, .myseo-col.col-md-offset-1, .myseo-col.col-md-offset-2, .myseo-col.col-md-offset-3, .myseo-col.col-md-offset-4, .myseo-col.col-md-offset-5, .myseo-col.col-md-offset-6, .myseo-col.col-md-offset-7, .myseo-col.col-md-offset-8, .myseo-col.col-md-offset-9, .myseo-col.col-md-offset-10, .myseo-col.col-md-offset-11, .myseo-col.col-md-offset-12 {
    box-sizing: border-box;
    flex: 0 0 auto;
    padding: 0.5rem;
  }
}
@media only screen and (min-width: 912px) {
  .myseo-col.col-md-3 {
    flex-basis: 25%;
    max-width: 25%;
  }
}
.myseo-col.text-xs-left {
  text-align: left !important;
  justify-content: flex-start;
}
.myseo-settings-row .settings-name {
  color: #141B38;
}
.myseo-settings-row .settings-name .name.align {
  line-height: 40px;
}
.myseo-settings-row .settings-name .name {
  font-weight: 600;
  font-size: 14px;
  display: flex;
  align-items: center;
}
@media only screen and (min-width: 912px) {
  .myseo-col.col-md-9 {
    flex-basis: 75%;
    max-width: 75%;
  }
}
.myseo-settings-row .settings-content {
  font-size: 14px;
}
.myseo-description {
  font-size: 12px;
  line-height: 1.8;
  margin: 8px 0 0;
  color: #141B38;
}
.myseo-input {
  position: relative;
  width: 100%;
}
.myseo-input input.medium {
  height: 40px;
  padding: 12px;
  font-size: 14px;
}
.myseo-input input {
  height: 48px;
  width: 100%;
  background-color: #fff;
  border: 1px solid #D0D1D7;
  border-radius: 3px;
  padding: 15px;
  font-size: 16px;
  position: relative;
  overflow: hidden;
  margin: 0;
}
.myseo-input textarea {
  min-height: 36px;
  width: 100%;
  background-color: #fff;
  border: 1px solid #D0D1D7;
  border-radius: 4px;
  padding: 10px;
  font-size: 14px;
  margin: 0;
}

カスタムフィールドを表示する

カスタムフィールドに値を入力したら、ページ上に表示します。

投稿ページで保存した内容

記入した内容はこんな感じです。

投稿ページで保存した内容

header.php

header.phpへ下記を追記します。既存のtitleタグや、descriptionとkeywordsのmetaタグはコメントアウトしてください。

<?php if( is_page() || is_single() ) { //固定ページ・シングルページ ?>
  <title><?php echo get_post_meta($post->ID, 'my_seo_title', true); ?></title>
  <meta name="description" content="<?php echo get_post_meta($post->ID, 'my_seo_description', true); ?>">
  <meta name="keywords" content="<?php echo get_post_meta($post->ID, 'my_seo_keywords', true); ?>">
<?php } else { //トップページ・その他 ?>
  <title><?php wp_title('|',true,'right'); bloginfo('name'); ?></title>
  <meta name="description" content="<?php bloginfo('description'); ?>">
  <meta name="keywords" content="ホームページ,制作,墨田区,Webデザイン">
<?php } ?>

表示の確認

ふむ、開発者ツールで出力が確認できました。

開発者ツールで出力が確認できた

まとめ

WordPressで独自のカスタムフィールドをfunctions.phpに記述する方法を紹介しました。

これで「All in One SEO」で使っていたフィールドは用意できました。記事数が多いので、すでに「All in One SEO」のフィールドに設定したタイトル・説明・キーワードを、どう移行するかが課題ですかね。これから検討します。

追記:All in one SEOからの移行

すでに「All in One SEO」のフィールドに設定したタイトル・説明・キーワードを、どう移行するかって課題についての追記です。

結局、データ移行ではなく独自SEO設定がなくてAll in one SEOに設定があれば表示するという方法をとることにしました。

funciton.phpのadd_my_seo_fields関数で「値を取得」ってやっているところを下記のコードに書き換えれば完了です。

// 独自SEO設定がなく、All in one SEOに設定があれば表示する
$title_value = ( empty(get_post_meta($post->ID, $title_name, true)) ) ? get_post_meta($post->ID, '_aioseop_title', true) : get_post_meta($post->ID, $title_name, true);
$description_value = ( empty(get_post_meta($post->ID, $description_name, true)) ) ? get_post_meta($post->ID, '_aioseop_description', true) : get_post_meta($post->ID, $description_name, true);
$keywords_value = ( empty(get_post_meta($post->ID, $keywords_name, true)) ) ? get_post_meta($post->ID, '_aioseop_keywords', true) : get_post_meta($post->ID, $keywords_name, true);

3.0系は「aioseop_」、4.0系は「aioseo_」にて取得できる。

詳しくは「All in One SEOで設定した値を取得する方法」で紹介しているのでチェックしてみてください。

おつかれさまでした。

この記事がお役に立ちましたら シェア をお願いいたします。