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」関数を使って、リクエストが有効かテストをおこない、テーブルへ保存します。
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で設定した値を取得する方法」で紹介しているのでチェックしてみてください。
おつかれさまでした。